Web cache poisoning occurs when an attacker causes a shared cache to store a response influenced by malicious request input and later serve that stored response to other users. The dangerous part is amplification: one crafted request can affect many subsequent requests if the cache and origin application disagree about which inputs define a unique response. The vulnerability is therefore a composition failure between application logic, proxy behavior, and cache-key design.
The proxy, load-balancing, and request-path foundations of N10-009 make cache behavior understandable, but deliberately poisoning a shared cache is an application-security problem beyond its named objectives. Effective Network testing compares the origin’s response variation with the cache key: if a header or query value changes rendered content without being included in the key, one user can influence a response served to another. An accurate diagnosis identifies that mismatch and distinguishes it from cache deception, where a sensitive response is cached because a path appears static.
A defender needs to understand three things: what the origin uses to generate a response, what the cache uses to identify an entry, and which responses are eligible for shared reuse. Poisoning becomes possible when attacker-controlled input changes the origin response but is omitted from the cache key or otherwise normalized differently by the intermediary.
The cache key is the security boundary
A shared cache normally builds a key from some combination of scheme, host, path, query string, and selected headers. The origin may also vary its response based on other inputs such as `X-Forwarded-Host`, language headers, device hints, or routing metadata. If an unkeyed input changes a cacheable response, one user can influence content later delivered to another.
This is why edge caching must be designed as part of application behavior, not as an invisible performance layer. Cache policy, origin routing, header trust, and response generation need one consistent model of identity. A fast cache with a weak key can turn a small input-validation mistake into a distributed integrity failure.
Unkeyed headers are a common source of mismatch
Reverse proxies often add or forward headers such as `Host`, `Forwarded`, `X-Forwarded-Host`, or `X-Forwarded-Proto`. Applications may use those values to build absolute URLs, redirects, canonical tags, or script references. If the cache ignores the same header, an attacker can supply a value that changes the response while the cache still considers the request equivalent to ordinary traffic.
A reverse proxy might cache a response under a URL while the origin varies the rendered page using a header the cache ignores. In that case the apparent request identity is different at the two layers, and a response generated for one context may become reusable in another. A safe diagnostic uses a controlled test origin and non-sensitive markers to compare response variation against cache keys and cache-hit indicators; it should not attempt to poison traffic for real users. The lasting fix aligns the cache key and origin behavior or prevents the response from being shared.
Trust boundaries matter here. A public client should not be able to inject a forwarding header that the application treats as authoritative unless the edge proxy strips or overwrites it. The application should know which intermediary is trusted and which headers are guaranteed to be produced by that intermediary rather than by the Internet client.
Query parameters create another mismatch class. Some caches ignore tracking parameters, reorder parameters, or exclude selected names from the key while the origin application still reads them. If an ignored parameter changes a script URL, locale, template, or redirect, an attacker may be able to store the modified response under the key used by ordinary visitors. The correct defense is not to key every arbitrary parameter; it is to ensure that excluded parameters cannot influence shared response content.
The `Vary` response header can tell compliant caches that selected request headers change the representation, but it should not be treated as a universal authorization control. Varying on a highly unique value such as a session cookie can destroy cache efficiency, and intermediary behavior still needs verification. Sensitive responses should generally be excluded from shared caching rather than relying on an extremely granular key to keep users apart.
Poisoning is different from cache deception
Web cache poisoning alters a response that the cache later serves broadly. Web cache deception instead tricks the cache into storing sensitive or personalized content under a URL that appears cacheable. The mechanisms differ, but both expose the same architectural mistake: cache eligibility and cache identity are being inferred from URL appearance rather than from the application’s real authorization and response semantics.
A strong application security model therefore treats caching as part of data isolation. Personalized responses, authorization-dependent content, and tenant-specific data should not become shared merely because they were reached through a route that looks static. Cache policy must follow the sensitivity and variability of the response.
Normalization disagreements create hidden alternate keys
Caches and origins may normalize paths, query parameters, ports, hostnames, or encoded characters differently. A proxy might treat two URLs as equivalent while the origin routes them to different handlers, or the origin might ignore a query parameter that the cache includes. Attackers look for these mismatches because they can create a request that stores one representation and affects users requesting another.
Testing should therefore compare what the cache believes with what the origin believes. Change one request component at a time and observe both response content and cache behavior. Response headers such as `Age`, cache-status indicators, surrogate keys, and vendor diagnostics can help show whether a response was generated, stored, or reused.
Cacheability should be tested explicitly. Status code, method, response headers, cookies, surrogate directives, and CDN configuration all influence whether an object is stored. A poisoning probe that changes content but never produces a cache hit is evidence of input influence, not yet of shared-cache persistence. The distinction prevents teams from overstating findings and focuses remediation on the actual boundary that is broken.
Testing should also use a harmless marker and an isolated cache key whenever possible. Security validation must not place executable content into a production shared cache or create a victim-visible redirect. A unique path, temporary hostname, or controlled test environment can prove key behavior while keeping the experiment from becoming the incident it is supposed to prevent.
A poisoned response needs persistence to become dangerous
A reflected input is not automatically cache poisoning. The response must also be cacheable and stored under a key that victims will later request. This is why a practical test confirms persistence: send a crafted request, remove the malicious input, then request the ordinary victim URL from a separate session and observe whether the modified content is served from the cache.
Operators should test through the same production-like path that users follow. A direct request to the origin can look safe because it bypasses the CDN or reverse proxy where the cache-key mismatch exists. Conversely, a CDN-only test can hide origin behaviors that appear only when particular forwarding headers or path rewrites are present.
Remediation must fix both the origin and the cache policy
Purging poisoned entries is incident containment, not root-cause remediation. The origin should stop reflecting or trusting unsafe inputs, and the cache must either include every legitimate response-varying input in the key or reject those inputs from cacheable routes. Sensitive or personalized responses should have explicit cache-control behavior that prevents shared storage.
The same discipline appears in API security: controls need to match actual request processing rather than an assumed diagram. An API gateway, CDN, reverse proxy, and application can each normalize requests differently. Security review should trace the concrete request that reaches every layer.
Purge design is part of incident readiness. Large delivery stacks can have browser, CDN, reverse-proxy, and application caches simultaneously. Purging only one layer may leave the poisoned object available elsewhere, while a global purge can create a severe origin-load spike. Teams should know how to invalidate a precise key, a path family, and an emergency broader scope, and should test those procedures before an active poisoning event.
Detection should focus on unexplained cache variance
Security teams can look for unusual forwarding headers, repeated cache purges, sudden content changes across unrelated users, or discrepancies between origin logs and edge responses. Synthetic tests can request the same resource through different header and query combinations and flag unexpected variance. The signal is not merely a cache hit; it is a cache hit that contains content inconsistent with the key that selected it.
Incident response should preserve both edge and origin evidence. If responders purge immediately without recording the poisoned key, headers, response metadata, and source requests, they may remove the strongest evidence of how the mismatch worked. A reproducible request pair—poisoning request and victim request—often provides the clearest path to a durable fix.
Configuration ownership should be explicit because cache policy often spans application code, CDN rules, load balancers, and infrastructure-as-code repositories. If no team owns the combined behavior, one group can add a header-dependent feature while another excludes that header from the cache key. Security review should treat those cross-team changes as one request-processing contract.
Teams should also test host canonicalization and redirect behavior because alternate hostnames can create separate cache entries or unsafe shared redirects. A canonical-host policy should be enforced consistently at the trusted edge and the origin. When both layers normalize differently, the cache can store content under a host identity the application did not intend to serve.
The durable lesson is request identity
Caches are safe when all layers agree on what makes one response equivalent to another. That agreement includes route selection, host and scheme, meaningful query parameters, trusted headers, authorization state, tenant identity, and content sensitivity. Performance optimizations become security controls as soon as stored content is reused across users.
For networking study, web cache poisoning is a reminder that proxies and application delivery devices do more than move packets. They interpret requests, transform headers, and reuse responses. Understanding that behavior makes it easier to reason about both troubleshooting and security failures at the application edge.