Skip to content

Sync high-value bug fixes from upstream undici#1

Merged
ronag merged 3 commits into
masterfrom
sync/upstream-high-value-fixes
May 19, 2026
Merged

Sync high-value bug fixes from upstream undici#1
ronag merged 3 commits into
masterfrom
sync/upstream-high-value-fixes

Conversation

@ronag
Copy link
Copy Markdown
Member

@ronag ronag commented May 19, 2026

Summary

Cherry-picks (with adaptation) high-value upstream bug fixes that were still missing from this fork. This PR is the subset that actually applies to the fork's slim feature set (HTTP/1 client + agent + pool, no fetch/h2/cache/socks/websocket).

Security

  • parseHeaders prevent __proto__ prototype pollution in response headers (upstream #4923)
  • trailers preserve trailers that shadow Object.prototype via defineProperty instead of Object.assign (upstream 90a1609d)
  • request use hasSafeIterator to guard against polluted Object.prototype[Symbol.iterator] (upstream #4824)

Correctness

  • request accept RFC 7230 comma-separated Connection header tokens (close, keep-alive, upgrade, custom names) — was rejecting valid values (upstream #4775)
  • client-h1 validate EOF for chunked h1 responses; surface ResponseContentLengthMismatchError / HTTPParserError instead of silently completing on truncated bodies (upstream #5273)
  • client-h1 pre-increment kCounter so maxRequestsPerClient: N enforces exactly N requests per socket (was N+1 due to post-increment) (upstream #5034)
  • client-h1 reuse parser WeakRef across setTimeout calls instead of allocating a fresh one each time (upstream #5125)

Also included (from prior local fixes on this branch)

  • `globalDispatcher` symbol kept at `.1` (no v2 bump)
  • `makeDispatcher` strips `dispatcher`/`agent` out of `opts` before spreading, so they don't reach the instance `dispatch()` guard added in upstream #5007

Skipped after investigation

Test plan

  • `node --test test/prototype-headers.js` — 2/2 pass (new file)
  • `node --test test/request.js` — 18/18 pass (5 new Connection-header tests + polluted-iterator test)
  • `node --test test/client-timeout.js` — 5/5 pass (new WeakRef test)
  • `node --test test/parser-issues.js` — 5/5 pass (new truncated-chunked test)
  • `node --test test/close-and-destroy.js` — 11/11 pass (existing maxRequestsPerClient tests now assert per-request connection assignment `[0,0,1,1]`)
  • `node --test test/dispatcher.js` — 1/1 pass
  • `node --test test/node-test/agent.js` — 24/24 pass

🤖 Generated with Claude Code

ronag and others added 3 commits May 19, 2026 20:58
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
opts.dispatcher was passed through to instance dispatch(), which now
throws InvalidArgumentError. Strip dispatcher and agent from the spread
so they don't leak to the underlying dispatcher.dispatch().

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Security:
- parseHeaders: prevent __proto__ prototype pollution in response headers [upstream nodejs#4923]
- trailers: preserve trailers that shadow Object.prototype via defineProperty [upstream 90a1609]
- request: use hasSafeIterator to guard against polluted Object.prototype[Symbol.iterator] [upstream nodejs#4824]

Correctness:
- request: accept RFC 7230 comma-separated Connection header tokens (close, keep-alive, custom) [upstream nodejs#4775]
- client-h1: validate EOF for chunked h1 responses; surface ResponseContentLengthMismatchError and HTTPParserError instead of silently completing on truncated bodies [upstream nodejs#5273]
- client-h1: pre-increment kCounter so maxRequestsPerClient enforces exactly N requests per socket (was N+1) [upstream nodejs#5034]
- client-h1: reuse parser WeakRef across setTimeout calls instead of allocating a new one per call [upstream nodejs#5125]

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ronag ronag merged commit bc587ae into master May 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant