Install
$ agentstack add skill-unboundcompute-security-agent-skills-testing-web-cache-attacks ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Testing web cache attacks: the bug is the key, not the app
A shared cache trades correctness for speed by serving one stored response to many users, and that sharing is the vulnerability. If an attacker can influence what gets stored (poisoning), everyone downstream receives their payload; if an attacker can make the cache store someone else's private response under a key the attacker controls (deception), they read data that was never theirs. Both live in the gap between what the cache keys on and what actually determines the response.
When to use
- You are reviewing a CDN, a reverse proxy, or any shared HTTP cache in front of an
app.
- Responses that depend on headers or user identity are served through a cache.
- You are assessing whether authenticated content can be cached and re-served.
Scope check
Test caches and apps you own or are authorized to test. Use benign markers and your own accounts; do not poison responses served to real users or read real users' data. If you can't name the authorization, stop.
The loop
- Map the cache and its key. Identify the caching layer in front of the app and
determine the cache key: which parts of the request (path, query, some headers) decide whether two requests share a stored response. Everything the response depends on but the key ignores is an unkeyed input, and unkeyed inputs are where both attacks live.
- Find what is cacheable. Determine which responses the cache stores and for how
long: static-looking paths, extensions, explicit cache headers, and any response the cache decides to keep. A response that is cached but depends on request data the key omits is a poisoning candidate.
- Test cache poisoning through unkeyed input. Send a request whose unkeyed header
or parameter changes the response (a reflected header, a header that sets a link or script origin, a header that triggers an error page), then confirm the poisoned response is stored and served to a normal request without your input. If a later clean request receives your payload, the cache is poisoned for every user of that key.
- Test cache deception. Request an authenticated, private page but shape the URL
so the cache treats it as a static cacheable resource (appending a path segment or an extension the cache stores while the app still returns the private content). If the private response is stored under that URL, an attacker who requests the same URL retrieves the victim's data. Confirm what the cache keys on versus what the app authorizes on.
- Rate impact and record. Poisoning that injects script or redirects affects
every downstream user of the key (high to critical); deception that exposes another user's authenticated data is a direct confidentiality breach. Record confirmed poisoning and deception paths, and configurations where the cache key covers every response-affecting input and refuses to cache authenticated content (killed) in the schema.
Where caches leak
- The bug is the key, not the app. The application can be correct while the cache
serves the wrong response to the wrong person.
- Unkeyed input is the whole game. Any header or parameter that changes the
response but not the key is a lever.
- The cache and the app disagree on identity. The app authorizes per user; the
cache serves per key. Deception exploits that disagreement.
- One stored response, many victims. Poisoning scales to everyone sharing the
key, which is what makes it severe.
Worked example (a confirm and a kill)
> Confirm. A page reflects an unkeyed header into an absolute script URL. The > attacker sends a request with that header pointing at their host; the cache stores > the response and serves it, with the attacker-controlled script origin, to every > subsequent visitor of that path. Confirmed cache poisoning, critical, > remediation = include the header in the cache key or stop reflecting it, and do not > cache responses that vary on unkeyed input. > > Kill. A profile page returns private, authenticated content with a directive > that forbids shared caching, the cache refuses to store any authenticated response, > and the cache key includes every input that changes the response. A deception > attempt (appended static extension) is not stored because the response is marked > non-cacheable. Killed, kill_reason = "authenticated responses are > non-cacheable; cache key covers all response-affecting inputs; no unkeyed lever."
Rationalizations to reject
- "The app is authorized correctly." → Authorization is per user; the cache serves
per key. Deception bypasses the app entirely.
- "It's just a caching layer." → It decides what every user receives. A poisoned
entry is a stored, shared payload.
- "That header doesn't affect the key." → If it affects the response, that is
exactly the poisoning lever.
- "Only static files are cached." → Deception makes a dynamic private page look
static. Verify what the cache actually stores.
Executing this in practice
You need to observe the caching layer's behavior: the cache key, which responses are stored, and how the app responds to unkeyed inputs and to deception-shaped URLs. Comparing keyed versus unkeyed requests and reading the cache hit/miss and age signals on responses is enough; the key-versus-response analysis is the method.
Related
mapping-attack-surface- locating the caching layers and shared infrastructure in
front of the app.
testing-llm-insecure-output-handling- a poisoned cached response is one more sink
that serves attacker content.
writing-vuln-reports- a poisoning or deception finding to a reproducible writeup.- [FINDING-SCHEMA.md](../../FINDING-SCHEMA.md) - source = the unkeyed input or
deception URL, sink = the stored response served to a victim.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: UnboundCompute
- Source: UnboundCompute/security-agent-skills
- License: MIT
- Homepage: https://security.unboundcompute.com
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.