HTTP Request Smuggling to Web Cache Poisoning in Bug Bounty
Request smuggling becomes much easier to sell when the next hop is a shared cache. The smuggled prefix alters how the backend handles a cacheable request; the edge then stores the wrong response under an innocent URL. One poisoned entry can reach many users without waiting for a lucky connection collision.
That reach is exactly why you should test with a cache key nobody else will request.
Picture the chain
Assume a front end and origin disagree about where request A ends. Your leftover bytes become the beginning of request B. If B is a cache miss for /assets/page?cb=private-canary, the origin may process a path or header chosen by you while the cache still associates the response with the original visible URL.
The result could cache:
- A redirect to an attacker-controlled domain
- An error page containing reflected script
- Private content under a public key
- A response generated with a poisoned
Hostor routing header - A frontend bundle response replaced by HTML
The cache is the amplifier, not the root cause. Your report should show both halves.
Use an isolated cache key
Choose a random query parameter of at least 16 characters and confirm it affects the cache key. Request it twice normally. Look for Age, X-Cache: HIT, CF-Cache-Status, or stable cache-specific headers. If both requests reach the origin or the response is private, find another route.
Do not target /, a shared JavaScript filename, or login pages used by real people. A unique path such as /static/test-not-found-7f3... is safer. Some caches ignore unknown query parameters, so verify isolation by comparing two canaries; if one poison appears on the other, stop immediately.
Controlled proof
First establish the smuggling primitive using timing or your own follow-up request. Then craft the smuggled request so its visible effect is harmless: perhaps a 302 to https://example.com/bug-bounty-canary or a reflected marker in an error response.
Send the poisoning sequence once. Fetch the unique public URL over a clean connection without the malformed framing. A strong proof shows:
- Clean URL initially returns response A.
- Smuggling sequence causes backend response B.
- Clean URL now returns B with a cache-hit indicator.
- Purge or wait for the short TTL, then confirm response A returns.
Never keep hitting it “for reliability.” Each attempt can desynchronize a pooled connection and affect unrelated traffic.
Why ordinary cache poisoning tests miss this
Classic web cache poisoning relies on an unkeyed input such as X-Forwarded-Host. The cache and backend agree on request boundaries; they disagree only on which input shapes the response. Smuggling adds boundary confusion, so even headers stripped by the front end may be reconstructed inside the smuggled request.
That opens routes behind edge normalization and can defeat cache-key assumptions. It also creates more failure modes. A WAF-generated redirect is not an origin response, and a browser cache hit is not shared-cache poisoning. Reproduce with a fresh client and inspect edge headers.
Report without creating an incident
Give the program your unique key, exact UTC timestamps, TTL, raw requests, and cleanup result. State whether poisoning crosses anonymous sessions and regions. If you only proved a harmless redirect, explain credible impact such as stored XSS delivery or credential phishing without deploying it.
Fixes belong at both layers: reject ambiguous HTTP framing, align parser behavior across proxy hops, avoid unsafe HTTP/2 downgrading, and prevent sensitive or attacker-shaped responses from becoming publicly cacheable.
PortSwigger covers smuggling consequences in exploiting HTTP request smuggling and cache fundamentals in its web cache poisoning material. Read both before touching a shared route.