This commit is contained in:
Iliyan Angelov
2025-12-10 01:36:00 +02:00
parent 2f6dca736a
commit 6a9e823402
84 changed files with 5293 additions and 1836 deletions

View File

@@ -1,4 +1,7 @@
from rest_framework import serializers
from django.utils.html import strip_tags, escape
from django.core.exceptions import ValidationError
import re
from .models import ContactSubmission
@@ -126,6 +129,72 @@ class ContactSubmissionCreateSerializer(serializers.ModelSerializer):
'privacy_consent',
]
def _sanitize_text_field(self, value):
"""
Sanitize text fields by detecting and rejecting HTML/script tags.
Returns cleaned text or raises ValidationError if dangerous content is detected.
"""
if not value:
return value
# Check for script tags and other dangerous HTML patterns
dangerous_patterns = [
(r'<script[^>]*>.*?</script>', 'Script tags are not allowed'),
(r'<iframe[^>]*>.*?</iframe>', 'Iframe tags are not allowed'),
(r'javascript:', 'JavaScript protocol is not allowed'),
(r'on\w+\s*=', 'Event handlers are not allowed'),
(r'<svg[^>]*onload', 'SVG onload handlers are not allowed'),
(r'<img[^>]*onerror', 'Image onerror handlers are not allowed'),
(r'<[^>]+>', 'HTML tags are not allowed'), # Catch any remaining HTML tags
]
value_lower = value.lower()
for pattern, message in dangerous_patterns:
if re.search(pattern, value_lower, re.IGNORECASE | re.DOTALL):
raise serializers.ValidationError(
f"Invalid input detected: {message}. Please remove HTML tags and scripts."
)
# Strip any remaining HTML tags (defense in depth)
cleaned = strip_tags(value)
# Remove any remaining script-like content
cleaned = re.sub(r'javascript:', '', cleaned, flags=re.IGNORECASE)
return cleaned.strip()
def validate_first_name(self, value):
"""Sanitize first name field."""
return self._sanitize_text_field(value)
def validate_last_name(self, value):
"""Sanitize last name field."""
return self._sanitize_text_field(value)
def validate_company(self, value):
"""Sanitize company field."""
return self._sanitize_text_field(value)
def validate_job_title(self, value):
"""Sanitize job title field."""
return self._sanitize_text_field(value)
def validate_message(self, value):
"""Sanitize message field."""
return self._sanitize_text_field(value)
def validate_phone(self, value):
"""Sanitize phone field - only allow alphanumeric, spaces, dashes, parentheses, and plus."""
if not value:
return value
# Remove HTML tags
cleaned = strip_tags(value)
# Only allow phone number characters
if not re.match(r'^[\d\s\-\+\(\)]+$', cleaned):
raise serializers.ValidationError("Phone number contains invalid characters.")
return cleaned.strip()
def validate_privacy_consent(self, value):
"""
Ensure privacy consent is given.