TL;DR

The OpenJS CNA published eight undici CVEs on 2026-10-15, all fixed in undici 6.29.1, 7.30.1 and 8.12.2 the same day; the GitHub Advisory Database reviewed three of them on 2026-10-27, which is how they surfaced here. Two change what an app trusts: with compose(redirect(), cache()) on an originless Agent and a shared cache store, a response produced after a cross-origin redirect is cached under the trusted original URL, so an attacker who controls a redirect target poisons the cache for every later caller and a private user-specific response can be served to others (CVE-2026-109829, 7.4); and Agent deep-cloned its options through JSON, so a tls.checkServerIdentity pinning callback was silently dropped and a certificate the callback was written to reject was accepted on the default dispatcher behind fetch() (CVE-2026-109383, 7.4). Of the other six, three end the process on a response from a malicious server (TLS 1.2 renegotiation CVE-2026-87018 7.5, excess content-encodings CVE-2026-109869 7.5, the decompress interceptor CVE-2026-87029 5.9), two exhaust memory (EventSource CVE-2026-109924, WebSocket PONG CVE-2026-109932, both 5.9), and one is a Subresource Integrity bypass through a non-lowercase algorithm token (CVE-2026-109841, 5.9). Node.js's 2026-10-21 releases bundle the fixed lines: 26.12.1 carries undici 8.12.2, 24.22.1 carries 7.30.1 and 22.23.4 carries 6.29.1, per the Node changelogs. Upgrade the package where you depend on it directly, and Node where you do not.

What happened

undici is the HTTP client under Node.js's global fetch(), and the package most agent SDKs, MCP clients and Next.js servers make outbound requests through whether they name it or not. On 2026-10-15 the undici maintainers (mcollina, UlisesGascon) published eight advisories on the nodejs/undici tab, the OpenJS Foundation CNA issued the CVE records the same day, and the 8.12.2 release notes list all eight. The database reviewed CVE-2026-109869 on 10-23 and the three below on 10-27, and the Node.js project's dependency-vulnerability bot opened an issue on 10-20 for CVE-2026-109829 against undici 8.11.2 in Node 26.x, with no maintainer comment as of 2026-10-28. The CNA records, read this sweep:

  • CVE-2026-109829 / GHSA-4w7w-5xrc-9h26 — cache poisoning and cross-user disclosure via cross-origin redirects (7.4, CWE-346, CWE-524). Affected 7.0.0 to 7.30.0 and 8.0.0 to 8.12.1 (the cache interceptor arrived in 7.0.0). When an originless Agent composes the redirect and cache interceptors in that order with a shared MemoryCacheStore or SqliteCacheStore, the cache key is built from the original request URL before the redirect handler changes the origin, so the response produced after a cross-origin redirect is stored under the original key; an attacker who controls the target of a redirect from a trusted URL has their response cached under that URL for later callers, and a private, no-store redirect response to a user-specific resource can be stored and served to later unauthenticated callers. The fix verifies the producing origin before storing and preserves each hop's cache-control policy. Workarounds: compose(cache(), redirect()), per-origin dispatchers and stores, or no shared caching for redirect-capable requests. Finders Kushalkhemka, mayank-jangid-moon, skigeek16; reporter bengsky13.
  • CVE-2026-109383 / GHSA-2m5v-pch6-74hx — TLS certificate validation bypass via dropped tls options in Agent (7.4, CWE-295). Affected 4.0.0 to 6.29.0, 7.0.0 to 7.30.0, 8.0.0 to 8.12.1. Agent passed its constructor options through a JSON deep clone before forwarding them to each per-origin pool, JSON cannot carry functions, so a caller-supplied tls.checkServerIdentity callback (the usual way to pin a certificate or public key) was silently dropped before the TLS layer; a peer whose certificate the callback should reject but which passes Node's default hostname and chain checks is accepted. Agent is the default dispatcher behind request, fetch and setGlobalDispatcher, and EnvHttpProxyAgent's direct and NO_PROXY routes are affected too; the same options through connect are not. The advisory calls it the Agent counterpart of CVE-2026-84961, which covered BalancedPool. Workaround: pass TLS options via connect instead of tls. Reporters euriconicacio, BlueN0r, ksanjeev284.
  • CVE-2026-87018 / GHSA-qrxm-fqhp-jwvm — process crash via TLS 1.2 certificate-changing renegotiation (7.5, CWE-248, CWE-617). Affected 4.2.1 to 6.29.0, 7.0.0 to 7.30.0, 8.0.0 to 8.12.1. A TLS 1.2 server that renegotiates after the connection is up and presents a different CA-trusted certificate with a non-matching hostname makes Node destroy the socket with a certificate-altname error, which undici's established-socket handler asserted could never happen, so the assertion is an uncaught exception that ends the process on both HTTP/1.1 and HTTP/2 paths. The attacker controls only the endpoint. Workaround: minVersion and maxVersion of TLSv1.3 in connect options where the targets allow it. Reporter benzdeus.
  • CVE-2026-109869 / GHSA-xjj6-f33q-929c — crash via unhandled error on excessive content-encodings (7.5). Affected 6.23.0 to 6.29.0, 7.18.0 to 7.30.0, 8.0.0 to 8.12.1. A server that sends more than five content codings and closes early leaves an orphaned internal stream whose error is unhandled.
  • CVE-2026-87029 — unhandled exception in the decompress interceptor (5.9), 7.15.0 to 7.30.0 and 8.0.0 to 8.12.1; CVE-2026-109841 — Subresource Integrity bypass via non-lowercase algorithm tokens (5.9), same ranges; CVE-2026-109924 — unbounded memory in the EventSource parser (5.9), 6.5.0 to 6.29.0, 7.0.0 to 7.30.0, 8.0.0 to 8.12.1; CVE-2026-109932 — WebSocket client unbounded automatic PONG buffering (5.9), 5.15.0 to 6.29.0, 7.0.0 to 7.30.0, 8.0.0 to 8.12.1. All fixed in 6.29.1, 7.30.1 and 8.12.2; the four 5.9 records were read from CVE Services this sweep and their advisory pages were not opened.

