VYPR
High severityNVD Advisory· Published Apr 23, 2014· Updated May 6, 2026

CVE-2014-0473

CVE-2014-0473

Description

The caching framework in Django before 1.4.11, 1.5.x before 1.5.6, 1.6.x before 1.6.3, and 1.7.x before 1.7 beta 2 reuses a cached CSRF token for all anonymous users, which allows remote attackers to bypass CSRF protections by reading the CSRF cookie for anonymous users.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
DjangoPyPI
< 1.4.111.4.11
DjangoPyPI
>= 1.5, < 1.5.61.5.6
DjangoPyPI
>= 1.6, < 1.6.31.6.3

Affected products

28
  • cpe:2.3:a:djangoproject:django:1.5:*:*:*:*:*:*:*+ 22 more
    • 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.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.7:alpha1:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.7:alpha2:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.7:beta1:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:*:*:*:*:*:*:*:*range: <=1.4.10
    • 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.2:*:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.4.3:*:*:*:*:*:*:*
    • 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: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

3
1170f285ddd6

[1.4.x] Prevented leaking the CSRF token through caching.

https://github.com/django/djangoAymeric AugustinApr 20, 2014via ghsa
2 files changed · +36 1
  • django/middleware/cache.py+9 1 modified
    @@ -50,7 +50,8 @@
     
     from django.conf import settings
     from django.core.cache import get_cache, DEFAULT_CACHE_ALIAS
    -from django.utils.cache import get_cache_key, learn_cache_key, patch_response_headers, get_max_age
    +from django.utils.cache import (get_cache_key, get_max_age, has_vary_header,
    +    learn_cache_key, patch_response_headers)
     
     
     class UpdateCacheMiddleware(object):
    @@ -93,8 +94,15 @@ def process_response(self, request, response):
             if not self._should_update_cache(request, response):
                 # We don't need to update the cache, just return.
                 return response
    +
             if not response.status_code == 200:
                 return response
    +
    +        # Don't cache responses that set a user-specific (and maybe security
    +        # sensitive) cookie in response to a cookie-less request.
    +        if not request.COOKIES and response.cookies and has_vary_header(response, 'Cookie'):
    +            return response
    +
             # Try to get the timeout from the "max-age" section of the "Cache-
             # Control" header before reverting to using the default cache_timeout
             # length.
    
  • tests/regressiontests/cache/tests.py+27 0 modified
    @@ -17,10 +17,12 @@
     from django.core.cache import get_cache, DEFAULT_CACHE_ALIAS
     from django.core.cache.backends.base import (CacheKeyWarning,
         InvalidCacheBackendError)
    +from django.core.context_processors import csrf
     from django.db import router
     from django.http import HttpResponse, HttpRequest, QueryDict
     from django.middleware.cache import (FetchFromCacheMiddleware,
         UpdateCacheMiddleware, CacheMiddleware)
    +from django.middleware.csrf import CsrfViewMiddleware
     from django.template import Template
     from django.template.response import TemplateResponse
     from django.test import TestCase, TransactionTestCase, RequestFactory
    @@ -1418,6 +1420,10 @@ def hello_world_view(request, value):
         return HttpResponse('Hello World %s' % value)
     
     
    +def csrf_view(request):
    +    return HttpResponse(csrf(request)['csrf_token'])
    +
    +
     class CacheMiddlewareTest(TestCase):
     
         def setUp(self):
    @@ -1635,6 +1641,27 @@ def test_view_decorator(self):
             response = other_with_timeout_view(request, '18')
             self.assertEqual(response.content, 'Hello World 18')
     
    +    def test_sensitive_cookie_not_cached(self):
    +        """
    +        Django must prevent caching of responses that set a user-specific (and
    +        maybe security sensitive) cookie in response to a cookie-less request.
    +        """
    +        csrf_middleware = CsrfViewMiddleware()
    +        cache_middleware = CacheMiddleware()
    +
    +        request = self.factory.get('/view/')
    +        self.assertIsNone(cache_middleware.process_request(request))
    +
    +        csrf_middleware.process_view(request, csrf_view, (), {})
    +
    +        response = csrf_view(request)
    +
    +        response = csrf_middleware.process_response(request, response)
    +        response = cache_middleware.process_response(request, response)
    +
    +        # Inserting a CSRF cookie in a cookie-less request prevented caching.
    +        self.assertIsNone(cache_middleware.process_request(request))
    +
     CacheMiddlewareTest = override_settings(
             CACHE_MIDDLEWARE_ALIAS='other',
             CACHE_MIDDLEWARE_KEY_PREFIX='middlewareprefix',
    
6872f42757d7

[1.5.x] Prevented leaking the CSRF token through caching.

https://github.com/django/djangoAymeric AugustinApr 20, 2014via ghsa
2 files changed · +36 1
  • django/middleware/cache.py+9 1 modified
    @@ -50,7 +50,8 @@
     
     from django.conf import settings
     from django.core.cache import get_cache, DEFAULT_CACHE_ALIAS
    -from django.utils.cache import get_cache_key, learn_cache_key, patch_response_headers, get_max_age
    +from django.utils.cache import (get_cache_key, get_max_age, has_vary_header,
    +    learn_cache_key, patch_response_headers)
     
     
     class UpdateCacheMiddleware(object):
    @@ -93,8 +94,15 @@ def process_response(self, request, response):
             if not self._should_update_cache(request, response):
                 # We don't need to update the cache, just return.
                 return response
    +
             if response.streaming or response.status_code != 200:
                 return response
    +
    +        # Don't cache responses that set a user-specific (and maybe security
    +        # sensitive) cookie in response to a cookie-less request.
    +        if not request.COOKIES and response.cookies and has_vary_header(response, 'Cookie'):
    +            return response
    +
             # Try to get the timeout from the "max-age" section of the "Cache-
             # Control" header before reverting to using the default cache_timeout
             # length.
    
  • tests/regressiontests/cache/tests.py+27 0 modified
    @@ -18,11 +18,13 @@
     from django.core.cache import get_cache
     from django.core.cache.backends.base import (CacheKeyWarning,
         InvalidCacheBackendError)
    +from django.core.context_processors import csrf
     from django.db import router
     from django.http import (HttpResponse, HttpRequest, StreamingHttpResponse,
         QueryDict)
     from django.middleware.cache import (FetchFromCacheMiddleware,
         UpdateCacheMiddleware, CacheMiddleware)
    +from django.middleware.csrf import CsrfViewMiddleware
     from django.template import Template
     from django.template.response import TemplateResponse
     from django.test import TestCase, TransactionTestCase, RequestFactory
    @@ -1456,6 +1458,10 @@ def hello_world_view(request, value):
         return HttpResponse('Hello World %s' % value)
     
     
    +def csrf_view(request):
    +    return HttpResponse(csrf(request)['csrf_token'])
    +
    +
     @override_settings(
             CACHE_MIDDLEWARE_ALIAS='other',
             CACHE_MIDDLEWARE_KEY_PREFIX='middlewareprefix',
    @@ -1696,6 +1702,27 @@ def test_view_decorator(self):
             response = other_with_timeout_view(request, '18')
             self.assertEqual(response.content, b'Hello World 18')
     
    +    def test_sensitive_cookie_not_cached(self):
    +        """
    +        Django must prevent caching of responses that set a user-specific (and
    +        maybe security sensitive) cookie in response to a cookie-less request.
    +        """
    +        csrf_middleware = CsrfViewMiddleware()
    +        cache_middleware = CacheMiddleware()
    +
    +        request = self.factory.get('/view/')
    +        self.assertIsNone(cache_middleware.process_request(request))
    +
    +        csrf_middleware.process_view(request, csrf_view, (), {})
    +
    +        response = csrf_view(request)
    +
    +        response = csrf_middleware.process_response(request, response)
    +        response = cache_middleware.process_response(request, response)
    +
    +        # Inserting a CSRF cookie in a cookie-less request prevented caching.
    +        self.assertIsNone(cache_middleware.process_request(request))
    +
     
     @override_settings(
             CACHE_MIDDLEWARE_KEY_PREFIX='settingsprefix',
    
d63e20942f30

[1.6.x] Prevented leaking the CSRF token through caching.

https://github.com/django/djangoAymeric AugustinApr 20, 2014via ghsa
2 files changed · +37 1
  • django/middleware/cache.py+9 1 modified
    @@ -47,7 +47,8 @@
     
     from django.conf import settings
     from django.core.cache import get_cache, DEFAULT_CACHE_ALIAS
    -from django.utils.cache import get_cache_key, learn_cache_key, patch_response_headers, get_max_age
    +from django.utils.cache import (get_cache_key, get_max_age, has_vary_header,
    +    learn_cache_key, patch_response_headers)
     
     
     class UpdateCacheMiddleware(object):
    @@ -90,8 +91,15 @@ def process_response(self, request, response):
             if not self._should_update_cache(request, response):
                 # We don't need to update the cache, just return.
                 return response
    +
             if response.streaming or response.status_code != 200:
                 return response
    +
    +        # Don't cache responses that set a user-specific (and maybe security
    +        # sensitive) cookie in response to a cookie-less request.
    +        if not request.COOKIES and response.cookies and has_vary_header(response, 'Cookie'):
    +            return response
    +
             # Try to get the timeout from the "max-age" section of the "Cache-
             # Control" header before reverting to using the default cache_timeout
             # length.
    
  • tests/cache/tests.py+28 0 modified
    @@ -19,12 +19,14 @@
     from django.core.cache import get_cache
     from django.core.cache.backends.base import (CacheKeyWarning,
         InvalidCacheBackendError)
    +from django.core.context_processors import csrf
     from django.db import router, transaction
     from django.core.cache.utils import make_template_fragment_key
     from django.http import (HttpResponse, HttpRequest, StreamingHttpResponse,
         QueryDict)
     from django.middleware.cache import (FetchFromCacheMiddleware,
         UpdateCacheMiddleware, CacheMiddleware)
    +from django.middleware.csrf import CsrfViewMiddleware
     from django.template import Template
     from django.template.response import TemplateResponse
     from django.test import TestCase, TransactionTestCase, RequestFactory
    @@ -1578,6 +1580,10 @@ def hello_world_view(request, value):
         return HttpResponse('Hello World %s' % value)
     
     
    +def csrf_view(request):
    +    return HttpResponse(csrf(request)['csrf_token'])
    +
    +
     @override_settings(
             CACHE_MIDDLEWARE_ALIAS='other',
             CACHE_MIDDLEWARE_KEY_PREFIX='middlewareprefix',
    @@ -1797,6 +1803,28 @@ def test_view_decorator(self):
             response = other_with_prefix_view(request, '16')
             self.assertEqual(response.content, b'Hello World 16')
     
    +    def test_sensitive_cookie_not_cached(self):
    +        """
    +        Django must prevent caching of responses that set a user-specific (and
    +        maybe security sensitive) cookie in response to a cookie-less request.
    +        """
    +        csrf_middleware = CsrfViewMiddleware()
    +        cache_middleware = CacheMiddleware()
    +
    +        request = self.factory.get('/view/')
    +        self.assertIsNone(cache_middleware.process_request(request))
    +
    +        csrf_middleware.process_view(request, csrf_view, (), {})
    +
    +        response = csrf_view(request)
    +
    +        response = csrf_middleware.process_response(request, response)
    +        response = cache_middleware.process_response(request, response)
    +
    +        # Inserting a CSRF cookie in a cookie-less request prevented caching.
    +        self.assertIsNone(cache_middleware.process_request(request))
    +
    +
     @override_settings(
             CACHE_MIDDLEWARE_KEY_PREFIX='settingsprefix',
             CACHE_MIDDLEWARE_SECONDS=1,
    

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

News mentions

0

No linked articles in our index yet.