CVE-2026-48587 Overview
CVE-2026-48587 affects Django versions 5.2 before 5.2.15 and 6.0 before 6.0.6. The flaw resides in django.utils.cache.has_vary_header(), which fails to strip leading or trailing whitespace from Vary response header values before comparison. Remote attackers can read cached responses by issuing requests to URLs whose responses contain whitespace-padded Vary header values. The issue is classified under [CWE-1023] (Incomplete Comparison with Missing Factors). Earlier, unsupported Django series such as 5.0.x, 4.1.x, and 3.2.x were not evaluated and may also be affected. Django credits Navid Rezazadeh for reporting the issue.
Critical Impact
Remote attackers can retrieve cached HTTP responses intended for other clients, exposing potentially sensitive content through Django's cache middleware.
Affected Products
- Django 5.2 before 5.2.15
- Django 6.0 before 6.0.6
- Unsupported series (5.0.x, 4.1.x, 3.2.x) potentially affected but not evaluated
Discovery Timeline
- Vulnerability reported by Navid Rezazadeh
- 2026-06-03 - CVE-2026-48587 published to NVD
- 2026-06-03 - Django publishes security release notes
- 2026-06-03 - Last updated in NVD database
Technical Details for CVE-2026-48587
Vulnerability Analysis
Django's cache framework uses the Vary HTTP response header to determine which request headers influence cache key generation. The helper function django.utils.cache.has_vary_header() checks whether a specific header name appears in the Vary value before deciding cache behavior. The function compares header names without normalizing surrounding whitespace. When a response sets a Vary value padded with spaces, the comparison fails to match the expected header name. The cache layer then treats the response as not varying on that header and serves cached content to requesters that should have received distinct responses. This allows an unauthenticated remote attacker to read cached responses that were generated for other request contexts.
Root Cause
The root cause is incomplete string comparison in has_vary_header(). Header field values in HTTP allow optional whitespace around list elements per RFC 7230, but Django's comparison logic does not call strip() on tokens parsed from the Vary header. The mismatch between RFC-compliant header formatting and Django's strict equality check creates a cache key confusion condition tracked as [CWE-1023].
Attack Vector
The attack vector is network-based and requires no authentication. An attacker issues HTTP requests to URLs whose application responses include a Vary header containing whitespace-padded values, such as Vary: " Cookie" or Vary: "Accept-Encoding ,Cookie". Because Django fails to recognize the listed headers, the response is cached without proper key segmentation. Subsequent attacker requests receive cached responses originally generated for other clients, exposing content that should have been isolated.
No verified public proof-of-concept code is available. Refer to the Django Blog on Security Releases for vendor technical details.
Detection Methods for CVE-2026-48587
Indicators of Compromise
- Application responses containing Vary header values with leading or trailing whitespace around comma-separated tokens
- Unexpected delivery of authenticated or personalized content to anonymous cache requests
- Cache hit ratios deviating from baseline on endpoints that set dynamic Vary headers
Detection Strategies
- Audit application and middleware code for any logic that constructs Vary headers programmatically, especially through string concatenation
- Inspect HTTP responses in staging and production for malformed Vary headers using web application logging or reverse proxy capture
- Review Django version inventory across services to identify instances running 5.2.0 through 5.2.14 or 6.0.0 through 6.0.5
Monitoring Recommendations
- Log full Vary response headers at the reverse proxy or CDN layer and alert on values containing whitespace anomalies
- Monitor cache backends (Memcached, Redis) for keys that map to a smaller-than-expected variant set on personalized endpoints
- Correlate authenticated session identifiers with cache hits to detect cross-client response delivery
How to Mitigate CVE-2026-48587
Immediate Actions Required
- Upgrade Django to 5.2.15 or 6.0.6 in all environments running the affected branches
- Decommission or upgrade unsupported Django series (5.0.x, 4.1.x, 3.2.x) since these were not evaluated and may be vulnerable
- Invalidate existing cache entries after patching to remove any previously poisoned responses
Patch Information
Django released fixed versions 5.2.15 and 6.0.6 on June 3, 2026. The patches normalize whitespace in Vary header tokens before comparison in django.utils.cache.has_vary_header(). Patch details and release notes are available in the Django Security Release Notes and announced via the Django Announcements Group.
Workarounds
- Sanitize Vary headers at a reverse proxy or middleware layer by stripping whitespace from each token before the response reaches Django's cache framework
- Disable Django's UpdateCacheMiddleware and FetchFromCacheMiddleware on endpoints that emit dynamic Vary headers until patching is complete
- Restrict caching to endpoints with statically defined Vary values controlled by the application
# Upgrade Django to a patched release
pip install --upgrade "Django>=5.2.15,<6.0"
# or for the 6.0 branch
pip install --upgrade "Django>=6.0.6"
# Verify installed version
python -c "import django; print(django.get_version())"
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


