$ the-wire · showcase
Undici fixes cookie parser stack overflow, EventSource header injection risk
By RepoJournal · Filed · About Node.js
Undici patches a stack overflow in Set-Cookie parsing and a UTF-8 validation gap in EventSource reconnects, while Node core improves diagnostics, QUIC handshakes, and resource timing.
Undici shipped two fixes that demand attention. A Set-Cookie parser in `lib/web/cookies/parse.js` recursed once per attribute with no depth bound [1]. A response header like `a=b;;;;...` overflowed the stack and threw an uncaught `RangeError` out of `getSetCookies`; the parser is now iterative with no behavior change. Separately, EventSource now UTF-8 encodes last event IDs before adding them to an internal request header list, clearing stale values and omitting IDs that cannot be transported as HTTP header values [2]. This prevents repeated local reconnect failures; the PR references GHSA-q9qx-47rg-rhc7. Undici also began honoring `connectTimeout` across SOCKS5 proxy setup, authentication, CONNECT negotiation, and target TLS upgrades, forwarding the option through `ProxyAgent` [3]. Cache revalidation now refetches when a 304 response introduces new `Vary` fields, evicting the stale entry so the replacement is stored with complete metadata [4].
In node core, `diagnostics_channel` now lazily creates the tracing context, which the author reports made `TracingChannel.traceSync()` and `tracePromise()` faster in one HTTP router benchmark [5]. QUIC now reuses the generic TLS pause machinery to pause the handshake entirely for the session event, stopping almost all events from being emitted except qlog, which removes the prior deferral machinery and simplifies the 0RTT flow [6]. `perf_hooks` added the missing `PerformanceResourceTiming` attributes `finalResponseHeadersStart`, `firstInterimResponseStart`, `renderBlockingStatus`, `contentType`, and `contentEncoding`, included them in `toJSON()`, and updated `responseStart` to return `firstInterimResponseStart` where applicable [7]. The WPT status file now enables ten `idlharness` subtests.
The memory provider in `vfs` previously rejected renames only when the destination had a different type [8]. Renaming a directory onto another directory silently dropped the destination and everything under it; now an existing destination directory must be empty, matching `rename(2)`'s `ENOTEMPTY` and RealFSProvider's behavior. The change also decrements nlink on a file replaced by a rename.
In undici types, `PendingInterceptor` and `PendingInterceptorsFormatter` move into the `MockAgent` namespace so consumers can name the argument types of `pendingInterceptors()` and custom formatters [9]. The nix tooling dropped the nghttp2 pin in `sharedLibDeps.nix` [10].
Action items
- → Review use of undici getSetCookies against Set-Cookie headers with long attribute lists; the stack overflow is fixed but any prior crashes indicate malformed headers from upstream servers nodejs/undici [immediate]
- → Test EventSource reconnects with non-ASCII Last-Event-ID values after upgrading undici nodejs/undici [plan]
- → Retest SOCKS5 proxies with aggressive connectTimeout settings to confirm the new timeout propagation nodejs/undici [plan]
References
- [1] fix: avoid unbounded recursion in Set-Cookie attribute parser ↗ nodejs/undici
- [2] fix(eventsource): validate Last-Event-ID on reconnect ↗ nodejs/undici
- [3] fix: honor SOCKS5 connection timeout ↗ nodejs/undici
- [4] fix(cache): refetch when 304 adds vary fields ↗ nodejs/undici
- [5] diagnostics_channel: lazily create tracing context ↗ nodejs/node
- [6] quic: reuse TLS pause machinery to drop event deferral & improve 0RTT ↗ nodejs/node
- [7] perf_hooks: add missing resource timing attributes ↗ nodejs/node
- [8] vfs: fix rename over non-empty directory ↗ nodejs/node
- [9] types: expose PendingInterceptor and PendingInterceptorsFormatter on the MockAgent namespace ↗ nodejs/undici
- [10] tools: remove nghttp2 pin in `sharedLibDeps.nix` ↗ nodejs/node