cloudflare / cloudflare/cloudflare-docs
Cache Deception Armor: undocumented .js / application/json exception allows Web Cache Deception
- Dominant language
- MDX
- Stars
- 5.2k
- Forks
- 16.7k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 337
Description
### Existing documentation URL(s)
- https://developers.cloudflare.com/cache/cache-security/cache-deception-armor/
### What changes are you suggesting?
## Description
The [Cache Deception Armor (CDA) documentation](https://developers.cloudflare.com/cache/cache-security/cache-deception-armor/) states that CDA *"will verify a URL's extension matches the returned Content-Type"* and *"when a mismatch that could result in a Web Cache Deception attack is found, Cloudflare does not cache the response."*
However, CDA does **not** block caching when a `.js` URL returns `Content-Type: application/json`. This exception is not listed in the [documented exceptions](https://developers.cloudflare.com/cache/cache-security/cache-deception-armor/#exceptions), leaving customers unaware that CDA does not protect against this specific mismatch.
## Current documented exceptions
- `application/octet-stream` for any extension
- `.jpg` served as `image/webp`
- `.gif` served as `video/webm`
- *"other cases that we think are unlikely to be attacks"*
## Missing exception
- **`.js` served as `application/json`** - CDA treats these as compatible and does not block caching.
## Why this matters
- `application/json` responses are the **primary target** of Web Cache Deception attacks (session tokens, PII, API keys)
- Cloudflare intentionally excludes `.json` from the [default cached file extensions](https://developers.cloudflare.com/cache/concepts/default-cache-behavior/#default-cached-file-extensions) because JSON carries sensitive data
- Customers enabling CDA reasonably expect it to block `.js` + `application/json` mismatches, since it blocks all other tested extension/Content-Type mismatches (`.css`, `.jpg`, `.png`, `.gif`, `.svg`, `.ico`, `.pdf`)
- Without documentation, customers have no way to know they need additional mitigation for this case
## Verified behavior
Tested with CDA enabled (`cache_deception_armor: true`) and Origin Cache Control active:
| Extension | Origin Content-Type | `cf-cache-status` | CDA Result |
|-----------|--------------------|--------------------|------------|
| `.css` | `application/json` | `BYPASS` | Blocked (documented) |
| `.jpg` | `application/json` | `BYPASS` | Blocked (documented) |
| `.png` | `application/json` | `BYPASS` | Blocked (documented) |
| `.gif` | `application/json` | `BYPASS` | Blocked (documented) |
| `.svg` | `application/json` | `BYPASS` | Blocked (documented) |
| `.ico` | `application/json` | `BYPASS` | Blocked (documented) |
| `.pdf` | `application/json` | `BYPASS` | Blocked (documented) |
| **`.js`** | **`application/json`** | **`MISS → HIT`** | **Not blocked (undocumented)** |
The same behavior applies to `application/json; charset=utf-8`.
## Suggested documentation update
Add the following bullet to the [Exceptions section](https://developers.cloudflare.com/cache/cache-security/cache-deception-armor/#exceptions):
> Cloudflare allows `.js` to be served as `application/json`, because JSON is considered syntactically compatible with JavaScript. If your origin returns sensitive JSON API responses on paths that could end in `.js`, set `Cache-Control: no-store` or `Cache-Control: private` on those responses to prevent caching.
## File to update
`src/content/docs/cache/cache-security/cache-deception-armor.mdx` — Exceptions section.
### Additional information
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.