Web cache poisoning exploits the gap between what a cache stores and what it checks — attackers inject malicious responses that get served to thousands of users. Here's how it works and how to stop it.
Anay Pandya
1,503 words
Anay Pandya
Founder of ZeriFlow · 10 years fullstack engineering · About the author
Key Takeaways
Web cache poisoning is an attack technique where an adversary manipulates a caching layer into storing and serving a malicious HTTP response to all users who subsequently request the same resource. Unlike attacks that target a single user, a successfully poisoned cache entry becomes a persistent threat that affects every visitor until the cache is purged — making it one of the most scalable web vulnerabilities in existence.
<div class="zf-stat-callout" style="background:#0d1117;border:1px solid rgba(16,185,129,0.25);border-left:3px solid #10b981;border-radius:4px;padding:16px 20px;margin:24px 0"> <p style="margin:0 0 4px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.15em;color:#10b981;font-family:monospace">ZeriFlow Data — 12,400+ sites analyzed</p> <p style="margin:0;font-size:13px;color:#e2e8f0;line-height:1.6;font-family:monospace">In ZeriFlow's dataset of 12,400+ scanned sites, the average security score is 52/100 — with 68% failing at least one critical check in categories including TLS configuration, check your security headers, DNS authentication, and cookie handling.</p> </div>
Keep reading
Is your site actually secure?
Run a free check — 60 seconds
Web caches (CDNs, reverse proxies like Varnish or Nginx, or browser caches) store copies of HTTP responses to reduce load and improve performance. When a request comes in, the cache checks a *cache key* — typically the URL and sometimes specific headers — to decide whether to return a stored response or forward the request to the origin server.
The critical concept: not all headers that influence the response are included in the cache key. These are called unkeyed inputs.
An unkeyed header is a request header that the origin server reads and uses to construct its response — but which the cache ignores when deciding whether to serve a cached copy.
Classic examples:
- X-Forwarded-Host
- X-Forwarded-Scheme
- X-Original-URL
- X-Rewrite-URL
- X-HTTP-Method-Override
If the origin server uses X-Forwarded-Host to construct absolute URLs in the response (for redirects, canonical tags, or JavaScript), but the cache only keys on the URL path, then an attacker can:
X-Forwarded-Host: evil.comhttps://evil.com/script.jsThe attacker sends requests with varying header values and observes whether the response changes while the cache key stays the same. Tools like Burp Suite's Param Miner automate this process.
GET / HTTP/1.1
Host: targetsite.com
X-Forwarded-Host: evil.comIf the response contains evil.com anywhere (in a redirect, a script src, a canonical URL), the attacker has found an exploitable unkeyed input.
The attacker crafts a request that causes the origin to generate a response containing malicious content — a JavaScript injection, a redirect to a phishing page, or a poisoned resource URL.
GET / HTTP/1.1
Host: targetsite.com
X-Forwarded-Host: evil.com
Cache-Buster: unique123The attacker times the request to hit the cache during its refresh cycle — or uses a cache buster on the first request (to reach the origin), removes it on the second request to prime the cache.
Once cached, every user who requests the page receives the poisoned version until the cache TTL expires or is manually invalidated.
If a page reads query parameters from document.location and passes them to innerHTML or eval, an attacker can inject a malicious query parameter that gets cached and delivered to all users.
Some servers process request bodies for GET requests. If the cache ignores the body but the origin reads it to generate the response, the body becomes an unkeyed vector.
Web frameworks often trust the Host header to generate self-referencing links. If an intermediate proxy rewrites Host before it reaches the cache, poisoning becomes straightforward:
GET /login HTTP/1.1
Host: evil.comPassword reset emails, OAuth redirects, and absolute URLs in responses are all impacted.
Query string parsing inconsistencies between the cache and the origin can allow attackers to inject parameters the cache ignores but the origin processes.
The Cache-Control header is your most powerful tool against cache poisoning. ZeriFlow checks Cache-Control as part of its security header audit.
For sensitive or dynamic pages:
Cache-Control: no-store, no-cache, must-revalidateFor static assets you do want cached:
Cache-Control: public, max-age=31536000, immutableKey directives:
- no-store: Never cache this response, not even conditionally
- no-cache: Cache it, but always revalidate with the origin before serving
- private: Only cache in the user's browser, not in shared CDN/proxy caches
- Vary: Tell the cache to include specific headers in the cache key
If your server legitimately uses a header like Accept-Language or X-Forwarded-Host to vary the response, you can instruct the cache to include it in the key using the Vary header:
Vary: Accept-Language, X-Forwarded-HostThis forces the cache to store separate copies for each unique value of those headers, neutralizing the unkeyed input attack vector for those specific headers.
X-Forwarded-* headers? Does it trust the Host header for URL generation? Every such header is a potential vector.Cache-Control: no-store or private.Vary. If it doesn't, strip it at the proxy layer before it reaches your origin.ZeriFlow's security scanner checks your site's Cache-Control, Pragma, and related caching headers as part of its 80+ security checks. Misconfigured caching headers are one of the most common findings — and one of the easiest to fix.
A: No, they're opposite attacks. Cache poisoning involves getting the cache to store a malicious response that is then served to victims. Cache deception tricks the cache into storing a *victim's* sensitive response, which the attacker can then retrieve. Both exploit the same cache architecture, but with different goals and methods.
A: No. HTTPS encrypts the transport layer, but cache poisoning happens at the application layer. The cache operates on decrypted responses. HTTPS is essential for other reasons but does not protect against cache poisoning.
A: CDNs can be the vectors for cache poisoning, not the defenders. CDN configurations that fail to key on all response-influencing headers are the most common source of cache poisoning vulnerabilities. Each CDN (Cloudflare, Fastly, CloudFront) has its own default behavior — review yours carefully.
A: Use Burp Suite with the Param Miner extension, which automates the discovery of unkeyed headers and parameters. James Kettle's research on cache poisoning (PortSwigger Web Security) provides a comprehensive methodology. Always test on a staging environment first.
A: DNS cache poisoning targets DNS resolvers to redirect domain lookups to malicious IPs. Web cache poisoning targets HTTP caches to serve malicious HTTP responses. Both exploit caching mechanisms but operate at different layers of the network stack.
Web cache poisoning is a force multiplier for attackers — a single successful exploit affects every user who visits your site until the cache is cleared. The defenses are well-understood: audit your caching headers, restrict what your origin trusts, configure Vary correctly, and apply strict Cache-Control to dynamic responses.
The first step is knowing where you stand. Automated security scanning gives you the baseline.
<!-- zf-internal-links -->
Related resources
Website Vulnerability Scanner
Run a broader website security audit across headers, TLS, DNS, cookies, SEO, and disclosure checks.
Security Headers Checker
Check CSP, HSTS, X-Frame-Options, and other response headers.
SSL Checker
Review TLS certificate, HTTPS, and transport security signals.
DMARC Checker
Validate email authentication records for domain spoofing protection.
CSP Checker
Review Content-Security-Policy coverage and common gaps.
June 24, 2026
Best Security Tools for AI Startups
Monitor your security score
Schedule recurring scans and catch regressions after deployments.