Skip to content

fix(client): reject pipelined TLS altname errors#5373

Merged
mcollina merged 1 commit into
nodejs:mainfrom
marko1olo:fix-tls-pipelining-altname
Jun 8, 2026
Merged

fix(client): reject pipelined TLS altname errors#5373
mcollina merged 1 commit into
nodejs:mainfrom
marko1olo:fix-tls-pipelining-altname

Conversation

@marko1olo

Copy link
Copy Markdown
Contributor

This relates to...

Fixes #5355

Rationale

ERR_TLS_CERT_ALTNAME_INVALID had a special connect-error path that asserted client[kRunning] === 0 before rejecting pending requests for the current server name. With pipelining > 1, requests can already be in the running segment when the TLS hostname validation error is reported, so the assertion can crash the process instead of rejecting the affected request promises.

Changes

Features

N/A

Bug Fixes

  • drain and reject already-running requests when a TLS altname error is reported
  • remove same-servername pending requests from the queue while rejecting them, preserving later pending requests for other server names
  • add a regression test using a local HTTPS server and pipelined requests

Breaking Changes and Deprecations

N/A

Status

  • I have read and agreed to the Developer's Certificate of Origin
  • Tested
  • Benchmarked (optional)
  • Documented - not applicable; this fixes internal error handling
  • Review ready
  • In review
  • Merge ready

Tested

  • node --test test\node-test\client-tls.js
  • NODE_OPTIONS=--expose-gc node --test test\tls-cert-leak.js
  • node --test test\client-connect.js
  • node --test --test-name-pattern servername test\node-test\client-dispatch.js
  • eslint lib\dispatcher\client.js test\node-test\client-tls.js
  • git diff --check

Drain already running requests before rejecting same-servername pending requests so TLS hostname failures reject the request promises instead of tripping the queue assertion.

Fixes nodejs#5355

Signed-off-by: marko1olo <barsukdana@gmail.com>

@mcollina mcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 75.00000% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.24%. Comparing base (a8ea6f2) to head (bf90ab2).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
lib/dispatcher/client.js 75.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5373      +/-   ##
==========================================
- Coverage   93.25%   93.24%   -0.01%     
==========================================
  Files         110      110              
  Lines       36738    36744       +6     
==========================================
+ Hits        34259    34262       +3     
- Misses       2479     2482       +3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 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.

Comment thread lib/dispatcher/client.js
if (err.code === 'ERR_TLS_CERT_ALTNAME_INVALID') {
assert(client[kRunning] === 0)
const running = client[kQueue].splice(client[kRunningIdx], client[kRunning])
client[kPendingIdx] = client[kRunningIdx]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense. the original assert(client[kRunning] === 0) assumed no pipelining — splicing out the running requests and rejecting them before handling pending ones is the right approach. using splice for pending too avoids the index shift issue. test with 20 pipelined requests against a bad cert is a good coverage of the race.

@AliMahmoudDev

Copy link
Copy Markdown
Contributor

Good catch — before this fix, running requests with a matching servername would stay in the queue and never get rejected when a TLS altname error hits. Using splice instead of incrementing the index is correct since errorRequest removes items from the queue. The test covering 20 pipelined requests all getting rejected with the right error code is solid.

@mcollina mcollina merged commit 01e89e9 into nodejs:main Jun 8, 2026
38 checks passed
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.

AssertionError in ERR_TLS_CERT_ALTNAME_INVALID handler when pipelining > 1

4 participants