Critical severityNVD Advisory· Published May 16, 2014· Updated May 6, 2026
CVE-2014-1418
CVE-2014-1418
Description
Django 1.4 before 1.4.13, 1.5 before 1.5.8, 1.6 before 1.6.5, and 1.7 before 1.7b4 does not properly include the (1) Vary: Cookie or (2) Cache-Control header in responses, which allows remote attackers to obtain sensitive information or poison the cache via a request from certain browsers.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
DjangoPyPI | >= 1.4, < 1.4.13 | 1.4.13 |
DjangoPyPI | >= 1.5, < 1.5.8 | 1.5.8 |
DjangoPyPI | >= 1.6, < 1.6.5 | 1.6.5 |
DjangoPyPI | >= 1.7a1, < 1.7b4 | 1.7b4 |
Affected products
39cpe:2.3:a:djangoproject:django:1.4:*:*:*:*:*:*:*+ 33 more
- cpe:2.3:a:djangoproject:django:1.4:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.4.1:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.4.10:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.4.11:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.4.12:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.4.2:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.4.4:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.4.5:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.4.6:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.4.7:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.4.8:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.4.9:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5.1:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5.2:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5.3:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5.4:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5.5:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5.6:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5.7:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5:alpha:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5:beta:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.6:-:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.6.1:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.6.2:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.6.3:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.6.4:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.6:beta1:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.6:beta2:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.6:beta3:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.6:beta4:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.7:beta1:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.7:beta2:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.7:beta3:*:*:*:*:*:*
cpe:2.3:o:canonical:ubuntu_linux:10.04:-:lts:*:*:*:*:*+ 4 more
- cpe:2.3:o:canonical:ubuntu_linux:10.04:-:lts:*:*:*:*:*
- cpe:2.3:o:canonical:ubuntu_linux:12.04:-:lts:*:*:*:*:*
- cpe:2.3:o:canonical:ubuntu_linux:12.10:*:*:*:*:*:*:*
- cpe:2.3:o:canonical:ubuntu_linux:13.10:*:*:*:*:*:*:*
- cpe:2.3:o:canonical:ubuntu_linux:14.04:*:*:*:lts:*:*:*
Patches
328e23306aa53[1.4.x] Dropped fix_IE_for_vary/attach.
3 files changed · +0 −100
django/core/handlers/base.py+0 −2 modified@@ -14,8 +14,6 @@ class BaseHandler(object): response_fixes = [ http.fix_location_header, http.conditional_content_removal, - http.fix_IE_for_attach, - http.fix_IE_for_vary, ] def __init__(self):
django/http/utils.py+0 −54 modified@@ -31,57 +31,3 @@ def conditional_content_removal(request, response): if request.method == 'HEAD': response.content = '' return response - -def fix_IE_for_attach(request, response): - """ - This function will prevent Django from serving a Content-Disposition header - while expecting the browser to cache it (only when the browser is IE). This - leads to IE not allowing the client to download. - """ - useragent = request.META.get('HTTP_USER_AGENT', '').upper() - if 'MSIE' not in useragent and 'CHROMEFRAME' not in useragent: - return response - - offending_headers = ('no-cache', 'no-store') - if response.has_header('Content-Disposition'): - try: - del response['Pragma'] - except KeyError: - pass - if response.has_header('Cache-Control'): - cache_control_values = [value.strip() for value in - response['Cache-Control'].split(',') - if value.strip().lower() not in offending_headers] - - if not len(cache_control_values): - del response['Cache-Control'] - else: - response['Cache-Control'] = ', '.join(cache_control_values) - - return response - -def fix_IE_for_vary(request, response): - """ - This function will fix the bug reported at - http://support.microsoft.com/kb/824847/en-us?spid=8722&sid=global - by clearing the Vary header whenever the mime-type is not safe - enough for Internet Explorer to handle. Poor thing. - """ - useragent = request.META.get('HTTP_USER_AGENT', '').upper() - if 'MSIE' not in useragent and 'CHROMEFRAME' not in useragent: - return response - - # These mime-types that are decreed "Vary-safe" for IE: - safe_mime_types = ('text/html', 'text/plain', 'text/sgml') - - # The first part of the Content-Type field will be the MIME type, - # everything after ';', such as character-set, can be ignored. - mime_type = response.get('Content-Type', '').partition(';')[0] - if mime_type not in safe_mime_types: - try: - del response['Vary'] - except KeyError: - pass - - return response -
tests/regressiontests/utils/http.py+0 −44 modified@@ -56,50 +56,6 @@ def test_urlencode(self): ] self.assertTrue(result in acceptable_results) - def test_fix_IE_for_vary(self): - """ - Regression for #16632. - - `fix_IE_for_vary` shouldn't crash when there's no Content-Type header. - """ - - # functions to generate responses - def response_with_unsafe_content_type(): - r = HttpResponse(content_type="text/unsafe") - r['Vary'] = 'Cookie' - return r - - def no_content_response_with_unsafe_content_type(): - # 'Content-Type' always defaulted, so delete it - r = response_with_unsafe_content_type() - del r['Content-Type'] - return r - - # request with & without IE user agent - rf = RequestFactory() - request = rf.get('/') - ie_request = rf.get('/', HTTP_USER_AGENT='MSIE') - - # not IE, unsafe_content_type - response = response_with_unsafe_content_type() - utils.fix_IE_for_vary(request, response) - self.assertTrue('Vary' in response) - - # IE, unsafe_content_type - response = response_with_unsafe_content_type() - utils.fix_IE_for_vary(ie_request, response) - self.assertFalse('Vary' in response) - - # not IE, no_content - response = no_content_response_with_unsafe_content_type() - utils.fix_IE_for_vary(request, response) - self.assertTrue('Vary' in response) - - # IE, no_content - response = no_content_response_with_unsafe_content_type() - utils.fix_IE_for_vary(ie_request, response) - self.assertFalse('Vary' in response) - def test_base36(self): # reciprocity works for n in [0, 1, 1000, 1000000, sys.maxint]:
4001ec8698f5[1.5.x] Dropped fix_IE_for_vary/attach.
4 files changed · +1 −103
django/core/handlers/base.py+0 −2 modified@@ -22,8 +22,6 @@ class BaseHandler(object): response_fixes = [ http.fix_location_header, http.conditional_content_removal, - http.fix_IE_for_attach, - http.fix_IE_for_vary, ] def __init__(self):
django/http/__init__.py+1 −2 modified@@ -6,5 +6,4 @@ HttpResponseRedirect, HttpResponseNotModified, HttpResponseBadRequest, HttpResponseForbidden, HttpResponseNotFound, HttpResponseNotAllowed, HttpResponseGone, HttpResponseServerError, Http404, BadHeaderError) -from django.http.utils import (fix_location_header, conditional_content_removal, - fix_IE_for_attach, fix_IE_for_vary) +from django.http.utils import fix_location_header, conditional_content_removal
django/http/utils.py+0 −55 modified@@ -39,58 +39,3 @@ def conditional_content_removal(request, response): else: response.content = '' return response - - -def fix_IE_for_attach(request, response): - """ - This function will prevent Django from serving a Content-Disposition header - while expecting the browser to cache it (only when the browser is IE). This - leads to IE not allowing the client to download. - """ - useragent = request.META.get('HTTP_USER_AGENT', '').upper() - if 'MSIE' not in useragent and 'CHROMEFRAME' not in useragent: - return response - - offending_headers = ('no-cache', 'no-store') - if response.has_header('Content-Disposition'): - try: - del response['Pragma'] - except KeyError: - pass - if response.has_header('Cache-Control'): - cache_control_values = [value.strip() for value in - response['Cache-Control'].split(',') - if value.strip().lower() not in offending_headers] - - if not len(cache_control_values): - del response['Cache-Control'] - else: - response['Cache-Control'] = ', '.join(cache_control_values) - - return response - - -def fix_IE_for_vary(request, response): - """ - This function will fix the bug reported at - http://support.microsoft.com/kb/824847/en-us?spid=8722&sid=global - by clearing the Vary header whenever the mime-type is not safe - enough for Internet Explorer to handle. Poor thing. - """ - useragent = request.META.get('HTTP_USER_AGENT', '').upper() - if 'MSIE' not in useragent and 'CHROMEFRAME' not in useragent: - return response - - # These mime-types that are decreed "Vary-safe" for IE: - safe_mime_types = ('text/html', 'text/plain', 'text/sgml') - - # The first part of the Content-Type field will be the MIME type, - # everything after ';', such as character-set, can be ignored. - mime_type = response.get('Content-Type', '').partition(';')[0] - if mime_type not in safe_mime_types: - try: - del response['Vary'] - except KeyError: - pass - - return response
tests/regressiontests/utils/http.py+0 −44 modified@@ -67,50 +67,6 @@ def test_urlencode(self): ] self.assertTrue(result in acceptable_results) - def test_fix_IE_for_vary(self): - """ - Regression for #16632. - - `fix_IE_for_vary` shouldn't crash when there's no Content-Type header. - """ - - # functions to generate responses - def response_with_unsafe_content_type(): - r = HttpResponse(content_type="text/unsafe") - r['Vary'] = 'Cookie' - return r - - def no_content_response_with_unsafe_content_type(): - # 'Content-Type' always defaulted, so delete it - r = response_with_unsafe_content_type() - del r['Content-Type'] - return r - - # request with & without IE user agent - rf = RequestFactory() - request = rf.get('/') - ie_request = rf.get('/', HTTP_USER_AGENT='MSIE') - - # not IE, unsafe_content_type - response = response_with_unsafe_content_type() - utils.fix_IE_for_vary(request, response) - self.assertTrue('Vary' in response) - - # IE, unsafe_content_type - response = response_with_unsafe_content_type() - utils.fix_IE_for_vary(ie_request, response) - self.assertFalse('Vary' in response) - - # not IE, no_content - response = no_content_response_with_unsafe_content_type() - utils.fix_IE_for_vary(request, response) - self.assertTrue('Vary' in response) - - # IE, no_content - response = no_content_response_with_unsafe_content_type() - utils.fix_IE_for_vary(ie_request, response) - self.assertFalse('Vary' in response) - def test_base36(self): # reciprocity works for n in [0, 1, 1000, 1000000]:
1abcf3a808b3[1.6.x] Dropped fix_IE_for_vary/attach.
4 files changed · +1 −103
django/core/handlers/base.py+0 −2 modified@@ -23,8 +23,6 @@ class BaseHandler(object): response_fixes = [ http.fix_location_header, http.conditional_content_removal, - http.fix_IE_for_attach, - http.fix_IE_for_vary, ] def __init__(self):
django/http/__init__.py+1 −2 modified@@ -6,5 +6,4 @@ HttpResponseRedirect, HttpResponseNotModified, HttpResponseBadRequest, HttpResponseForbidden, HttpResponseNotFound, HttpResponseNotAllowed, HttpResponseGone, HttpResponseServerError, Http404, BadHeaderError) -from django.http.utils import (fix_location_header, conditional_content_removal, - fix_IE_for_attach, fix_IE_for_vary) +from django.http.utils import fix_location_header, conditional_content_removal
django/http/utils.py+0 −55 modified@@ -39,58 +39,3 @@ def conditional_content_removal(request, response): else: response.content = b'' return response - - -def fix_IE_for_attach(request, response): - """ - This function will prevent Django from serving a Content-Disposition header - while expecting the browser to cache it (only when the browser is IE). This - leads to IE not allowing the client to download. - """ - useragent = request.META.get('HTTP_USER_AGENT', '').upper() - if 'MSIE' not in useragent and 'CHROMEFRAME' not in useragent: - return response - - offending_headers = ('no-cache', 'no-store') - if response.has_header('Content-Disposition'): - try: - del response['Pragma'] - except KeyError: - pass - if response.has_header('Cache-Control'): - cache_control_values = [value.strip() for value in - response['Cache-Control'].split(',') - if value.strip().lower() not in offending_headers] - - if not len(cache_control_values): - del response['Cache-Control'] - else: - response['Cache-Control'] = ', '.join(cache_control_values) - - return response - - -def fix_IE_for_vary(request, response): - """ - This function will fix the bug reported at - http://support.microsoft.com/kb/824847/en-us?spid=8722&sid=global - by clearing the Vary header whenever the mime-type is not safe - enough for Internet Explorer to handle. Poor thing. - """ - useragent = request.META.get('HTTP_USER_AGENT', '').upper() - if 'MSIE' not in useragent and 'CHROMEFRAME' not in useragent: - return response - - # These mime-types that are decreed "Vary-safe" for IE: - safe_mime_types = ('text/html', 'text/plain', 'text/sgml') - - # The first part of the Content-Type field will be the MIME type, - # everything after ';', such as character-set, can be ignored. - mime_type = response.get('Content-Type', '').partition(';')[0] - if mime_type not in safe_mime_types: - try: - del response['Vary'] - except KeyError: - pass - - return response
tests/utils_tests/test_http.py+0 −44 modified@@ -67,50 +67,6 @@ def test_urlencode(self): ] self.assertTrue(result in acceptable_results) - def test_fix_IE_for_vary(self): - """ - Regression for #16632. - - `fix_IE_for_vary` shouldn't crash when there's no Content-Type header. - """ - - # functions to generate responses - def response_with_unsafe_content_type(): - r = HttpResponse(content_type="text/unsafe") - r['Vary'] = 'Cookie' - return r - - def no_content_response_with_unsafe_content_type(): - # 'Content-Type' always defaulted, so delete it - r = response_with_unsafe_content_type() - del r['Content-Type'] - return r - - # request with & without IE user agent - rf = RequestFactory() - request = rf.get('/') - ie_request = rf.get('/', HTTP_USER_AGENT='MSIE') - - # not IE, unsafe_content_type - response = response_with_unsafe_content_type() - utils.fix_IE_for_vary(request, response) - self.assertTrue('Vary' in response) - - # IE, unsafe_content_type - response = response_with_unsafe_content_type() - utils.fix_IE_for_vary(ie_request, response) - self.assertFalse('Vary' in response) - - # not IE, no_content - response = no_content_response_with_unsafe_content_type() - utils.fix_IE_for_vary(request, response) - self.assertTrue('Vary' in response) - - # IE, no_content - response = no_content_response_with_unsafe_content_type() - utils.fix_IE_for_vary(ie_request, response) - self.assertFalse('Vary' in response) - def test_base36(self): # reciprocity works for n in [0, 1, 1000, 1000000]:
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
14- www.djangoproject.com/weblog/2014/may/14/security-releases-issued/nvdPatchVendor Advisory
- github.com/advisories/GHSA-q7q2-qf2q-rw3wghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2014-1418ghsaADVISORY
- lists.opensuse.org/opensuse-updates/2014-09/msg00023.htmlnvdWEB
- ubuntu.com/usn/usn-2212-1nvdWEB
- www.debian.org/security/2014/dsa-2934nvdWEB
- www.openwall.com/lists/oss-security/2014/05/14/10nvdWEB
- www.openwall.com/lists/oss-security/2014/05/15/3nvdWEB
- github.com/django/django/commit/1abcf3a808b35abae5d425ed4d44cb6e886dc769ghsaWEB
- github.com/django/django/commit/28e23306aa53bbbb8fb87db85f99d970b051026cghsaWEB
- github.com/django/django/commit/4001ec8698f577b973c5a540801d8a0bbea1205bghsaWEB
- github.com/pypa/advisory-database/tree/main/vulns/django/PYSEC-2014-19.yamlghsaWEB
- www.djangoproject.com/weblog/2014/may/14/security-releases-issuedghsaWEB
- secunia.com/advisories/61281nvd
News mentions
0No linked articles in our index yet.