← Back to blog
Blog Detail

Web Cache Poisoning and Cache Deception: Detection, Impact, and CTEM-Style Exposure Reduction

Web cache poisoning and cache deception turn your CDN into an attack delivery system: one crafted request can serve malicious content to every user, or expose private responses cached as static files. This guide covers the mechanics, the telemetry that catches both, and how CTEM-style continuous exposure management keeps cache layers visible.

Trusteed Team
Trusteed Editorial
Written On
Sep 30, 2026
Category
CTEM
Read Time
14 min read
  • CTEM
  • Trusteed
  • Web Cache Poisoning
  • Cache Deception
  • Attack Surface Management
  • CDN Security
  • Application Security
  • Vulnerability Prioritization
Web Cache Poisoning and Cache Deception: Detection, Impact, and CTEM-Style Exposure Reduction

Web Cache Poisoning and Cache Deception: Detection, Impact, and CTEM-Style Exposure Reduction

TL;DR

  • Web cache poisoning abuses an input the cache ignores when building its cache key. An attacker poisons one cached response; every visitor after them receives the attacker's version.
  • Web cache deception abuses the opposite direction: it tricks a cache into storing a private, authenticated response under a URL that looks like a static asset, then fetches that copy without credentials.
  • Neither class is patchable. There is no CVE, no vendor advisory, no upgrade path. The exposure lives in your CDN configuration, reverse proxy rules, application routing, and path normalization behavior.
  • Most teams cannot answer a basic question: how many caching layers sit in front of our origins right now? CDN edge, load balancer, reverse proxy, framework-level micro-cache, service worker. You cannot test what you have not inventoried.
  • Trusteed CTEM keeps the web surface — domains, services, technologies, and the hosts behind caching layers — in a continuous inventory, then validates exploitability and business context before anything reaches an analyst queue.
  • The remediation loop is: inventory caches, test unkeyed inputs and path confusion, fix cache key and origin routing rules, then keep testing, because CDN settings drift with every deploy.

What is web cache poisoning (and cache deception)?

Both attack classes are HTTP caching bugs, and both hinge on a small set of definitions that every practitioner should carry in their head.

  • Cache key — the subset of request attributes (typically method, host, path, and sometimes query string) a cache uses to decide whether two requests should receive the same stored response.
  • Unkeyed input — any part of the request that can influence the response but is not part of the cache key: headers, cookies, body parameters, path segments, method overrides.
  • Web cache poisoning — an attacker supplies an unkeyed input that gets reflected into a cacheable response, then waits for the cache to store and serve that response to everyone.
  • Web cache deception — an attacker persuades the cache that a dynamic, private response is a static asset, so the cache stores and serves it as if it were public.

A useful mental model: cache poisoning is a write primitive against shared infrastructure, and cache deception is a read primitive against private data. Both require the same two preconditions — a caching layer you do not fully control, and a disagreement between the cache and the origin about what a given request actually means.

This is why cache attacks sit awkwardly in traditional vulnerability management. Nothing is unpatched. Nothing is misconfigured in a way a CVE scanner recognizes. The flaw is architectural, in how your stack interprets and stores HTTP.

Why it matters now

Edge caching is no longer an optimization you opt into. It is a default in most modern stacks: managed CDNs, framework-level caching in Next.js and similar runtimes, API gateways that cache JSON responses, and service workers that cache at the browser. Each layer is another place where a cache key can be computed incorrectly.

The business impact is disproportionate to the effort required to exploit it.

  • At-scale XSS and defacement. A single poisoned response can inject a script tag or redirect into a page served to thousands of users. The attacker never touches your origin, and your WAF sees legitimate-looking cached responses.
  • Session and credential theft. Cache deception harvests authenticated HTML and API JSON — profile pages, account objects, tokens embedded in markup — and serves them to anyone who requests the poisoned URL before the TTL expires.
  • Availability loss. Poisoning a redirect, a 301 loop, or an enormous response body into a high-traffic path is a cheap denial-of-service primitive against a shared cache.
  • Privacy and regulatory exposure. If a cache stores personal data under a public URL, that is a data exposure event whether or not anyone notices. Regulators do not distinguish between a database leak and a cache leak.
  • Detection debt. Cache attacks are quiet. There is no exploit payload in your WAF logs by default, no malware signature, and no alert from a standard vulnerability scanner. Teams typically learn about them from a researcher disclosure or a customer report.

