# Vulnerable: Reflected data in HttpResponse
from django.http import HttpResponse, JsonResponse
from django.views import View
from django.shortcuts import render
import json
# Dangerous: Direct reflection of user input
class SearchView(View):
def get(self, request):
query = request.GET.get('q', '')
# CRITICAL: User input reflected without escaping
html_content = f"""
Search Results
You searched for: {query}
No results found
"""
return HttpResponse(html_content)
# Another dangerous pattern
def error_page(request):
error_msg = request.GET.get('error', '')
user_name = request.GET.get('user', '')
# Dangerous: Multiple user inputs in response
response_html = f"""
Error
Error for user: {user_name}
{error_msg}
"""
return HttpResponse(response_html)
# JSON response vulnerability
def api_response(request):
message = request.POST.get('message', '')
callback = request.GET.get('callback', '')
# Dangerous: JSONP callback injection
if callback:
response_content = f"{callback}({{'message': '{message}'}});"
return HttpResponse(response_content, content_type='application/javascript')
# Also dangerous: Unescaped message in JSON
return JsonResponse({'message': message})
# Form processing with reflection
def process_form(request):
if request.method == 'POST':
name = request.POST.get('name', '')
email = request.POST.get('email', '')
comment = request.POST.get('comment', '')
# Dangerous: Form data reflected in response
html = f"""
Form Submitted Successfully
Name: {name}
Email: {email}
Comment: {comment}
Go Back
"""
return HttpResponse(html)
# Debug information exposure
def debug_info(request):
debug_param = request.GET.get('debug', '')
user_agent = request.META.get('HTTP_USER_AGENT', '')
# Dangerous: Debug info with user-controlled data
debug_html = f"""
Debug Information
Debug Parameter: {debug_param}
User Agent: {user_agent}
"""
return HttpResponse(debug_html)
# Redirect with reflected data
def custom_redirect(request):
redirect_url = request.GET.get('next', '/')
message = request.GET.get('msg', '')
# Dangerous: Message reflected in redirect page
redirect_html = f"""
Redirecting...
{message}
You will be redirected to: {redirect_url}
"""
return HttpResponse(redirect_html)
# Secure: Safe handling of user data in responses
from django.http import HttpResponse, JsonResponse
from django.views import View
from django.shortcuts import render
from django.template.loader import render_to_string
from django.utils.html import escape, format_html
from django.core.exceptions import ValidationError
import json
import re
# Safe: Using Django templates with auto-escaping
class SafeSearchView(View):
def get(self, request):
query = request.GET.get('q', '')
try:
# Validate query
validated_query = self.validate_search_query(query)
# Safe: Django template with auto-escaping
context = {
'query': validated_query,
'results': [] # Would contain actual search results
}
return render(request, 'search_results.html', context)
except ValidationError as e:
return JsonResponse({'error': str(e)}, status=400)
def validate_search_query(self, query):
# Validate query length
if len(query) > 100:
raise ValidationError('Search query too long')
# Basic XSS prevention
if '<' in query or '>' in query or 'script' in query.lower():
raise ValidationError('Invalid characters in search query')
return query.strip()
# Safe: Error handling with proper escaping
def safe_error_page(request):
error_msg = request.GET.get('error', '')
user_name = request.GET.get('user', '')
try:
# Validate inputs
validated_error = validate_error_message(error_msg)
validated_user = validate_username(user_name)
# Safe: Using Django template
context = {
'error_message': validated_error,
'user_name': validated_user
}
return render(request, 'error_page.html', context)
except ValidationError:
# Safe fallback
return render(request, 'generic_error.html')
def validate_error_message(message):
if not message:
return 'An error occurred'
# Limit length
if len(message) > 200:
message = message[:200]
# Remove potentially dangerous content
message = re.sub(r'[<>"\']', '', message)
return message
def validate_username(username):
if not username:
return 'Guest'
# Only allow alphanumeric and safe characters
if not re.match(r'^[a-zA-Z0-9_.-]+$', username):
return 'User'
return username[:50] # Limit length
# Safe: JSON API responses
def safe_api_response(request):
message = request.POST.get('message', '')
try:
# Validate message
validated_message = validate_api_message(message)
# Safe: Django's JsonResponse automatically escapes
return JsonResponse({
'status': 'success',
'message': validated_message,
'timestamp': int(time.time())
})
except ValidationError as e:
return JsonResponse({'error': 'Invalid message'}, status=400)
def validate_api_message(message):
if not message:
raise ValidationError('Empty message')
if len(message) > 500:
raise ValidationError('Message too long')
# Remove dangerous characters
cleaned_message = re.sub(r'[<>"\']', '', message)
return cleaned_message
# Safe: Form processing with templates
def safe_process_form(request):
if request.method == 'POST':
try:
# Validate form data
validated_data = validate_form_data(request.POST)
# Process form data here (save to database, etc.)
# Safe: Template rendering with auto-escaping
context = {
'success': True,
'name': validated_data['name'],
'email': validated_data['email']
# Note: Comment not displayed for security
}
return render(request, 'form_success.html', context)
except ValidationError as e:
return JsonResponse({'error': str(e)}, status=400)
return render(request, 'form.html')
def validate_form_data(post_data):
name = post_data.get('name', '').strip()
email = post_data.get('email', '').strip()
comment = post_data.get('comment', '').strip()
# Validate name
if not name or len(name) > 100:
raise ValidationError('Invalid name')
if not re.match(r'^[a-zA-Z\s.-]+$', name):
raise ValidationError('Name contains invalid characters')
# Validate email
if not email or len(email) > 254:
raise ValidationError('Invalid email')
email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
if not re.match(email_pattern, email):
raise ValidationError('Invalid email format')
# Validate comment
if len(comment) > 1000:
raise ValidationError('Comment too long')
return {
'name': name,
'email': email,
'comment': comment
}
# Safe: Debug information without reflection
def safe_debug_info(request):
# Only show debug info to staff users
if not request.user.is_staff:
return JsonResponse({'error': 'Access denied'}, status=403)
debug_param = request.GET.get('debug', '')
# Safe: No user input reflection
debug_info = {
'timestamp': int(time.time()),
'user_authenticated': request.user.is_authenticated,
'session_key_exists': bool(request.session.session_key),
'method': request.method,
'secure': request.is_secure()
}
# Only include debug param if it's safe
if debug_param and debug_param in ['sql', 'cache', 'session']:
debug_info['debug_mode'] = debug_param
return JsonResponse(debug_info)
# Safe: Redirect without reflection
def safe_custom_redirect(request):
redirect_url = request.GET.get('next', '/')
message_type = request.GET.get('msg_type', '')
# Validate redirect URL
allowed_domains = ['localhost', 'example.com', 'myapp.com']
if not is_safe_redirect_url(redirect_url, allowed_domains):
redirect_url = '/'
# Use predefined messages instead of user input
messages = {
'logout': 'You have been logged out successfully.',
'login': 'Please log in to continue.',
'error': 'An error occurred. Please try again.'
}
message = messages.get(message_type, 'Redirecting...')
# Safe: Template with no user input reflection
context = {
'redirect_url': redirect_url,
'message': message,
'delay': 3
}
return render(request, 'redirect.html', context)
def is_safe_redirect_url(url, allowed_domains):
from urllib.parse import urlparse
if not url:
return False
# Allow relative URLs
if url.startswith('/'):
return True
# Validate absolute URLs
try:
parsed = urlparse(url)
return parsed.netloc in allowed_domains
except Exception:
return False