What Is Web Cache Poisoning?

On this page
  1. How does cache poisoning work?
  2. What makes it dangerous?
  3. How do you cache safely?

Web cache poisoning stores a harmful response in a shared cache — a CDN or reverse proxy — so that it is then served to every user who requests that resource. A single crafted request can poison one cache entry and harm thousands of subsequent visitors. It turns a caching layer, meant for performance, into a distribution channel for an attack.

How does cache poisoning work?#

Caches serve a stored response based on a cache key — usually the URL plus a few headers. Anything that influences the response but is not part of the key is an unkeyed input, and it is the attacker’s lever:

  1. The attacker finds an unkeyed header (say, X-Forwarded-Host) that the app reflects into the response.
  2. They send a request with a malicious value that produces a harmful response.
  3. The cache stores that response under the normal key.
  4. Every visitor requesting the URL gets the poisoned copy.

If the reflected value lands in a script src or link, cache poisoning becomes stored XSS at scale.

What makes it dangerous?#

PropertyEffect
Shared cacheOne request poisons many users
PersistentThe bad response stays until eviction
Amplifies other bugsTurns reflected flaws into stored, mass-delivered ones

How do you cache safely?#

  • Key on everything that affects the response — or do not vary the response on it.
  • Do not reflect unkeyed headers like X-Forwarded-Host into responses.
  • Cache only truly static, safe resources; mark user-specific responses private/no-store.
  • Understand your CDN’s keying — misconfiguration here is the usual root cause.

Cache poisoning can be chained from request smuggling. More at the Web Security hub.

Frequently asked questions#

What is web cache poisoning?

Web cache poisoning is an attack where a malicious response is stored in a shared cache — a CDN or reverse proxy — and then served to every user who requests that resource. The attacker crafts a request that influences the response via an input the cache ignores when deciding what to store, so one poisoned entry harms many victims.

What is an unkeyed input?

A cache decides which stored response to serve using a cache key, typically the URL and some headers. Any request input that affects the response but is not part of the key is unkeyed. If an unkeyed header changes the response, an attacker can poison the cached copy for everyone sharing that key.

Sources & further reading