npm / undici
undici
What changed in undici 6 to 8, from its official release notes, upgrade guides and advisories. Sources checked 2026-10-17.
25 breaking66 security27 new APIs and options8 performance9 behavior and defaults1 tooling225 fixes and other
See which of these apply to your code, ranked, in your agent:
npx @unstale/cli initundici 8269 changes
Breaking changes 21
Unsupported FormData request bodies are rejected.
An error is thrown when WebAssembly is unavailable.
Reverts preserving HTTP/2 for legacy fetch consumers.
Cache reads and writes are now restricted to safe HTTP methods; successful unsafe requests still invalidate cached responses.
Every decompression stage is now limited to 64 MiB by default, and the limit can be configured with maxSize.
maxSize is now enforced against received bytes for chunked responses without Content-Length, and oversized responses are aborted.
The connection now fails when an HTTP/2 extended CONNECT response is non-200.
A server selecting a subprotocol when none was requested now receives protocol error 1002 instead of triggering an uncaught TypeError.
Upgrade requests are no longer deduplicated.
HTTP/2 options are now namespaced, changing how developers configure them.
The retry interceptor now rejects partial responses whose Content-Length is inconsistent with Content-Range, preventing downstream response desynchronization, hangs, or corruption.
setCookie() now validates cookie domains, paths, and unparsed attributes more strictly, preventing injected cookie attributes.
Rejects non-ASCII octets in cookie paths.
A request fails when its CONNECT tunnel drops instead of looping.
Requires exact SameSite values instead of accepting Strict, Lax, or None as substrings, avoiding silently weakened cookie policies.
Snapshots are no longer persisted on close in playback mode.
Removes throwOnError from Dispatcher.RequestOptions.
Requests with malformed content-length headers are now rejected.
Support for non-real Blob objects is removed.
HTTP/2 is enabled by default, changing the default protocol behavior for developers using Undici.
Legacy handler wrappers are removed, so code relying on them may need to change.
Security 51
Agent preserves function-valued TLS options when creating per-origin dispatchers, so custom certificate or public-key verification callbacks are not silently dropped.
The cache interceptor verifies response origin before caching cross-origin redirects and preserves redirect-hop cache-control policy.
The content-encoding chain is validated before creating the body stream, and oversized chains are aborted safely.
Retained EventSource parser state is bounded, including field counts, buffered chunks, unfinished-line length, and retained field data.
fetch() normalizes mixed-case and uppercase SRI algorithm tokens before validation and digest selection.
The interceptor limits the size of response error bodies.
The zstd window size is limited to 8 MB.
Upstream creation now preserves function-valued connect and legacy tls options, including custom TLS certificate validation callbacks.
Cache reads and writes are now restricted to safe HTTP methods, while successful unsafe requests still invalidate cached entries.
Proxy-Agent now guards Proxy-Authorization in iterable header containers.
A terminal retry failure after response headers are exposed now propagates to the exposed body, preventing consumers from hanging indefinitely.
Fetch now sends Sec-Fetch-Mode only to potentially trustworthy URLs.
Unbounded recursion in the Set-Cookie attribute parser is avoided.
undici vulnerable to caching and replay of unsafe HTTP method responses
undici vulnerable to cross-origin cache poisoning via missing origin isolation in interceptors
undici vulnerable to cross-user cookie disclosure via Set-Cookie caching in shared caches
undici vulnerable to Denial of Service via orphaned RetryHandler response body
undici vulnerable to Denial of Service via unbounded decompression of compressed responses
undici vulnerable to Denial of Service via unhandled error in WebSocket permessage-deflate decompression
undici vulnerable to Denial of Service via unrequested WebSocket subprotocol
undici vulnerable to Denial of Service via WebSocketStream unclean close
undici vulnerable to downstream response splitting via retry interceptor
undici vulnerable to response truncation via oversized chunked responses in the dump interceptor
undici vulnerable to TLS certificate validation bypass via dropped connect options in BalancedPool
A server now rejects a handshake with protocol error 1002 if it selects a subprotocol that was not requested.
An unclean close with a locked writable stream now propagates failure through the retained writable stream controller instead of creating an unobserved rejected promise.
EventSource event size is limited.
The cache parser now handles empty qualified directives conservatively and safely handles mixed qualified and unqualified directives, preventing cross-user information disclosure or a parse-time crash.
Cache-Control parsing now normalizes optional whitespace around = in qualified no-cache and private directives and applies conservative cache decisions to prevent shared-cache restrictions from being bypassed.
Non-string header values are validated after coercion, including array elements, preventing crafted toString() or Symbol.toPrimitive implementations from introducing CRLF sequences.
undici vulnerable to cookie attribute injection via unsanitized domain and unparsed setCookie fields
undici vulnerable to CRLF Injection via blob-like body 'type' property
undici vulnerable to cross-user information disclosure and parse-time crash via degenerate private cache directives
undici vulnerable to cross-user information disclosure via whitespace around equals in Cache-Control directives
undici vulnerable to downstream response desynchronization via retry interceptor
Location and Content-Location URIs are invalidated on unsafe methods.
Trims whitespace-padded qualified field names so shared caches do not incorrectly cache authenticated responses as public.
undici vulnerable to cross-user information disclosure via shared cache whitespace bypass
undici vulnerable to HTTP header injection via Set-Cookie percent-decoding
undici vulnerable to HTTP response queue poisoning via keep-alive socket reuse
undici vulnerable to Set-Cookie SameSite attribute downgrade via permissive substring matching
undici vulnerable to TLS certificate validation bypass via dropped requestTls in SOCKS5 ProxyAgent
undici WebSocket client vulnerable to denial of service via cumulative fragment bypass
undici WebSocket client vulnerable to denial of service via fragment count bypass
Enforces the configured maximum payload size across all fragments in a message, preventing fragmented messages from exceeding the limit.
Limits the number of fragments in a WebSocket message to prevent unbounded memory growth and denial of service.
Rejects pipelined TLS altname errors.
WebSocket upgrades are now rejected when the response status is not 200.
SOCKS5 now enforces authenticated state before issuing CONNECT.
Uses per-origin pools to prevent requests, credentials, or responses from being routed across origins.
undici vulnerable to cross-origin request routing via SOCKS5 proxy pool reuse
New APIs and options 11
An alternative experimental HTTP parser is available.
The MockAgent namespace now exposes the PendingInterceptor and PendingInterceptorsFormatter types.
HTTP QUERY method support was added.
Adds textStream() to bodyMixin, providing a way to consume the body as a text stream.
The connect option offers HTTP/2 first in ALPN.
A redirect option was added to strip headers on redirect.
Adds normalizeBody to SnapshotAgent.
Adds normalizeQuery to SnapshotAgent.
Adds TOpaque to client connect options.
Adds throwOnMaxRedirect to the interceptor options and its types.
Adds configurable maxPayloadSize for WebSocket.
Performance 6
Large SQLite cache entries are compressed with zstd.
The idle-socket timer floor is dropped using a ref'd setImmediate.
Fetch skips work for empty RequestInit objects.
Optimizes the HTTP/2 request hot path.
Caches the FormData boundary.
Reduces redundant scans when selecting a dispatcher.
Behavior and default changes 8
DataView reply bodies are now supported.
Mock reply option callbacks can now be asynchronous.
The Accept-Encoding header used by fetch was updated.
HTTP/2 delivers an early final response to an Expect: 100-continue request.
Allows HTTP/2 POST requests to be multiplexed.
The HTTP/2 Client now multiplexes requests.
ProxyAgent now supports proxy authentication using a username without a password.
Built-in fetch mirrors the legacy global dispatcher.
Tooling 1
WPT tests are split out of the npm test command.
Fixes and other changes 171
Exceptions from downstream response handlers during asynchronous decompression are converted into per-request errors instead of uncaught exceptions.
Post-connect certificate errors no longer terminate the process during HTTP/1.1 and HTTP/2 connection handling.
Frame parsing pauses when automatic PONG writes encounter backpressure and resumes after the socket drains.
The build:wasm npm script was restored.
HTTP/1 handling of 204 and 304 responses is corrected.
Cache event order for 304 responses is preserved when using async stores.
bodyTimeout is paused while HTTP/2 applies backpressure.
Cached responses now track abort state and preserve abort reasons after completion.
Decompression no longer inflates compress and x-compress encodings.
Numeric expires values outside the Date range are ignored.
DNS handles a null pick and no longer fails over to an expired record.
EventSource redirect targets and retry wrapping are corrected, and maxEventSize is enforced on unterminated lines.
Language tags in filename* parameters are parsed.
Connections are reset for transfers with no-body transfer encoding.
HTTP/2 headers are normalized for legacy dispatch handlers.
HTTP/2 now enforces the maximum number of concurrent streams.
MemoryCacheStore evicts least recently used entries.
Removed clients no longer pick up requests.
A header named __proto__ is preserved across features.
ProxyAgent handles the Host header correctly.
WebSocket and EventSource receive limits are retained behind dispatcher wrappers.
Request headers are retained when resuming a download.
HTTP/1 strictContentLength handling is corrected.
The throwOnMaxRedirect edge case is corrected, and max-redirect errors now include an error code.
A bug in TLS session caching is fixed.
Tracked response header field boundaries are preserved.
Cache entries with zero lifetime are always treated as stale.
Aborted requests no longer trigger reconnection.
Rejected HTTP/2 WebSocket streams are now closed.
Fixes a hang when a 3xx response has a large body.
Fixes bugs in WebSocketStream.
Pool fan-out is avoided during ALPN negotiation.
Successful cache hits are no longer reported as aborted.
Cache.add no longer hangs.
Cache.addAll no longer hangs.
Repeated content-encoding headers are joined during decompression.
Data URL parsing is improved.
Inherited Object.prototype names are treated as unsupported encodings.
The decompression interceptor now honors backpressure.
Requests settle when deduplicate is composed with retry.
An Expires value of 0 is retained when serializing a cookie.
Cookies named __proto__ are retained in getCookies.
A request is not replayed after GOAWAY if its response has already started.
The maxConcurrentStreams option is validated directly.
Non-upgrade legacy requests continue to use HTTP/2.
Queued requests remain alive when the last stream closes.
HTTP/2 response content-length is validated.
Sessions with open streams are no longer unreferenced.
Sessions remain referenced while requests are queued.
Wildcard semantics for NO_PROXY are corrected in EnvHttpProxyAgent.
Repeated iterable headers are preserved by ProxyAgent.
Informational responses are ignored in redirect history.
Responses settle after a connection closes.
SIMD is selectively re-enabled for ppc64.
The compressed flag is reset when a message completes.
The cache now refetches when a 304 response adds Vary fields.
Last-Event-ID is now validated on EventSource reconnect.
SOCKS5 connections now honor the configured connection timeout.
The retry backoff now honors the abort signal.
Pools with pending GOAWAY replays are preserved.
Cache entries are evicted when a key holds a single entry.
Dispatcher origin is propagated to composed interceptors.
A deduplicated request settles when it is aborted.
Dispatcher options are propagated to the base class.
HTTP/2 now honors maxResponseSize.
The dump interceptor rejects aborted requests even when the response is smaller than maxSize.
Persistent mocks re-invoke the reply callback, and MockAgent interceptors are preserved when using legacy global fetch.
Trailing dots are ignored when matching no_proxy.
Interceptor handlers now forward onBodySent and onRequestSent.
HTTP/2 forwards 1xx informational responses to onInfo.
The default retry strategy now honors the retryAfter option.
Negative Max-Age attributes are accepted when processing Set-Cookie.
The socket is destroyed when SOCKS5 negotiation times out.
cache() and deduplicate() no longer remain silently inert on Client or Pool instances without opts.origin.
Preserves the DNS origin hostname on sockets.
Ensures every HTTP/2 request settles.
Retries refused HTTP/2 streams.
Detaches the upgrade close handler after GOAWAY.
Uses setTimeout(0) again to prevent stalls on an idle event loop.
Non-string path matchers work with ignoreTrailingSlash.
Emits request body lifecycle hooks.
Bare IPv6 addresses in no_proxy are now matched.
Consumes a body even when its end event has already been emitted.
Preserves body bytes that arrive after setEncoding() is called.
Skips the content-length checkpoint for HEAD requests and 206 responses without content-range.
Forwards informational responses.
Evicts unused origin pools.
WebSocket now supports process.unref.
Decompression now preserves response trailers.
setGlobalDispatcher now handles a frozen globalThis.
Revalidation-only responses are stored so ETag revalidation can engage.
Decompression is skipped for HEAD responses.
Aborted streams are destroyed synchronously rather than via setImmediate.
Completed requests are released from the queue.
Request streams are completed on end instead of waiting for close.
Stream-bodied requests can now multiplex on a busy HTTP/2 session.
must-revalidate and proxy-revalidate now take precedence over max-stale and stale-if-error.
Body headers are removed when a redirect changes POST to GET.
A null init argument is now converted correctly.
A zero-delay Retry-After value is now handled correctly.
stale-if-error is honored for connection errors during revalidation.
Guards against a response event delivered after completion.
Destroys the stream on abort rather than relying on close().
Automatically detects HTTP proxy tunneling.
Open-ended Range values are no longer rejected.
Ignores chunks that arrive after consumption has completed.
Adds the static buildDispatch method to the RedirectHandler type definition.
Ignores an unparseable Expires attribute.
Sets the use-URL-credentials flag for EventSource.
The types for deleteCookie attributes were corrected.
Requeues requests on a GOAWAY'd session instead of crashing.
Response chunks are dropped after the response stream is destroyed.
Retry flow control stays wired to the active connection across resumes.
Incomplete multi-byte UTF-8 sequences are handled in setEncoding().
Aligns EventSource behavior with the specification.
Skips DNS requests that do not have an origin.
Prevents a race condition between onEnd and onTrailers in the HTTP/2 client.
The paused parser completes on socket end instead of crashing.
All synchronous HTTP/2 request stream errors are handled.
Timeout errors are preserved for HTTP/2 requests.
Invalid HTTP/2 sessions are reset.
The method's single-argument behavior is restored.
Validates EOF for chunked HTTP/1 responses.
Accepts Content-Range values with an unknown size.
Aligns HTTP/2 empty-body content-length methods with HTTP/1 behavior.
Preserves a fetch multipart body when falling back to MockAgent.
Prevents replaying the pipeline body on redirect.
Preserves pool capacity after a stale client is removed, preventing the pool from losing capacity.
Validates the response body length against Content-Range.
Uses the configured connector in Socks5ProxyAgent.
Preserves the dispatch backpressure return value.
Prevents the dispatcher from being cleaned up prematurely.
The cache key now includes the query when opts.path is undefined.
Corrects the signed integer bounds used when converting values.
Multipart form-data now prefers filename* over filename.
The AND operator now intersects filterCalls results as expected.
HTTP/2 now allows request bodies for GET and HEAD requests.
Validates the maxConcurrentStreams option.
Request option validation now rejects NaN highWaterMark values.
The client now respects the peer's maximum number of concurrent streams.
Handles invalid HTTP/2 connection headers.
HTTP/2 now sends bodies for methods that do not expect payloads when content is supplied.
Accepted streams are preserved after GOAWAY.
Upgrade streams that close before response headers are now rejected.
The TLS session cache now enforces the configured maximum number of cached sessions.
Streamed cache entries at the maxEntrySize limit are now allowed.
Corrects the CRLF check in the multipart form-data parser.
Replaces stale pool clients while remaining under the connection limit.
Stops buffering data after the SOCKS5 connection is established.
Correctly expands the compressed :: notation in IPv6 addresses.
Embedded IPv4 tails in IPv6 literals are now encoded correctly.
Vary information is now persisted when SQLite cache entries are updated.
Expired SQLite vary entries are skipped during lookup.
The SQLite cache now enforces maxCount after inserting an entry.
Pruning now evicts the oldest cache entries first.
The cache now returns staleAt as an immutable value in milliseconds.
Fixes how the environment variable controls WASM SIMD behavior.
Propagates useH2c to the connector when a pool has more than one connection.
Corrects the argument order when a WebSocketStream encounters a UTF-8 failure.
Avoids double-closing stream readers when a WebSocket stream is canceled.
Prevents cache deduplication key collisions caused by unescaped delimiters.
Preserves the connect option in H2CClient.
Fixes native WebSocket over an H2 server after importing undici.
Throws a descriptive error when opts.dispatcher is passed instance methods.
Removes stale constructor interceptors from the types and pool options.
Makes ProxyAgent respect connectTimeout.
Avoids 401 failures for requests with stream-backed bodies.
WebSocket connections fall back to HTTP/1.1 when H2 CONNECT is unavailable.
Only parsed messages are enqueued in WebSocketStream.
Short-lived cache entries are preserved for revalidation.
Request statusText is preserved.
undici 787 changes
Breaking changes 4
Removes maxDecompressedMessageSize.
Non-safe methods are no longer deduplicated by default.
Streams are errored instead of canceled.
Receiving a 401 now returns the response instead of a network error.
Security 13
Checks Authorization on request headers according to RFC 9111 §3.5.
Avoids prototype collisions when parsing headers.
Fixed __proto__ pollution.
Fixes inconsistent interpretation of HTTP requests that could enable request/response smuggling.
Undici has an HTTP Request/Response Smuggling issue
Undici has CRLF Injection in undici via
upgradeoptionUndici has Unbounded Memory Consumption in its DeduplicationHandler via Response Buffering that leads to DoS
Undici has Unbounded Memory Consumption in WebSocket permessage-deflate Decompression
Undici has Unhandled Exception in WebSocket Client Due to Invalid server_max_window_bits Validation
Undici: Malicious WebSocket 64-bit length overflows parser and crashes the client
Hardens header iterable checks against prototype-pollution scenarios.
Fixes the vulnerability identified as CVE-2026-22036.
Undici has an unbounded decompression chain in HTTP responses on Node.js Fetch API via Content-Encoding leads to resource exhaustion
New APIs and options 16
Adds IP prioritization hints for HTTP/1.1 and HTTP/2.
Adds SOCKS5 proxy support to ProxyAgent.
Revalidation supports asynchronous cache stores.
Adds pingInterval for dispatching PING frames.
The WebSocketStream interface now includes a close method.
request() ResponseData now exposes statusText.
Adds an origins option for whitelist filtering.
Client exposes HTTP/2 flow-control options.
Adds getUpstream() to retrieve an upstream from a BalancedPool.
Adds an interceptor for request deduplication.
Adds storage support for the DNS interceptor.
Adds support for h2c over Unix domain sockets.
Adds a round-robin pool.
Adds runtime feature detection, allowing Undici to detect runtime capabilities.
Adds a ProxyAgent diagnostics event named undici:proxy:connected.
Adds support for WebSocket connections through HTTP/2.
Performance 2
The EventSourceStream parser now performs fewer allocations.
Uses fewer promises when extracting a body.
Behavior and default changes 1
Supports open diagnostics over HTTP/2.
Fixes and other changes 51
Lifecycle fixes were backported for upgrade diagnostics.
HTTP/2 now honors headersTimeout, so the configured timeout applies to HTTP/2 requests.
HTTP/2 now handles GOAWAY for CONNECT streams.
HTTP/2 requests whose streams are cancelled are now settled.
v7 now uses the legacy global dispatcher.
Preserves raw headers in the dispatch handler bridge.
Adds support for Node 26 and the legacy global dispatcher.
Fixes handling of stream-backed bodies for 401 responses.
The clone method is now declared as an instance method rather than an instance property.
Fetch now correctly handles multi-value rawHeaders.
Response types now align with DOM fetch types.
Prevents a client hang by wrapping the kConnector call in try/catch.
Supports connection-specific header names specified by the Connection header, per RFC 7230.
Improves the error message when mock intercepts are exhausted, making failures easier to diagnose.
Assumes an HTTP or HTTPS scheme for proxy environment variable values that omit a scheme.
The cache applies a 1-year deleteAt only for immutable responses.
Fixed dispatch path extraction to handle URL credentials.
Fixes a TypeError caused by reading push from null in HTTP/2.
Fixes fetch path logic.
Stops fetch from stripping a trailing ? from a URL.
Fixes a TypeError reading servername in _resume when an HTTP/2 stream completes.
Ignores late data frames after request completion.
Preserves latin1 header encoding in WrapHandler.
Forwards onResponseStarted through WrapHandler and UnwrapHandler.
Prevents AbortController garbage collection when redirect is set to error.
Passes socketPath to custom connect callbacks.
Preserves tuple headers in the DNS interceptor.
Uses the OR operator in includesCredentials to follow the WHATWG URL Standard.
Leading dots and asterisks are stripped when processing proxy exclusions.
WebSocket upgrades are routed through onRequestUpgrade.
Fixes a cleanup race involving clientTtl in Agent.
The finalizer is now set only for fetch responses.
Handles an undefined __filename in bundled environments.
Fetch stack traces are preserved.
Fixes delayed responses with AbortSignal in MockAgent.
Fixes flaky stream end handling on macOS.
HTTP headers are decoded as latin1 instead of utf8.
Fixes a 401 loop in fetch.
Regenerates a stream from its source when cache.match is called after garbage collection.
MockAgent normalizes origins for case-insensitivity and URL handling.
RetryAgent now handles FormData body types correctly for retried requests.
Fixes basic authentication for WebSocket connections.
Fixes the WebSocketStream open error.
Fixes running without SSL, which may affect environments where SSL is unavailable.
Fixes an off-by-one error when fetching a Blob with a range.
Updates the cache when a 304 Not Modified response is received upon revalidation.
Handles invalid fetch priority values properly.
Ensures HTTP/2 sends Content-Length for empty POST requests.
Adds a missing return after a callback call in ProxyAgent.
Makes the status parameter optional in the Response.redirect type.
Prevents onSocketClose from being called multiple times.
undici 65 changes
Security 2
Cookie values are no longer percent-decoded, preventing encoded CR, LF, or NUL sequences from becoming literal bytes that could enable HTTP header injection.
WebSocket message handling now limits fragment count as well as cumulative payload size, preventing unbounded memory growth and denial of service from malicious servers.
Fixes and other changes 3
Fixes aborting Streams.
The exposed body is settled when retry reaches terminal failure.
Upgrade diagnostics lifecycle fixes were backported to v6.x.