Cache Poisoning
Also Known As
web cache poisoning
CDN poisoning
TL;DR
An attacker manipulates a cached response so that subsequent users receive malicious content served from the cache.
Explanation
Web cache poisoning abuses the gap between what a caching layer uses as a cache key (typically URL + Host) and what the backend actually processes (including unkeyed headers like X-Forwarded-Host). By injecting a malicious value into an unkeyed header that the application reflects in its response, an attacker can poison the cached copy served to all subsequent visitors. Mitigations include keying caches on all relevant headers, disabling reflection of arbitrary headers, and using Vary headers appropriately.
How It's Exploited
GET /page HTTP/1.1
Host: evil.com
# If Host is reflected in cached response, every subsequent visitor gets evil.com links
Host: evil.com
# If Host is reflected in cached response, every subsequent visitor gets evil.com links
Common Misconception
✗ Cache poisoning only affects public CDN caches. Server-side application caches and reverse proxies can also be poisoned if unkeyed headers influence the cached response.
Why It Matters
A poisoned cache entry serves malicious content to every user who hits that cache key — a single request from an attacker can affect thousands of victims.
Common Mistakes
- Reflecting unkeyed request headers (like X-Forwarded-Host or X-Original-URL) into cached responses.
- Including user-controlled query parameters in responses that are served from cache to other users.
- Not separating cached static resources from dynamic personalised responses.
- Trusting the Host header for generating absolute URLs in cached pages.
Code Examples
✗ Vulnerable
// Caching a response that includes unvalidated Host header
\$cacheKey = 'page:' . \$_SERVER['HTTP_HOST'] . \$_SERVER['REQUEST_URI'];
\$cached = \$cache->get(\$cacheKey);
if (!\$cached) {
\$html = render(['canonical' => 'https://' . \$_SERVER['HTTP_HOST'] . '/page']);
\$cache->set(\$cacheKey, \$html);
}
✓ Fixed
// Use a fixed canonical hostname — never trust the Host header for cache keys
\$canonicalHost = config('app.url'); // 'https://yourapp.com'
\$cacheKey = 'page:' . md5(\$canonicalHost . \$_SERVER['REQUEST_URI']);
// In nginx — only forward known Host values to PHP:
// if (\$host !~* ^(yourapp\.com|www\.yourapp\.com)\$) { return 444; }
References
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
15 Mar 2026
Edited
22 Mar 2026
Views
29
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 0
No pings yet today
Ahrefs 8
Perplexity 7
Amazonbot 6
Unknown AI 2
Also referenced
How they use it
crawler 23
Related categories
⚡
DEV INTEL
Tools & Severity
🟠 High
⚙ Fix effort: Medium
⚡ Quick Fix
Never cache responses based on unvalidated request headers; vary cache keys on only the headers you explicitly support; set Cache-Control: no-store on sensitive pages
📦 Applies To
PHP 5.0+
web
api
🔗 Prerequisites
🔍 Detection Hints
Response content influenced by X-Forwarded-Host or arbitrary headers that are also cached; user-specific content in shared cache
Auto-detectable:
✗ No
burpsuite
semgrep
owasp-zap
⚠ Related Problems
🤖 AI Agent
Confidence: Medium
False Positives: Medium
✗ Manual fix
Fix: High
Context: File
Tests: Update
CWE-345
CWE-494