The operational reality is that caching changes on every deploy. A framework upgrade alters header handling. A CDN rule changes the cache key. An engineer adds Cache-Control: public to fix a performance ticket. Exposure management for cache layers has to be continuous, not annual.

How cache poisoning and cache deception attacks work

Cache poisoning: write once, serve to everyone

  1. Find a cacheable response. Look for Age, X-Cache: Hit, CF-Cache-Status: HIT, Cache-Control: public, max-age=…, or s-maxage. Static assets are trivially cacheable, but the interesting targets are HTML pages and API JSON cached for even a few seconds — that window is enough.
  2. Enumerate unkeyed inputs. Common candidates include X-Forwarded-Host, X-Forwarded-Scheme, X-Forwarded-Proto, X-Host, X-Original-URL, X-Rewrite-URL, X-HTTP-Method-Override, Referer, and cookie values that affect rendering. "Fat GET" requests — parameters smuggled into a GET body — belong on the same list.
  3. Confirm reflection. If setting X-Forwarded-Host: attacker.example changes a canonical link, a script src, a redirect Location, or a JSON field, you have a candidate. If the response is cacheable, you have an exploitable one.
  4. Poison with a cache buster. Add a unique query string per attempt so you never test against the copy real users receive. Then observe whether a request that did not send the header receives the modified response.
  5. Escalate. Reflected values become stored XSS at cache scale, open redirects, or content injection. A redirect loop cached into a popular path becomes an outage.

Cache key confusion

Caches normalize differently from origins. Some ignore trailing slashes. Some decode %2f differently. Some key on the raw path while the origin routes on a decoded, normalized version. Where the two disagree about which resource a request addresses, an attacker who can poison one endpoint can often serve that payload at a different, higher-traffic URL. This family of issues — cache key confusion through delimiter and encoding mismatches — is the reason cache attacks keep resurfacing years after the original research.

Cache deception: make private look static

  1. The attacker sends a victim a link such as https://app.example/account/profile/nonexistent.css.
  2. The victim, authenticated, clicks it. The origin's router strips or ignores the extension and returns the account page.
  3. The cache sees a .css suffix, applies a static-asset rule with a long TTL, and stores the authenticated response body — including the victim's email, account details, or markup-embedded tokens — under a public URL.
  4. The attacker requests that URL with no cookies at all, and reads the cached copy.

Variants use delimiter confusion (;, %00, %0a, %2e, encoded slashes), appended path segments, and API endpoints (/api/me.css). When the target is a JSON API returning user objects, the same trick leaks structured records at scale for the duration of the TTL.

Root causes worth fixing at the source

  • Missing Cache-Control: private, no-store on authenticated responses.
  • Missing or incomplete Vary headers on responses that change by header or cookie.
  • Origin routing that tolerates arbitrary path suffixes instead of returning 404.
  • Applications that trust X-Forwarded-* headers from any client.
  • Extension-based cache rules that ignore Content-Type.

Detection and visibility

Dark CTEM insight card titled Cache Exposure Signals listing four cache telemetry signals: a .css request returning text/html, a cached response containing Set-Cookie, a novel X-Forwarded-Host value seen once, and a canary marker found in a later response. Below, a split panel contrasts the edge log showing a cache HIT with no cookies against the origin log showing an authenticated 200 session, flagged as cache deception. Footer credits Trusteed Threat Research.

