Skip to content

http: validate headers in writeEarlyHints#61897

Open
rsclarke wants to merge 1 commit intonodejs:mainfrom
rsclarke:fix/earlyhints-crlf
Open

http: validate headers in writeEarlyHints#61897
rsclarke wants to merge 1 commit intonodejs:mainfrom
rsclarke:fix/earlyhints-crlf

Conversation

@rsclarke
Copy link

writeEarlyHints() constructs the 103 Early Hints response by directly concatenating user-supplied header names and values into the raw HTTP response. Unlike setHeader(), appendHeader(), and writeHead(), it never calls validateHeaderName() or validateHeaderValue(), allowing CRLF sequences to pass through unchecked.

This means user supplied data passed to writeEarlyHints() can inject arbitrary HTTP response headers (or entire responses) via CRLF injection in:

  • Non-link header values
  • Non-link header names
  • Link header URLs (the linkValueRegExp regex uses [^>]* which matches \r\n)

This PR adds the same validation used by setHeader():

Call validateHeaderName() and validateHeaderValue() for non-link headers in the writeEarlyHints loop
Call checkInvalidHeaderChar() on the assembled Link header value
Tighten linkValueRegExp from [^>]* to [^>\r\n]* to reject CRLF inside the <...> URL portion

The HTTP/2 compatibility layer (lib/internal/http2/compat.js) has the same gap but nghttp2 rejects CRLF in HTTP/2 binary frame headers at the lower level. Though, it could be open for discussion whether similar validation should also be applied?

Add validateHeaderName/validateHeaderValue checks for non-link
headers and checkInvalidHeaderChar for the Link value in HTTP/1.1
writeEarlyHints, closing a CRLF injection gap where header names
and values were concatenated into the raw response without
validation.

Also tighten linkValueRegExp to reject CR/LF inside the <...>
URL portion of Link header values.
@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/http
  • @nodejs/net

@nodejs-github-bot nodejs-github-bot added http Issues or PRs related to the http subsystem. needs-ci PRs that need a full CI run. labels Feb 20, 2026
@codecov
Copy link

codecov bot commented Feb 20, 2026

Codecov Report

❌ Patch coverage is 72.72727% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.76%. Comparing base (f632f3f) to head (79bd80c).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
lib/_http_server.js 70.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #61897      +/-   ##
==========================================
- Coverage   91.70%   89.76%   -1.95%     
==========================================
  Files         337      674     +337     
  Lines      140104   204895   +64791     
  Branches    21758    39381   +17623     
==========================================
+ Hits       128484   183921   +55437     
- Misses      11398    13239    +1841     
- Partials      222     7735    +7513     
Files with missing lines Coverage Δ
lib/internal/validators.js 98.25% <100.00%> (+12.06%) ⬆️
lib/_http_server.js 97.05% <70.00%> (-0.06%) ⬇️

... and 456 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

http Issues or PRs related to the http subsystem. needs-ci PRs that need a full CI run.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments