Overview
CVE-2007-5712 describes a DoS risk in Django's internationalization (i18n) framework when USE_I18N is enabled and the i18n component is active. In the affected releases (Django 0.91, 0.95, 0.95.1, and 0.96, and in integrations such as PyLucid), processing an unusually large Accept-Language header could cause excessive memory consumption on the server, potentially exhausting resources across workers and making the site unavailable. This CVE is categorized under CWE-399 (Resource Exhaustion) and there was a patch released to address the issue. The vulnerability stems from unbounded header processing during language negotiation, which can lead to memory growth under load and degrade service reliability. The impact is primarily DoS, but the reliability of the service directly affects access to any sensitive data by legitimate users due to outages or error conditions.
Attackers could repeatedly send crafted requests with long Accept-Language headers to trigger memory growth, exploiting how Django negotiates languages and caches translations. This can exhaust per-process memory and, under load, cause service degradation or crashes. Although the immediate effect is Denial of Service, the resulting outages can indirectly expose sensitive data through error messages, verbose logs, or by forcing fallback behavior that reveals application internals. Organizations relying on vulnerable Django versions should treat this as a critical remediation item to prevent data exposure via unavailable services.
Remediation guidance focuses on upgrading Django to patched releases and, where upgrading is not possible, applying defensive controls to bound header processing and i18n usage. In real Django code, the fix involves limiting Accept-Language input, restricting how many languages are processed, and ensuring i18n behavior does not create unbounded memory growth under adversarial request patterns. If i18n is not required for the project, disabling USE_I18N or the LocaleMiddleware can reduce exposure. Implementing header size limits at the web server or middleware layer is a practical defense in depth.
Affected Versions
Django 0.91, 0.95, 0.95.1, 0.96 (and as used in integrations like PyLucid)
Code Fix Example
Django API Security Remediation
import django
from django.utils import translation
# Vulnerable pattern: unbounded Accept-Language processing
class VulnerableLocaleMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
accept_lang = request.META.get('HTTP_ACCEPT_LANGUAGE', '')
if accept_lang:
# Vulnerable: no bounds, uses first language directly
languages = [l.strip() for l in accept_lang.split(',') if l.strip()]
if languages:
translation.activate(languages[0])
response = self.get_response(request)
translation.deactivate()
return response
# Fixed pattern: bound the input and limit languages processed
class SafeLocaleMiddleware:
MAX_ACCEPT_LANG_LENGTH = 256
MAX_LANGS = 5
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
accept_lang = request.META.get('HTTP_ACCEPT_LANGUAGE', '')
if len(accept_lang) > self.MAX_ACCEPT_LANG_LENGTH:
accept_lang = accept_lang[:self.MAX_ACCEPT_LANG_LENGTH]
languages = [l.strip() for l in accept_lang.split(',') if l.strip()]
chosen = languages[:self.MAX_LANGS] if languages else ['en']
translation.activate(chosen[0])
response = self.get_response(request)
translation.deactivate()
return response