Cache attacks are detectable, but only if you are collecting the right signals and comparing them across layers.

  • Extension and content-type mismatches. Alert on .css, .js, .png, .ico paths returning Content-Type: text/html or application/json. This is the single highest-yield rule for cache deception.
  • Origin vs. edge log correlation. Join CDN logs to origin logs on request ID. Look for requests where the edge reports HIT with no Cookie header while the origin recorded a 200 for an authenticated session, and for raw paths that normalize to the same origin resource.
  • Cached responses carrying private markers. Any cached response containing Set-Cookie, Authorization, a session identifier, or user-specific fields is a finding, not a curiosity.
  • Unkeyed header telemetry. Count distinct values of X-Forwarded-Host, X-Forwarded-Scheme, and X-Original-URL per host. Legitimate proxies send a small, predictable set. A novel value appearing once, then appearing inside a response body, is a smoking gun.
  • Cache poisoning canaries. Send a scheduled synthetic request to high-value cacheable endpoints with a unique marker in both the query string and an unkeyed header. If that marker later appears in a response to a request that never sent it, the cache is storing attacker-controlled content. This is the highest-signal control available and it belongs in continuous monitoring, not a quarterly test.
  • Cache indicator inventory. Track which hosts emit Age, X-Cache, or CF-Cache-Status, and intersect that list with hosts that serve authenticated content. That intersection is your real exposure list — usually much smaller than your total host count, and much more valuable to watch.
  • Validate before alerting. Thousands of X-Forwarded-Host probes arrive from the internet every week. Alerting on the raw request pattern produces fatigue that buries the one real finding.

Reduce risk: best practices

  1. Inventory every caching layer. CDN, load balancer, reverse proxy, application cache, service worker. Assign an owner to each and record it in your asset inventory.
  2. Never cache authenticated responses. Apply Cache-Control: private, no-store at the framework level, not per-route, so new endpoints inherit the safe default.
  3. Be explicit with Vary. If a response changes based on a header or cookie, that header belongs in Vary — or the input should be stripped before it reaches the cache.
  4. Normalize consistently between cache and origin. Make the cache and the origin agree on path handling, and return 404 for dynamic routes with static-looking suffixes instead of a 200.
  5. Stop reflecting unkeyed headers. Maintain an allowlist of trusted headers, terminate proxies yourself, and build absolute URLs from configuration rather than from client-supplied X-Forwarded-Host.
  6. Strip what you do not need at the edge. If an application never reads X-Original-URL, drop it before it can influence anything.
  7. Keep TTLs short on anything dynamic — but treat short TTLs as damage reduction, not mitigation. A five-minute poisoned window still hits every user in that window.
  8. Run canary tests continuously on login, account, and checkout paths, and after every deploy.
  9. Instrument the SOC gate. Route cache-related findings through validation so analysts only see confirmed, exploitable conditions.
  10. Re-test after CDN, framework, and routing changes. Cache behavior changes silently with configuration and dependency upgrades.

How Trusteed CTEM helps

Trusteed CTEM insight card: raw cache signals (discovered hosts, surface scans, header anomalies) pass through a shield-labelled validation gate that suppresses 62% of noise, producing three prioritized findings with EPSS and KEV badges and should_alarm indicators, above a 30-day sparkline showing cache exposure down 38%.

Trusteed CTEM (trusteed.io) approaches cache-layer exposure the same way it approaches any other part of the attack surface: discover it continuously, test it in a structured way, and only escalate what is genuinely actionable.

  • Continuous attack surface and asset inventory. Domains, IPs, services, and technologies are discovered passively and actively, so CDN-fronted hosts and newly spun-up endpoints do not stay invisible between assessments.
  • Structured, scheduled scanning. Network, web surface, API surface, SSL/TLS, and mail/DNS posture checks run as ongoing scan plans rather than a one-time point-in-time exercise — because cache configuration drifts with every deploy.
  • Findings with real context. Scanner detections are enriched with catalog CVE data, EPSS and KEV signals, and exploit references, so routing and caching exposure gets weighed alongside everything else competing for engineer time.
  • A validation gate before the SOC queue. Not every scanner hit becomes an alarm. Trusteed validates exploitability and business context so dashboards and analyst queues stay focused on actionable risk instead of raw signal volume.
  • Deeper application and API coverage. A dedicated API surface testing worker complements generic scanning, and a deep DAST worker goes further on critical applications — useful when the exploitable behavior sits behind a routing or caching layer rather than on the page itself.
  • Compliance and reporting views. Framework-oriented views and customer reporting let you show exposure trends and remediation status to stakeholders, not just a list of URLs.

