Overview
Django's early i18n framework (USE_I18N enabled) in versions like 0.91, 0.95, 0.95.1, and 0.96 could be mass-exploitable via crafted HTTP Accept-Language headers, leading to memory exhaustion and denial of service. This real-world issue stems from how the i18n subsystem parsed and activated translations per request without bounding resource usage. While not a classic Broken Object Property Level Authorization flaw, it demonstrates how misconfiguration of a global feature can be abused to exhaust server resources on Django deployments that rely on internationalization and translation caching. References to CVE-2007-5712 highlight remote DoS through excessive header payloads when USE_I18N and i18n components were enabled, including usage in projects like PyLucid. Upgrading to patched Django versions or disabling i18n where not needed mitigates this risk. In modern Django, object-level authorization patterns should be paired with secure i18n practices to avoid auxiliary attack surfaces, particularly in multi-tenant or high-traffic sites.
Affected Versions
Django 0.91, 0.95, 0.95.1, 0.96
Code Fix Example
Django API Security Remediation
from django.http import HttpResponse
from django.utils import translation
from django.conf import settings
# Vulnerable pattern: unbounded Accept-Language handling
def vulnerable_view(request):
# Accept-Language header is taken at face value and language is activated
accept_lang = request.META.get('HTTP_ACCEPT_LANGUAGE', '')
language = accept_lang.split(',')[0] if accept_lang else 'en'
translation.activate(language)
return HttpResponse('Vulnerable: language set to {}'.format(language))
# Fixed pattern: bound the header length and validate against allowed LANGUAGES
def fixed_view(request):
accept_lang = request.META.get('HTTP_ACCEPT_LANGUAGE', '')
# Bound header length to prevent excessive processing/memory usage
if len(accept_lang) > 1024:
accept_lang = accept_lang[:1024]
language = (accept_lang.split(',')[0] if accept_lang else 'en').split(';')[0].strip()
# Validate against Django's configured LANGUAGES
allowed = [code for code, _ in getattr(settings, 'LANGUAGES', [('en', 'English')])]
if language not in allowed:
language = 'en'
translation.activate(language)
return HttpResponse('Fixed: language set to {}'.format(language))