A shared cookie jar that nobody asked for — undici's opt-in cache happily serves one user's session to the next
CVE-2026-84933 affects undici versions 7.0.0 – 7.29.0 and 8.0.0 – 8.10.1. The cache interceptor, when enabled in shared mode (the default *when the interceptor is active*), stores HTTP responses without stripping or rejecting Set-Cookie headers. A cacheable response carrying Set-Cookie — e.g. one with Cache-Control: public, max-age=3600 — gets stored verbatim and replayed to every subsequent caller whose request matches the same cache key. The result is cross-user cookie disclosure: caller B receives caller A's session cookie, and an attacker-controlled upstream can inject arbitrary cookies into all downstream consumers.
The vendor rates this MEDIUM / 6.5 with AC:H, and that rating is *defensible*. The single most important friction point is that the cache interceptor is opt-in — it is not enabled by default. A developer must explicitly compose the interceptor via setGlobalDispatcher(getGlobalDispatcher().compose(interceptors.cache())). Despite undici's massive install base (~175 million weekly npm downloads), the fraction of deployments that enable the cache interceptor in shared mode is small — likely single-digit percent. For those that do, the impact is real: session hijack, cookie injection, and potential auth bypass in multi-tenant Node.js services. But the AC:H vector and opt-in gating make 6.5 a fair ceiling; noisgate trims it to 5.5 for the opt-in friction.
4 steps from start to impact.
Upstream returns Set-Cookie with cacheable directives
Set-Cookie header and Cache-Control: public, max-age=<N>. Alternatively, a legitimate upstream may unintentionally combine these headers, which is uncommon but not unheard of in misconfigured CDN origins.- Attacker controls or can influence at least one upstream origin
- Upstream response includes Set-Cookie alongside cacheable Cache-Control directives
- Most legitimate origins do not combine Set-Cookie with public cache directives
- MITM requires a separate position on the network or DNS compromise
Undici cache interceptor stores response with Set-Cookie intact
Set-Cookie, the full response — including the session cookie — is written to the cache store (in-memory, SQLite, or Redis). The cache key is derived from the request method, URL, and Vary headers. No special conditions beyond the interceptor being enabled are needed.- Cache interceptor explicitly enabled via
interceptors.cache() - Shared cache mode (default when interceptor is active)
- Cache interceptor is opt-in — most undici consumers never enable it
- Developers using private cache mode (
type: 'private') are not affected in the same cross-user way
Second caller receives first caller's cookie
Set-Cookie header from user A's session. User B's HTTP client or browser now sets the cookie, effectively assuming user A's session. In a server-side proxy or SSR framework, user B's response is sent downstream with user A's cookie baked in.- A second request matches the same cache key before TTL expiry
- The application does not independently strip Set-Cookie from cached responses
- Cache key collision requires same method + URL + Vary-matched headers
- Short max-age values reduce the exploitation window
Session hijack or cookie injection
- Application relies on cookies for authentication or authorization
- No additional session-binding (e.g. IP pinning, device fingerprinting) is enforced
- Modern frameworks often use token-based auth (JWT in Authorization header) rather than cookies for API-to-API calls
- Server-side undici callers are less likely to honor Set-Cookie than browser-based flows
The supporting signals.
| In-the-Wild Exploitation | None observed. Not listed on CISA KEV. No known campaigns as of 2026-09-05. |
|---|---|
| Proof of Concept | No public PoC. The advisory describes the mechanism in sufficient detail to reproduce in a test harness, but no standalone exploit repo has been published. |
| EPSS Score | Not yet scored — CVE disclosed 2026-09-04; EPSS data typically populates within 7–14 days of NVD publication. |
| KEV Status | Not listed. No CISA KEV entry as of 2026-09-05. |
| CVSS Vector | CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:L/A:N — Network-accessible, high attack complexity, no privileges or user interaction needed. High confidentiality impact (cookie disclosure), low integrity impact (cookie injection), no availability impact. |
| Affected Versions | undici 7.0.0 – 7.29.0 and 8.0.0 – 8.10.1. The cache interceptor was introduced in undici 7.0.0. |
| Fixed Versions | 7.29.1 and 8.10.2 — the fix strips Set-Cookie from responses before cache storage in shared mode. |
| Installed Base | undici has ~175 million weekly npm downloads. However, the cache interceptor is opt-in and not enabled by default, drastically limiting the exposed population. |
| Disclosure Date | 2026-09-04 via GitHub Security Advisory GHSA-4cwx-7wf7-3272 (covers related cache issues). |
| Reporter | Not publicly attributed in the advisory. |
noisgate verdict.
The single most decisive factor is the opt-in gating: undici's cache interceptor must be explicitly enabled by the developer, meaning the vast majority of the ~175M weekly-download install base is unexposed. For the small fraction of deployments that do enable shared caching, cross-user cookie disclosure is a real but bounded risk that does not reach fleet-scale or identity-scale blast radius.
Why this verdict
- Opt-in friction is the dominant downgrade factor. The cache interceptor is not enabled by default in undici. A developer must explicitly compose it into the dispatcher chain. This transforms a 175M-download-base vulnerability into one affecting a small opt-in subset — likely <5% of installations.
- AC:H already baked in. The vendor's CVSS vector sets Attack Complexity to High, acknowledging that exploitation requires specific conditions (cacheable + Set-Cookie + matching cache key + shared mode). This is accurate.
- No exploitation signal. Zero KEV listing, zero known campaigns, no public PoC as of day-one disclosure. The practical risk to an enterprise scanning for this today is near zero.
- Role multiplier: (a) *Low-value role* — dev tooling, CLI scripts, test harnesses using undici: chain does not succeed because cache interceptor is almost never enabled. (b) *Typical role* — Node.js API server using undici as an HTTP client: chain succeeds only if cache interceptor is explicitly enabled in shared mode AND upstream sends Set-Cookie with cacheable directives. Blast radius is tenant-level (one service's users). (c) *High-value role* — Node.js reverse proxy / API gateway / SSR framework (e.g. Next.js, Nuxt) with undici shared caching enabled and serving multi-tenant authenticated traffic: blast radius is cross-user session hijack within that service. This is serious but bounded to the service, not fleet/domain/supply-chain scale. undici is not canonically infrastructure (not a hypervisor, IdP, PAM, CA, or network edge appliance), so the HIGH floor does not trigger.
Why not higher?
Upgrading to HIGH would require either active exploitation, a public weaponized PoC, or a blast radius that reaches fleet/domain/supply-chain scale. None of these conditions are met. The cache interceptor is opt-in, the attack complexity is high, and even in the worst case the blast radius is limited to cross-user disclosure within a single Node.js service — not lateral movement, domain takeover, or supply-chain compromise.
Why not lower?
Dropping to LOW would understate the impact for the deployments that *do* use shared caching. In those environments, cross-user session cookie disclosure is a genuine confidentiality breach that could enable account takeover. The CVSS C:H rating is warranted for affected deployments, and the network-accessible attack vector with no authentication requirement keeps a baseline of concern.
What to do — in priority order.
- Disable or switch to private cache mode — If you enabled the cache interceptor, switch to
type: 'private'in the interceptor options or disable the interceptor entirely until you can upgrade. This eliminates the cross-user disclosure vector. No noisgate mitigation SLA applies (MEDIUM verdict), so go straight to the 365-day remediation window, but this is a one-line config change worth making immediately. - Strip Set-Cookie before caching at the application layer — If you have a custom cache store or middleware, add a pre-store hook that deletes the
Set-Cookieheader from responses before they enter the cache. This replicates what the patch does. - Upgrade undici to 7.29.1 or 8.10.2 — The definitive fix. The patch ensures Set-Cookie headers are stripped from responses before shared-cache storage. Fits within the noisgate remediation SLA of 365 days for MEDIUM.
- Audit upstream Cache-Control directives — Review upstream origins to ensure they are not combining
Set-CookiewithCache-Control: public. This is an HTTP best-practice violation regardless of this CVE.
- WAF rules — This is an application-layer caching logic bug inside the Node.js process. No network-level WAF can inspect or modify undici's internal cache store behavior.
- CDN-level Set-Cookie stripping — Stripping Set-Cookie at the CDN edge does not help because undici's cache interceptor operates on the origin response *after* the CDN, inside the Node.js process.
Crowdsourced verification payload.
Run this on any host where a Node.js application uses undici. It checks the installed undici version against the vulnerable ranges. Requires node and npm in PATH. No elevated privileges needed. Example: bash check_undici_cve_2026_84933.sh /path/to/your/node/project
#!/usr/bin/env bash\n# check_undici_cve_2026_84933.sh\n# Checks whether the installed undici version is vulnerable to CVE-2026-84933\n# Usage: bash check_undici_cve_2026_84933.sh [project_dir]\n# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN\n\nset -euo pipefail\n\nPROJECT_DIR=\"${1:-.}\"\n\nif [ ! -d \"$PROJECT_DIR/node_modules/undici\" ]; then\n echo \"UNKNOWN - undici not found in $PROJECT_DIR/node_modules/\"\n exit 2\nfi\n\nVERSION=$(node -e \"console.log(require('$PROJECT_DIR/node_modules/undici/package.json').version)\" 2>/dev/null)\n\nif [ -z \"$VERSION\" ]; then\n echo \"UNKNOWN - could not read undici version\"\n exit 2\nfi\n\n# Parse major.minor.patch\nIFS='.' read -r MAJOR MINOR PATCH <<< \"$VERSION\"\n\nVULN=false\n\n# Check 7.0.0 - 7.29.0\nif [ \"$MAJOR\" -eq 7 ]; then\n if [ \"$MINOR\" -lt 29 ]; then\n VULN=true\n elif [ \"$MINOR\" -eq 29 ] && [ \"$PATCH\" -lt 1 ]; then\n VULN=true\n fi\nfi\n\n# Check 8.0.0 - 8.10.1\nif [ \"$MAJOR\" -eq 8 ]; then\n if [ \"$MINOR\" -lt 10 ]; then\n VULN=true\n elif [ \"$MINOR\" -eq 10 ] && [ \"$PATCH\" -lt 2 ]; then\n VULN=true\n fi\nfi\n\nif [ \"$VULN\" = true ]; then\n echo \"VULNERABLE - undici $VERSION is affected by CVE-2026-84933\"\n exit 1\nelse\n echo \"PATCHED - undici $VERSION is not affected by CVE-2026-84933\"\n exit 0\nfiIf you remember one thing.
interceptors.cache(), you are not affected — confirm this and move on. If any service *does* use shared caching, switch it to private mode or disable it now, then upgrade undici to 7.29.1 (v7 branch) or 8.10.2 (v8 branch) within the noisgate remediation SLA of 365 days. There is no noisgate mitigation SLA for MEDIUM — go straight to the remediation window. No active exploitation or public PoC exists as of 2026-09-05, so this is a scheduled patch, not a fire drill. Monday morning: grep your repos for interceptors.cache to identify exposed services, flip any shared caches to private mode, and queue the upgrade in your next dependency refresh cycle.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.