Operators work the findings in the tenant app at app.trusteed.io, where exposure is tracked continuously rather than rediscovered each quarter.

Web cache exposure: point tools vs. Trusteed CTEM

Capability Typical point tool Trusteed CTEM
Coverage model Point-in-time scan of hostnames you already know Continuous discovery and monitoring across domains, IPs, services, and technologies
Asset context Flat list of URLs and template results Findings tied to hosts, services, and tech stack so caching layers are visible in context
Prioritization Raw severity from template output Catalog CVE data, EPSS/KEV context, and exploit references applied to each finding
Noise handling Every hit surfaces with equal weight Validation and SOC gate so only actionable risk reaches analysts
API and app depth Generic web templates Dedicated API surface worker plus deep DAST for critical applications
Reporting JSON or console output Framework-oriented views and customer-ready reporting

Template-based scanners such as Nuclei remain excellent for CI checks and container scanning. They produce signals. CTEM is the workflow around those signals: inventory, validation, prioritization, and continuous re-testing.

FAQ

Is web cache poisoning a vulnerability or a misconfiguration? It is neither in the classic sense. It is an emergent property of how a cache and an origin interpret the same request. There is no CVE and no patch — remediation is a combination of cache configuration, application routing, and header-handling changes.

How is cache deception different from cache poisoning? Poisoning writes attacker-controlled content into a shared cache so other users receive it. Deception reads private content out of a shared cache by making a dynamic response look cacheable. One is an injection primitive; the other is a disclosure primitive. They frequently share root causes.

Will a WAF stop these attacks? Not reliably. Poisoning requests look like ordinary HTTP with an unusual header, and the malicious response is served from the cache to victims without the WAF inspecting it. Deception requests are plain GETs to static-looking paths. WAF rules can reduce the attack surface but should not be treated as the control.

Can cache poisoning be exploited without any user interaction? Poisoning itself requires no interaction — the attacker only needs the cache to store the response. The impact usually materializes when other users request that cached URL, whether through normal browsing or a link. Deception, by contrast, requires a victim to be authenticated and to visit an attacker-supplied URL.

What is the fastest check for a cache misconfiguration? Send a request to a cacheable endpoint with a unique query string as a cache buster and a test value in an unkeyed header such as X-Forwarded-Host. Then request the same URL with the buster but without the header. If the test value appears in the second response, the cache stored attacker-influenced content. For deception, request an authenticated page with a .css suffix and check whether the response is cached and served without cookies.

How do I know if my origin is handing private responses to a cache? Inspect the response headers on authenticated endpoints. Look for Cache-Control values that permit shared caching, missing Vary headers on responses that vary by header or cookie, and any Set-Cookie or user-specific data inside a response the edge reports as a HIT.

How is CTEM different from running a scanner? A scanner produces a snapshot of signals against a list of targets you provided. CTEM is the operating loop around that: continuously discovering what you own, testing it on a schedule, validating which findings are exploitable and business-relevant, and tracking whether remediation actually reduced exposure. The distinction matters most for architectural issues like cache behavior, where the finding is only useful if you know which hosts and layers it applies to.

Do I still need to worry if I use a CDN with default settings? Yes. Default settings are optimized for performance and compatibility, not for your application's routing behavior. The mismatch between a CDN's extension-based caching rules and your application's path handling is exactly where cache deception lives.

Related resources

Join Our Newsletter

Trusteed keeps you informed: emerging risks, platform updates, and practical guides for faster defense.

Web Cache Poisoning & Deception: A CTEM Playbook