Before you start: This lesson assumes HTTP request and response anatomy from http-fundamentals, Cache-Control and Vary header knowledge from security-headers-hardening, and XSS familiarity from the Cross-Site Scripting & Client-Side category — the poisoning impact (stored XSS at cache scale) will not make sense without it.
Web cache poisoning and web cache deception are infrastructure-level attacks that abuse a shared cache — a CDN or reverse proxy in front of the application — and so affect not just you but other users of that cache. They are caching-layer misconfigurations, catalogued under OWASP A05:2021 (Security Misconfiguration) and related to CWE-525 (web cache containing sensitive information).
How a shared cache works
A shared cache sits between users and the origin server and tries to avoid round-trips:
many users ──▶ shared cache (CDN / reverse proxy) ──▶ origin (app server)When a request arrives, the cache builds a cache key from selected parts of the request — usually the method, host, and URL path (and sometimes the query string). If a stored response already matches that key, the cache serves it directly to the user, never touching the origin.
Keyed versus unkeyed input
Everything about these attacks comes from one distinction:
- Keyed input — the parts of the request the cache includes in the key (path, often query string). Different keyed input means a different cache entry.
- Unkeyed input — the parts the cache ignores when building the key, but that the application still reads when generating the response. Headers like
X-Forwarded-HostandX-Forwarded-Forare classic unkeyed inputs.
That gap is the engine of cache poisoning: if the application reflects an unkeyed header into its response, an attacker can send a request that looks identical to a normal one from the cache's point of view but carries a malicious header — and the cache will store and re-serve that poisoned response to everyone.
What you will do in this lesson
- Understand cache keys and the keyed/unkeyed distinction.
- Distinguish poisoning (write a bad response everyone gets) from deception (steal a victim's private cached response).
- Find an unkeyed header reflected into a cacheable response.
- Name an unkeyed header used to poison a cache, and learn the durable fix.
Required external lab. This is not reproducible in a bare NovaCart instance — it needs a caching layer / CDN in front of the app. Use the PortSwigger Web Security Academy Web Cache Poisoning and Web Cache Deception labs (free account required at portswigger.net).
Estimated time: ten to fifteen minutes.
When you are ready, send the Continue signal.