Source: node-undici Version: 8.9.0+dfsg+~cs3.2.0-1 Severity: important Tags: security upstream X-Debbugs-Cc: [email protected], Debian Security Team <[email protected]>
Hi, The following vulnerabilities were published for node-undici. CVE-2026-18149[0]: | undici's retry handler can leave an already-exposed response body | pending forever. When a server returns a successful response that | declares a Content-Length, sends only part of the body, and closes | the connection, the retry handler retries the request. If the retry | returns a non-retryable status such as 400, the handler forwards | that new response downstream and replaces its internal response | stream, but the original response body that the application still | holds is never ended or destroyed. As a result calls that read that | body never settle, and the configured body timeout does not fire | because its timer is tied to the connection parser rather than the | orphaned body. An attacker-controlled server can trigger this with | two short responses without keeping a connection open, and repeated | requests accumulate pending promises and streams that can exhaust | application concurrency or memory. This affects undici versions from | 7.11.0 up to 7.29.1 and from 8.0.0 up to 8.10.2. Users should | upgrade to undici 7.29.1 or 8.10.2. CVE-2026-18540[1]: | undici's retry interceptor can append the body of a ranged retry | response to bytes already delivered from an earlier partial response | while still presenting the original response's status and headers. | This happens when an upstream server delivers part of a body without | a trustworthy resume checkpoint, for example a non-success response | whose headers were already sent or a partial-content response with | an unusable content range, then closes the connection and answers | the resumed range request with more bytes. As a result the response | body can be longer than the Content-Length that the application | observes. An application that relays such a response to a downstream | HTTP/1.1 peer without normalizing the framing can emit a body that | exceeds the forwarded Content-Length, and the excess bytes can be | interpreted as the start of a following response, which enables | downstream response splitting or desynchronization. Exploitation | requires an attacker-controlled upstream server and an application | that forwards the response through a framing-sensitive path. This | affects undici versions before 6.28.1, from 7.0.0 up to 7.29.1, and | from 8.0.0 up to 8.10.2. Users should upgrade to undici 6.28.1, | 7.29.1, or 8.10.2. CVE-2026-19534[2]: | undici's WebSocket client crashes the whole Node.js process during | the opening handshake when a server responds with a subprotocol that | the client never requested. A default WebSocket connection sends no | subprotocol, but if the server's 101 response includes a Sec- | WebSocket-Protocol header, undici dereferences a null value while | checking it against the requested list and throws an uncaught | TypeError. Because that code runs inside a microtask with no | surrounding error handling, the exception propagates and terminates | the process under Node's default behavior, instead of gracefully | failing the connection as required by the WebSocket protocol. Any | application that opens a WebSocket to an attacker-controlled or | compromised server, or over a plaintext connection subject to a | machine-in-the-middle, can be crashed remotely without | authentication in the default configuration. This affects undici | versions from 6.7.0 up to 6.28.1, from 7.0.0 up to 7.29.1, and from | 8.0.0 up to 8.10.2. Users should upgrade to undici 6.28.1, 7.29.1, | or 8.10.2. CVE-2026-84890[3]: | undici's decompress interceptor decompresses response bodies | according to the untrusted Content-Encoding header. While the number | of content-encoding layers is capped, the total decompressed output | size is unbounded and there is no configuration option to limit it. | A malicious or faulty upstream can therefore return a small | compressed payload, a compression bomb, that expands to hundreds of | megabytes or more in client memory, an asymmetric resource | consumption that can exhaust memory and crash the process. This | affects undici versions from 7.15.0 up to 7.29.1 and from 8.0.0 up | to 8.10.2. Users should upgrade to undici 7.29.1 or 8.10.2. CVE-2026-84933[4]: | undici's cache interceptor does not handle the Set-Cookie response | header anywhere in its cache path, so it neither refuses to store | nor strips that header. In shared cache mode, which is the default, | an otherwise cacheable response that carries a Set-Cookie header, | for example one marked with a public and max-age directive, is | stored and then re-served to a later caller that matches the same | cache key. As a result one caller's cookie is disclosed to a | different caller, and an untrusted server can inject cookies into | cached responses served to all subsequent callers. This violates the | requirement that a shared cache must not store cookies. This affects | undici versions from 7.0.0 up to 7.29.1 and from 8.0.0 up to 8.10.2. | Users should upgrade to undici 7.29.1 or 8.10.2. CVE-2026-84947[5]: | undici's dump interceptor reads and discards a response body up to a | configurable maximum size. When a response declares a Content-Length | that exceeds the maximum, the interceptor aborts cleanly, but when a | response has no Content-Length and is chunked, the interceptor | instead signals completion early once the accumulated size reaches | the maximum, without pausing or aborting the request. Because the | underlying parser keeps delivering body bytes, a second completion | signal fires and trips an internal assertion, which aborts the | request and tears down the connection. The application is left | observing a misleading successful status with an empty or truncated | body while the connection has actually been disconnected. This | affects undici versions from 7.1.0 up to 7.29.1 and from 8.0.0 up to | 8.10.2. Users should upgrade to undici 7.29.1 or 8.10.2. CVE-2026-84961[6]: | undici's BalancedPool constructor passes its entire options object | through an internal deep-clone that serializes and reparses the | value as JSON. Because JSON cannot represent functions, any | function-valued TLS option, such as a caller-supplied | checkServerIdentity callback or a custom connector inside the | connect option, is silently discarded before it reaches the TLS | layer. As a result a peer whose certificate the application's custom | checkServerIdentity was written to reject, but which still passes | Node's default hostname and chain checks, is accepted when reached | through BalancedPool. The Client, Pool, and Agent dispatchers are | not affected because they extract the connect and tls options before | cloning. This affects undici versions from 7.24.1 up to 7.29.1 and | from 8.0.0 up to 8.10.2, and only when the application supplies a | function-valued connect or tls option to BalancedPool. Users should | upgrade to undici 7.29.1 or 8.10.2. CVE-2026-85008[7]: | undici's cache interceptor documents that only safe HTTP methods are | cached, but its logic to skip caching is built by subtracting the | configured methods from the set of safe methods, so an unsafe method | such as POST, PUT, or DELETE is never placed in the skip list and | instead falls through to the full cache-read path. The response- | storage gate also lacked a method check, so a response to an unsafe | request that is heuristically cacheable or carries an explicit | Cache-Control directive is stored and later replayed from cache. | Because response headers from a remote origin are untrusted, an | origin can answer once with a cacheable status and then have the | client's own subsequent state-changing requests to that path served | from the stale cache entry without ever reaching the origin, an | integrity failure that occurs under the interceptor's default | configuration. This affects undici versions from 7.0.0 up to 7.29.1 | and from 8.0.0 up to 8.10.2. Users should upgrade to undici 7.29.1 | or 8.10.2. CVE-2026-85014[8]: | undici's experimental WebSocketStream client crashes the whole | Node.js process when a remote peer closes the TCP connection without | a WebSocket close handshake. On an unclean close the internal | socket-close handler calls abort on the writable stream | unconditionally and discards the returned promise, but per the | WHATWG Streams standard aborting a locked writable returns a promise | that rejects with a TypeError. Because the application holds a | writer on that writable, which is the only way to write, the | rejection is never observed and Node's default unhandled-rejection | behavior terminates the process. An untrusted server can therefore | crash a client with a single abrupt disconnect, with no | authentication and no application mistake. This affects undici | versions from 7.0.0 up to 7.29.1 and from 8.0.0 up to 8.10.2. Users | should upgrade to undici 7.29.1 or 8.10.2. CVE-2026-85024[9]: | undici bundles a WebSocket client whose permessage-deflate size- | limit cleanup removes all listeners from the internal zlib inflate | stream, including its error listener, while that stream can still | emit. When a remote peer sends a compressed payload that crosses the | built-in 128 MiB decompressed-payload limit and then contains a | malformed DEFLATE byte, the inflate stream emits a data error with | no listener attached, which Node.js treats as a fatal unhandled | error and terminates the entire process. Exploitation is remote and | unauthenticated, requires no application mistake, and is asymmetric, | since roughly 130 KB on the wire expands past the limit and crashes | the process, and reconnecting can repeat the crash. This affects | undici versions from 6.25.0 up to 6.28.1, from 7.28.0 up to 7.29.1, | and from 8.1.0 up to 8.10.2. Users should upgrade to undici 6.28.1, | 7.29.1, or 8.10.2. CVE-2026-85152[10]: | undici 8.10.0 omits the destination origin from the cache and | request-deduplication keys when the cache or deduplicate interceptor | is composed directly onto a Client or Pool. Because the internal | cache key falls back to an empty origin string, a cacheable or in- | flight response from one upstream origin is returned for a request | to a different, trusted origin whenever the method, path, and | relevant headers match, which permits cross-origin information | disclosure and persistent cache poisoning. The reporter demonstrated | a full authentication bypass in which a JWT signed with an attacker- | controlled key was accepted as belonging to a trusted issuer, and | the trusted origin was never contacted. This is a regression | introduced in 8.10.0 and affects undici versions from 8.10.0 up to | 8.10.2. Applications using an Agent, which carries the origin in its | dispatch options, are not affected. Users should upgrade to undici | 8.10.2. If you fix the vulnerabilities please also make sure to include the CVE (Common Vulnerabilities & Exposures) ids in your changelog entry. For further information see: [0] https://security-tracker.debian.org/tracker/CVE-2026-18149 https://www.cve.org/CVERecord?id=CVE-2026-18149 [1] https://security-tracker.debian.org/tracker/CVE-2026-18540 https://www.cve.org/CVERecord?id=CVE-2026-18540 [2] https://security-tracker.debian.org/tracker/CVE-2026-19534 https://www.cve.org/CVERecord?id=CVE-2026-19534 [3] https://security-tracker.debian.org/tracker/CVE-2026-84890 https://www.cve.org/CVERecord?id=CVE-2026-84890 [4] https://security-tracker.debian.org/tracker/CVE-2026-84933 https://www.cve.org/CVERecord?id=CVE-2026-84933 [5] https://security-tracker.debian.org/tracker/CVE-2026-84947 https://www.cve.org/CVERecord?id=CVE-2026-84947 [6] https://security-tracker.debian.org/tracker/CVE-2026-84961 https://www.cve.org/CVERecord?id=CVE-2026-84961 [7] https://security-tracker.debian.org/tracker/CVE-2026-85008 https://www.cve.org/CVERecord?id=CVE-2026-85008 [8] https://security-tracker.debian.org/tracker/CVE-2026-85014 https://www.cve.org/CVERecord?id=CVE-2026-85014 [9] https://security-tracker.debian.org/tracker/CVE-2026-85024 https://www.cve.org/CVERecord?id=CVE-2026-85024 [10] https://security-tracker.debian.org/tracker/CVE-2026-85152 https://www.cve.org/CVERecord?id=CVE-2026-85152 Regards, Salvatore

