← Back to Feed CACHED · 2026-09-04 20:08:50 · CACHE_KEY CVE-2026-84933
CVE-2026-84933 · CWE-200 · Disclosed 2026-09-04

undici cache interceptor cross-user Set-Cookie disclosure in shared cache mode

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

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.

"Opt-in cache feature leaks cookies between callers, but most Node.js apps never turn it on."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Upstream returns Set-Cookie with cacheable directives

The attacker controls or influences an upstream HTTP server (or is a man-in-the-middle). The server returns a response with both a 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.
Conditions required:
  • Attacker controls or can influence at least one upstream origin
  • Upstream response includes Set-Cookie alongside cacheable Cache-Control directives
Where this breaks in practice:
  • Most legitimate origins do not combine Set-Cookie with public cache directives
  • MITM requires a separate position on the network or DNS compromise
STEP 02

Undici cache interceptor stores response with Set-Cookie intact

Because the cache interceptor does not check for or strip 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.
Conditions required:
  • Cache interceptor explicitly enabled via interceptors.cache()
  • Shared cache mode (default when interceptor is active)
Where this breaks in practice:
  • 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
Detection/coverage: Application-level logging of cached response headers would reveal Set-Cookie in stored entries; no standard scanner detects this pattern.
STEP 03

Second caller receives first caller's cookie

A different caller (user B) issues a request that matches the same cache key. The interceptor serves the cached response, including the 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.
Conditions required:
  • A second request matches the same cache key before TTL expiry
  • The application does not independently strip Set-Cookie from cached responses
Where this breaks in practice:
  • Cache key collision requires same method + URL + Vary-matched headers
  • Short max-age values reduce the exploitation window
STEP 04

Session hijack or cookie injection

With user A's session cookie, the attacker (or an innocent user B) can impersonate user A on the target application. If the attacker controlled the upstream, they can inject arbitrary cookies into all subsequent callers — enabling session fixation, CSRF token override, or auth bypass at scale across the Node.js service's consumer base.
Conditions required:
  • Application relies on cookies for authentication or authorization
  • No additional session-binding (e.g. IP pinning, device fingerprinting) is enforced
Where this breaks in practice:
  • 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
03 · Compensating Control

1
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.
2
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-Cookie header from responses before they enter the cache. This replicates what the patch does.
3
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.
4
Audit upstream Cache-Control directives — Review upstream origins to ensure they are not combining Set-Cookie with Cache-Control: public. This is an HTTP best-practice violation regardless of this CVE.
What doesn't work
  • 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.
04 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationNone observed. Not listed on CISA KEV. No known campaigns as of 2026-09-05.
Proof of ConceptNo 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 ScoreNot yet scored — CVE disclosed 2026-09-04; EPSS data typically populates within 7–14 days of NVD publication.
KEV StatusNot listed. No CISA KEV entry as of 2026-09-05.
CVSS VectorCVSS: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 Versionsundici 7.0.0 – 7.29.0 and 8.0.0 – 8.10.1. The cache interceptor was introduced in undici 7.0.0.
Fixed Versions7.29.1 and 8.10.2 — the fix strips Set-Cookie from responses before cache storage in shared mode.
Installed Baseundici has ~175 million weekly npm downloads. However, the cache interceptor is opt-in and not enabled by default, drastically limiting the exposed population.
Disclosure Date2026-09-04 via GitHub Security Advisory GHSA-4cwx-7wf7-3272 (covers related cache issues).
ReporterNot publicly attributed in the advisory.

Sources.

  1. CVE-2026-84933 — THREATINT
  2. GHSA-4cwx-7wf7-3272 — undici cache interceptor advisory
  3. undici npm package
  4. undici releases — GitHub
  5. Bringing HTTP Caching to Node.js — Platformatic Blog
  6. undici documentation — Interceptors
  7. GitLab Advisory Database — undici
05 · The Call

Final Verdict
= UNCHANGED to MEDIUM (5.5/10)

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.

06 · Verification

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

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/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\nfi