What this means for the audience. An agent is an HTTP client that fetches URLs a model chose, and every URL a model chose is a redirect an attacker may control; the two 7.4s are the trust-boundary ones. The cache-poisoning case needs the specific interceptor composition and a shared store, which is a deliberate server-side setup rather than a default, so check for it rather than assume it. The pinning case is the opposite: anyone who added checkServerIdentity to an Agent to pin a provider or an internal CA has been running with the pin silently off since undici 4.0.0, and the default fetch() dispatcher is Agent. The five crash records are the usual shape for a client library, a malicious or compromised server ends the process, and for a long-running agent or MCP host that is a denial of service with one response. On versions: the 8.12.2 fix release and the eight records are dated 2026-10-15; Node.js's 2026-10-21 security post lists "Undici on 26.x, 24.x, 22.x" among dependency updates without saying which CVE it closes; the Node changelogs settle it, with 26.12.1 updating undici to 8.12.2 (PR #66721), 24.22.1 to 7.30.1 (PR #66764) and 22.23.4 to 6.29.1 (PR #66765), all three the fixed versions. next@16.4.3 declares no undici dependency of its own and uses the runtime's fetch, so a Next.js app's exposure is the Node version it runs on, plus any direct undici pin in its lockfile.

Am I affected?

# Direct dependency: below 6.29.1, 7.30.1 or 8.12.2 is affected (ranges above differ per CVE)
npm ls undici 2>/dev/null | grep undici
grep -n '"undici"' package-lock.json pnpm-lock.yaml 2>/dev/null | head

# Bundled with Node: the 2026-10-21 security releases updated it; check your runtime
node -p 'process.versions.undici + " in node " + process.version'

# The two trust-boundary cases
grep -rn 'checkServerIdentity' --include='*.js' --include='*.ts' --include='*.mjs' . | grep -v node_modules
grep -rnE 'compose\(\s*(interceptors\.)?redirect' --include='*.js' --include='*.ts' . | grep -v node_modules

A checkServerIdentity passed inside tls: to new Agent(...) or setGlobalDispatcher(new Agent(...)) was not running on an affected version. A compose(redirect(), cache()) with a shared store is the poisoning setup.

If you are affected

Upgrade undici to 6.29.1, 7.30.1 or 8.12.2, or Node to the 2026-10-21 lines (22.23.4, 24.22.1, 26.12.1 per the Node.js file). If you pinned a certificate through Agent tls options, decide whether anything connected to a host the pin should have rejected; there is no log of it. If a shared cache sat behind a redirect-capable dispatcher, clear it. auditing a vibe-coded repo for the dependency sweep.

Prevention

  • Keep the runtime on a supported Node line and read the security-release post's dependency list as a CVE list; the bundled undici is where fetch() lives.
  • Pass TLS pinning through connect, not tls, on undici dispatchers, which the advisory names as the safe path on every version.
  • Treat the URL an agent fetches as attacker-chosen and deny egress by default; agent-sandboxing.
  • supply-chain-attack-surface.

Sources