hunt-cache-poison – Security skill for AI agents
Hunting skill for cache poison vulnerabilities. Built from 10 public bug bounty reports including X-Forwarded-Host poisoning, X-HTTP-Method-Override / GCS cache, reflected→stored XSS via cache, classic Omer-Gil Web Cache Deception, Cloudflare Cache Deception Armor bypass, session-token cache deception, Akamai hop-by-ho
Install the hunt-cache-poison skill with one command
Pick the tool you use, copy the command and paste it in your terminal. The skill lands in that tool's skills folder and is ready in your next session.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/hunt-cache-poison-868e8.tgz | tar xz -C ~/.claude/skills
Call it in Claude Code: /hunt-cache-poison – then describe the task you want done.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/hunt-cache-poison-868e8.tgz | tar xz -C ~/.codex/skills
Call it in Codex: $hunt-cache-poison – then describe the task you want done.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/hunt-cache-poison-868e8.tgz | tar xz -C ~/.hermes/skills
Call it in Hermes Agent: /hunt-cache-poison – then describe the task you want done.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/hunt-cache-poison-868e8.tgz | tar xz -C ~/.deepcode/skills
Call it in DeepSeek: /hunt-cache-poison – then describe the task you want done.
SKILL.md content
Crown Jewel Targets
Cache poisoning is high-value because a single poisoned cache entry can affect thousands or millions of victims simultaneously — one request, mass exploitation. Payout scales with blast radius.
Highest-value targets:
- CDN-served assets (cdn.shopify.com, cloudfront distributions, Fastly/Akamai edges) — poisoning these affects every visitor globally
- E-commerce platforms with affiliate/referral flows (Shopify, WooCommerce storefronts) — session hijack or affiliate fraud potential
- Gaming platforms with update servers (rockstargames updates.* domains) — DoS on update delivery = widespread client breakage
- Authentication endpoints served through caches — leads to account takeover (the highest severity variant)
- Asset CDNs (JS/CSS delivery) — XSS payload delivery at scale
- SaaS multi-tenant platforms — one poisoned response bleeds into all tenants sharing a cache key
Asset types that pay most: CDN hostnames, subdomain-per-tenant patterns, update/download servers, login/account pages cached incorrectly, affiliate link shorteners.
---
Attack Surface Signals
URL patterns to look for:
cdn.,assets.,static.,updates.,downloads.subdomains- URL path structures with extensions that look static:
/path/to/page.css,/account.php/nonexistent.jpg - Affiliate/link shortener endpoints:
/link/,/go/,/ref/,/out/ - Paths that mix dynamic content with cacheable-looking URLs
Response headers that signal a cache:
X-Cache: HIT / MISS
X-Cache-Status: HIT
CF-Cache-Status: HIT / MISS (Cloudflare)
Age: <nonzero>
Via: 1.1 varnish / cloudfront / fastly
Cache-Control: public, max-age=...
Surrogate-Control: max-age=...
X-Served-By: cache-...JS/tech stack signals:
- Fastly, Varnish, Cloudfront, Akamai, Nginx proxy_cache in response headers
- Shopify/Linkpop stacks with third-party integrations
- Platforms using path-based routing without normalizing trailing segments
- Servers that reflect unvalidated headers into responses (Host, X-Forwarded-Host, X-Original-URL)
Dangerous header candidates (unkeyed inputs):
X-Forwarded-Host
X-Host
X-Forwarded-Scheme
X-Original-URL
X-Rewrite-URL
Forwarded
X-HTTP-Method-Override---
Step-by-Step Hunting Methodology
1. Map cache infrastructure. Send a GET to the target and inspect response headers. Identify the caching layer (Cloudflare, Fastly, Varnish, Nginx). Note Age, X-Cache, CF-Cache-Status headers.
2. Identify cache key components. Send two identical requests — if Age increments, the response is cached. Vary headers one-by-one (e.g., add X-Forwarded-Host) to determine which headers are NOT included in the cache key (unkeyed).
3. Test unkeyed header reflection. Add X-Forwarded-Host: evil.com and check if the value appears in the response body (redirects, canonical links, CSP headers, JS src attributes, meta tags). Append a unique cache-busting query parameter (e.g. ?cb=<random>) so the probe lands on a cache MISS under a throwaway key — this verifies reflection without prematurely storing a live poison entry under the real, victim-shared cache key. (Param Miner's "Guess headers" mode is the canonical Burp toolchain for discovering these unkeyed headers/parameters automatically.)
4. Test URL path manipulation (Web Cache Deception). Append fake static extensions to dynamic endpoints:
GET /account/profile.cssGET /dashboard/settings.jpgGET /affiliate-link/target.js
Check if the server returns dynamic content AND the cache stores it.
5. Test for DoS via cache poisoning. Send a request with a header that causes a 4xx/5xx error and check if that error response gets cached:
- Malformed
Hostheader X-Forwarded-Hostpointing to an invalid host- Oversized headers that trigger backend errors
6. Confirm unkeyed parameter poisoning. Try query parameter fatigue or HTTP parameter pollution:
GET /page?utm_source="><script>alert(1)</script>
Check if the param is reflected and cached for clean requests to /page.
7. Validate cache storage. After sending a potentially poisoned request, immediately request the same URL WITHOUT the malicious header from a different IP or incognito session. If you receive the poisoned response — it's confirmed.
8. Measure cache TTL. Check Cache-Control: max-age and Age to understand how long the poison persists and whether it's exploitable before expiry.
9. Check affiliate/link flows specifically. For platforms like Linkpop, test whether the referrer/product URL is embedded in a cacheable response that another user will receive.
10. Document blast radius. Determine: global CDN edge (worldwide), regional cache, or single-server cache. This directly affects severity rating.
---
Payload & Detection Patterns
Confirm caching behavior:
# Send twice, compare Age header
curl --max-time 30 --connect-timeout 10 -s -I "https://target.com/page" | grep -i "age\|x-cache\|cf-cache"
curl --max-time 30 --connect-timeout 10 -s -I "https://target.com/page" | grep -i "age\|x-cache\|cf-cache"Test unkeyed X-Forwarded-Host:
curl --max-time 30 --connect-timeout 10 -s -H "X-Forwarded-Host: evil.attacker.com" \
"https://target.com/page" | grep -i "evil.attacker.com"Test Web Cache Deception (path appending):
# Authenticated session cookie required
curl --max-time 30 --connect-timeout 10 -s -b "session=YOUR_SESSION" \
"https://target.com/account/profile.css"
# Then fetch without auth from another client
curl --max-time 30 --connect-timeout 10 -s "https://target.com/account/profile.css"Force cache miss to test poison without hitting cached version:
# Use a unique cache-busting query param to land on a fresh key — do NOT rely on
# client-sent "Cache-Control: no-cache" (per RFC 7234 it requests revalidation, not
# skip-storage, and Cloudflare/Fastly/Akamai generally ignore it on cacheable assets).
curl --max-time 30 --connect-timeout 10 -s -H "X-Forwarded-Host: canary.attacker.com" \
"https://target.com/page?cb=$RANDOM"DoS via poisoned error response:
curl --max-time 30 --connect-timeout 10 -s -H "X-Forwarded-Host: aaaaaaaaaaa.invalid" \
"https://target.com/js/app.js" -I
# Check if next clean request returns error
curl --max-time 30 --connect-timeout 10 -s -I "https://target.com/js/app.js" | grep "HTTP/"Grep patterns in Burp/ZAP response history:
# Headers indicating cache hit
X-Cache: HIT
CF-Cache-Status: HIT
Age: [1-9]
# Reflected unkeyed input in body
evil\.attacker\.com
canary\d+\.
# Web cache deception indicators
Content-Type: text/css (but response is HTML/JSON)
Cache-Control: public.*max-age (on authenticated endpoint)Parameter pollution test:
curl --max-time 30 --connect-timeout 10 -s "https://target.com/page?cb=1¶m=CANARY_VALUE" | grep CANARY_VALUE
# Then check if clean request returns poisoned version
curl --max-time 30 --connect-timeout 10 -s "https://target.com/page?cb=1"Burp Suite Intruder wordlist for unkeyed headers:
X-Forwarded-Host
X-Host
X-Forwarded-Server
X-HTTP-Host-Override
Forwarded
X-Original-URL
X-Rewrite-URL
X-Forwarded-Scheme
X-Forwarded-Proto
True-Client-IP---
Common Root Causes
1. CDN misconfiguration — caching based on URL path only. Engineers configure cache rules like "cache everything matching *.js" without realizing the path can be appended to dynamic routes. The origin server ignores the extra path segments, but the CDN uses them as cache keys.
2. Unkeyed header forwarding. Developers configure reverse proxies to forward X-Forwarded-Host to backends for URL generation (canonical links, redirects, password reset emails) without including it in the cache key. The CDN caches the poisoned response.
3. Web Cache Deception via permissive routing. Frameworks that normalize URLs (e.g., Rails, Express) accept /account/settings.css and serve the same response as /account/settings. The CDN sees a .css extension and applies aggressive caching rules.
4. Shared caching of multi-tenant responses. SaaS platforms that use a single CDN without tenant isolation in the cache key allow cross-tenant cache poisoning.
5. Error responses cached without thought. Backend errors (404, 500) triggered by attacker-controlled input get cached, causing DoS for legitimate users. Developers implement caching without excluding error status codes.
6. Lazy Vary header implementation. Developers know they should add Vary: X-Forwarded-Host but forget, or CDNs strip/ignore Vary headers entirely (Cloudflare historically strips Vary on some asset types).
7. Third-party integrations with URL reflection. Affiliate/link tracking systems (like Shopify Linkpop) reflect the destination URL in metadata, canonical tags, or redirects — and these get cached globally.
---
Bypass Techniques
… (full content is in the download package)
Related skills
- hunt-cicd – Hunt CI/CD pipeline vulnerabilities — GitHub Actions workflow injection…
- api-security – Authorized security assessment of REST, GraphQL, WebSocket, and SOAP APIs: discovery…
- hunt-csrf – Hunting skill for csrf vulnerabilities. Built from 15 public bug bounty reports…
- hunt-django – Hunt Django-specific vulnerabilities: DRF permission gaps, ORM injection, and admin…
- hunt-fastapi – Hunt FastAPI-specific vulnerabilities: dependency injection gaps, Pydantic coercion, and…
- geopandas – Guidance and local audit tools for Python workflows that directly use GeoPandas…
- security-best-practices – Perform language and framework specific security best-practice reviews and suggest…
- hunt-graphql – Hunting skill for graphql vulnerabilities. Built from 12 public bug bounty reports…