# Cache poisoning via unkeyed input

Unkeyed headers, params or path forms that the cache and origin interpret differently, then get stored.

_Area: Web injection and code execution. Seen in 2 disclosed reports; latest 2022-09-02. Updated 2026-10-23._

## How it works
A cache stores a response under a key built from only some request parts (usually host, path, selected query params). Everything else — other headers, fragments, duplicate params, path oddities — is forwarded to the origin but not keyed. If the origin reacts to that unkeyed input (reflects it, routes on it, normalizes it differently), the attacker's influence gets stored under a key other users request. The broken assumption: "what the cache keys on equals what the origin consumes." Any divergence turns a per-request reflection into a shared, stored one.

## Where it shows up
- Headers used to build URLs or markup (X-Forwarded-Host, X-Forwarded-Scheme, X-Host) interpolated into HTML/CSS without escaping [E4](https://bugbountylibrary.com/r/h1%3A394016.md)
- Path normalization differences: dot-segments, encoded slashes, case, trailing chars handled by CDN but not origin [E2](https://bugbountylibrary.com/r/blog%3Anokline-github-io-bugbounty-2022-09-02-glassdoor-cache-poisoning-html.md)
- Duplicate or encoded query params where cache keys the first and backend uses the last [E3](https://bugbountylibrary.com/r/blog%3Ayoust-in-posts-cache-poisoning-at-scale.md)
- URL fragments forwarded to origin but not keyed [E3](https://bugbountylibrary.com/r/blog%3Ayoust-in-posts-cache-poisoning-at-scale.md)
- Methods like TRACE that echo the full request, giving a byte-controlled body [E1](https://bugbountylibrary.com/r/blog%3Aportswigger-net-research-trace-desync-attack.md)
- Cacheable responses (CSS, fonts, preload links) built from request headers [E4](https://bugbountylibrary.com/r/h1%3A394016.md)

## How to review
Identify the cache key exactly (host, path, query subset) and list every other input the origin reads. The invariant: no unkeyed input may change response bytes or routing. Check that the CDN and origin parse paths, params and headers identically — send a path with dot-segments or encoded slashes under a cached prefix and compare what is cached versus served [E2](https://bugbountylibrary.com/r/blog%3Anokline-github-io-bugbounty-2022-09-02-glassdoor-cache-poisoning-html.md). Confirm reflection points escape output and that responses built from headers are not cacheable [E4](https://bugbountylibrary.com/r/h1%3A394016.md). Verify TRACE and other echo methods are disabled at the edge [E1](https://bugbountylibrary.com/r/blog%3Aportswigger-net-research-trace-desync-attack.md).

## Variants seen
- TRACE reflection plus HTTP/2 desync and HEAD concatenation to control cached bytes [E1](https://bugbountylibrary.com/r/blog%3Aportswigger-net-research-trace-desync-attack.md)
- CDN dot-segment normalization vs origin non-normalization, caching self-XSS under a different path [E2](https://bugbountylibrary.com/r/blog%3Anokline-github-io-bugbounty-2022-09-02-glassdoor-cache-poisoning-html.md)
- Unkeyed headers, fragments, duplicate/illegal params across many CDNs [E3](https://bugbountylibrary.com/r/blog%3Ayoust-in-posts-cache-poisoning-at-scale.md)
- X-Forwarded-Host reflected unescaped into font-face CSS/HTML, cached 60s [E4](https://bugbountylibrary.com/r/h1%3A394016.md)

## Impact and severity
Stored XSS served to all users of a cached path, redirects, DoS, and full app compromise [E1](https://bugbountylibrary.com/r/blog%3Aportswigger-net-research-trace-desync-attack.md)[E2](https://bugbountylibrary.com/r/blog%3Anokline-github-io-bugbounty-2022-09-02-glassdoor-cache-poisoning-html.md)[E3](https://bugbountylibrary.com/r/blog%3Ayoust-in-posts-cache-poisoning-at-scale.md)[E4](https://bugbountylibrary.com/r/h1%3A394016.md). Severity rises with cache TTL, breadth of affected paths, and whether the poisoned response executes script in victim browsers.

## Evidence
- E1: https://bugbountylibrary.com/r/blog%3Aportswigger-net-research-trace-desync-attack.md
- E2: https://bugbountylibrary.com/r/blog%3Anokline-github-io-bugbounty-2022-09-02-glassdoor-cache-poisoning-html.md
- E3: https://bugbountylibrary.com/r/blog%3Ayoust-in-posts-cache-poisoning-at-scale.md
- E4: https://bugbountylibrary.com/r/h1%3A394016.md
