The popular library 'axios-cache-interceptor' (< 1.11.1) failed to respect the HTTP 'Vary' header. This effectively treats authenticated responses as global public assets. If an Admin visits a page, the library caches it. If a Guest visits the same page immediately after, they get the Admin's cached view, bypassing backend authentication checks entirely.
A critical failure in cache key generation allows unprivileged users to inherit the sessions of privileged users in server-side implementations of axios-cache-interceptor.
There is an old joke in computer science: 'There are only two hard things in CS: cache invalidation and naming things.' In the world of web security, we can add a third hard thing: context-aware caching. Speed is addictive. Developers love slapping a caching layer on top of their HTTP clients to make their Node.js backends feel snappy. Enter axios-cache-interceptor, a library designed to bring performance to the ubiquitous Axios client.
But here is the catch: when you use a caching interceptor in a server-side environment (like a Backend-for-Frontend or a proxy), that interceptor is often a singleton. It lives as long as the server process lives, and it shares its memory across every single request the server handles.
If that cache isn't smart enough to distinguish between 'User A asking for /profile' and 'User B asking for /profile', you have just built a mechanism to accidentally broadcast private data to the public. CVE-2025-69202 is exactly this scenario: a logic flaw where the library decided that the URL was the only thing that mattered, turning private sessions into public broadcasts.
The HTTP specification includes a very specific header for exactly this problem: Vary. When an upstream server responds with Vary: Authorization, it is explicitly shouting, 'Do not serve this cached response to anyone unless they have the exact same Authorization header!'
Prior to version 1.11.1, axios-cache-interceptor essentially plugged its ears and ignored this shouting. The library's logic for generating a cache key—the unique ID used to store and retrieve data—was primarily derived from the request URL and method. It did not automatically factor in headers that vary the content.
[!NOTE] The Logic Trap: The developer assumes
GET /api/user/123always returns the same JSON. But in many REST APIs,GET /api/mereturns different data depending on theAuthorizationbearer token. By ignoring the token in the cache key, the library treats the endpoint as static content.
This leads to a classic Race Condition or Time-of-Check Time-of-Use (TOCTOU) style vulnerability, but purely in the caching layer. The upstream API is secure. The application logic is secure. But the middleware sitting in between them is happily handing out photocopies of the Admin's bank statements to anyone who asks.
The fix, introduced in commit 49a808059dfc081b9cc23d48f243d55dfce15f01, is elegant in its simplicity but revealing in what was missing. The maintainers introduced a mechanism to inspect the Vary header from the response and, crucially, pull those specific headers from the new request into the cache key generator.
Here is a conceptual look at the logic change:
// VULNERABLE LOGIC (Simplified)
function generateCacheKey(request) {
return hash(request.method + request.url);
}
// PATCHED LOGIC (Simplified)
function generateCacheKey(request, cachedResponse) {
let key = request.method + request.url;
// Check if the cached entry has a 'Vary' requirement
if (cachedResponse && cachedResponse.headers.vary) {
const varyHeaders = cachedResponse.headers.vary.split(',');
varyHeaders.forEach(header => {
// Add the actual value of the header (e.g., the Auth Token) to the key
key += `::${header}=${request.headers[header]}`;
});
}
return hash(key);
}The patch also included a fix to ensure header lookup is case-insensitive (Authorization vs authorization), preventing bypasses where a malicious user might just change the casing of their headers to dodge the check.
To exploit this, an attacker does not need fancy tools. They just need timing. The target is a Node.js application acting as a proxy or BFF (Backend-For-Frontend) using the vulnerable interceptor.
The Scenario:
/dashboard/stats. This triggers a backend request to the upstream API.200 OK with sensitive financial data and the header Vary: Authorization.axios-cache-interceptor stores this response. The key is simply GET:/dashboard/stats./dashboard/stats using their own (or no) authentication token.GET:/dashboard/stats.This is particularly devastating because it is invisible to logs on the Upstream API. The Attacker's request never even reaches the real backend; it is served entirely from the Node.js application's memory.
The impact of CVE-2025-69202 depends entirely on architecture.
Client-Side (Browser): If this library is used inside a React/Vue app running in the user's browser, the risk is minimal. The cache is local to that user's device. Unless the attacker has physical access to the device, they cannot poison the cache for others.
Server-Side (Node.js): This is the kill zone. In microservices, SSR (Server-Side Rendering) apps, or API gateways, a single instance of the library handles traffic for thousands of users. A single cached admin response can technically compromise every subsequent user who requests that endpoint before the TTL (Time To Live) expires.
We are looking at:
The remediation is straightforward, but the lessons learned should be permanent.
axios-cache-interceptor to version 1.11.1 or higher. This version enables Vary header support by default.Cache-Control: private for sensitive data. While the vulnerable interceptor might have ignored Vary, a compliant cache must respect private directives by not storing them in shared caches (though implementation varies by library).If you cannot upgrade immediately, you must disable caching for any route that requires Authentication or returns personalized data.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
axios-cache-interceptor Arthur Fiorette | < 1.11.1 | 1.11.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-524 (Sensitive Information in Cache) |
| Attack Vector | Network (AV:N) |
| Impact | Confidentiality High, Authorization Bypass |
| CVSS Score | 6.5 (Medium) |
| Exploit Status | PoC Available (in unit tests) |
| Fix Version | 1.11.1 |
Use of Cache Containing Sensitive Information
Get the latest CVE analysis reports delivered to your inbox.