Skip to content

tls: throw on invalid ALPNProtocols instead of aborting - #65076

Open
sankalpsthakur wants to merge 1 commit into
nodejs:mainfrom
sankalpsthakur:fix/65069-alpn-sigabrt
Open

tls: throw on invalid ALPNProtocols instead of aborting#65076
sankalpsthakur wants to merge 1 commit into
nodejs:mainfrom
sankalpsthakur:fix/65069-alpn-sigabrt

Conversation

@sankalpsthakur

Copy link
Copy Markdown

Fixes #65069

tls.connect() with malformed ALPNProtocols (e.g. [''] or invalid wire format buffers like Buffer.from([0])) aborts the process with SIGABRT. The failure is CHECK_EQ(0, SSL_set_alpn_protos(...)) in TLSWrap::SetALPNProtocols when OpenSSL rejects the malformed list.

This change replaces the hard abort with THROW_ERR_INVALID_ARG_VALUE so invalid input throws a recoverable JavaScript exception. Valid inputs are unchanged; e.g. ['h2','http/1.1'] and wire buffers produced by convertProtocols continue to work.

Repro: node -e "require('node:tls').connect({ host: '127.0.0.1', port: 9999, ALPNProtocols: [''] })"

Before: SIGABRT exit 134
After: throws ERR_INVALID_ARG_VALUE

Assisted-by: Codex

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/crypto

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. crypto Issues and PRs related to the crypto subsystem. needs-ci PRs that need a full CI run. labels Aug 6, 2026

@pimterry pimterry 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.

Thanks for looking at this @sankalpsthakur! I agree it'd be good to fix, but I think there's a different approach that would cover the server case too and be a bit cleaner.

We do also need a test covering this, either as a new test or extending any existing validation tests we have here.

Comment thread src/crypto/crypto_tls.cc Outdated
sankalpsthakur pushed a commit to sankalpsthakur/node that referenced this pull request Aug 6, 2026
Address review feedback on nodejs#65076: move validation closer to call
site in convertALPNProtocols so both client and server are covered
and fail early. Empty string protocols now throw before reaching
OpenSSL; wire-format buffers are validated for truncated/zero-length
entries. C++ defense (THROW_ERR_INVALID_ARG_VALUE) remains for safety.

Refs: nodejs#65076
sankalpsthakur pushed a commit to sankalpsthakur/node that referenced this pull request Aug 6, 2026
@sankalpsthakur

Copy link
Copy Markdown
Author

Updated per review: validation now in lib/tls.js convertALPNProtocols (covers client and server, fails early), C++ defense kept, added test covering [''] and malformed buffers (Buffer.from([0]), [2,0x61], [1,0x61,0x62]). Ready for re-review.

sankalpsthakur pushed a commit to sankalpsthakur/node that referenced this pull request Aug 6, 2026
Address review feedback on nodejs#65076: move validation closer to call
site in convertALPNProtocols so both client and server are covered
and fail early. Empty string protocols now throw before reaching
OpenSSL; wire-format buffers are validated for truncated/zero-length
entries. C++ defense (THROW_ERR_INVALID_ARG_VALUE) remains for safety.

Refs: nodejs#65076
sankalpsthakur pushed a commit to sankalpsthakur/node that referenced this pull request Aug 6, 2026
@sankalpsthakur
sankalpsthakur force-pushed the fix/65069-alpn-sigabrt branch from dab0602 to af6b21f Compare August 6, 2026 12:42
@sankalpsthakur

Copy link
Copy Markdown
Author

Thanks for the feedback. I moved validation into convertALPNProtocols so both client and server fail early before reaching OpenSSL, and kept the C++ check as a defense in depth. Empty string protocols now throw via convertProtocols and wire format buffers are validated for empty, zero length and truncated cases. Added test coverage for the repro cases from #65069. I fixed the lint and formatting issues as well and rebased onto latest main.

Comment thread lib/tls.js Outdated
Comment thread src/crypto/crypto_tls.cc Outdated
@sankalpsthakur

sankalpsthakur commented Aug 7, 2026

Copy link
Copy Markdown
Author

@pimterry empty [] / empty buffer allowed again (skip ALPN). C++ is CHECK_EQ again, no user throw there. still reject [''] and bad wire buffers in convertALPNProtocols. 6e497bb.

sankalpsthakur added a commit to sankalpsthakur/node that referenced this pull request Aug 7, 2026
Empty ALPN buffer/array means skip ALPN (same as historical
behavior for []). Zero-length protocol entries and malformed
wire buffers still throw from convertALPNProtocols.

Revert the C++ THROW_ERR_INVALID_ARG_VALUE back to CHECK_EQ:
after JS validation, a non-zero SSL_set_alpn_protos return is
an internal invariant failure, not user-facing input.

Refs: nodejs#65076
@sankalpsthakur

sankalpsthakur commented Aug 8, 2026

Copy link
Copy Markdown
Author

@pimterry empty ALPN skip, convertALPNProtocols validation, CHECK_EQ, and tests are on latest head. Ready when you have a moment.

@pimterry pimterry added author ready PRs that have at least one approval, no outstanding review comments, and a CI started. request-ci Add this label to start a Jenkins CI on a PR. labels Aug 9, 2026
@github-actions github-actions Bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Aug 9, 2026
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

@sankalpsthakur

sankalpsthakur commented Aug 9, 2026

Copy link
Copy Markdown
Author

CI job 75694 ran on 6e497bb before the fixture fix. That commit still used invalid ALPN bytes (abcd) in test-tls-basic-validations.js, so the reds there are expected.

193e77b uses valid length-prefixed fixtures (same copy-isolation check). Could someone re-run CI on current HEAD? Thanks.

@codecov

codecov Bot commented Aug 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.30%. Comparing base (ee64033) to head (193e77b).
⚠️ Report is 184 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff            @@
##             main   #65076    +/-   ##
========================================
  Coverage   90.29%   90.30%            
========================================
  Files         759      759            
  Lines      247754   248355   +601     
  Branches    46721    46857   +136     
========================================
+ Hits       223708   224270   +562     
+ Misses      15521    15514     -7     
- Partials     8525     8571    +46     
Files with missing lines Coverage Δ
lib/tls.js 93.47% <100.00%> (+0.33%) ⬆️

... and 61 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.

@pimterry pimterry added the request-ci Add this label to start a Jenkins CI on a PR. label Aug 9, 2026
@sankalpsthakur
sankalpsthakur force-pushed the fix/65069-alpn-sigabrt branch from 82aed18 to 193e77b Compare August 18, 2026 04:45
@trivikr trivikr removed the author ready PRs that have at least one approval, no outstanding review comments, and a CI started. label Aug 22, 2026
@trivikr

trivikr commented Aug 22, 2026

Copy link
Copy Markdown
Member

@sankalpsthakur Can you please rebase?

The merge commits don't work with our tooling.

@sankalpsthakur
sankalpsthakur force-pushed the fix/65069-alpn-sigabrt branch from 82aed18 to 1e49721 Compare August 22, 2026 07:21
sankalpsthakur pushed a commit to sankalpsthakur/node that referenced this pull request Aug 22, 2026
Address review feedback on nodejs#65076: move validation closer to call
site in convertALPNProtocols so both client and server are covered
and fail early. Empty string protocols now throw before reaching
OpenSSL; wire-format buffers are validated for truncated/zero-length
entries. C++ defense (THROW_ERR_INVALID_ARG_VALUE) remains for safety.

Refs: nodejs#65076
sankalpsthakur pushed a commit to sankalpsthakur/node that referenced this pull request Aug 22, 2026
sankalpsthakur added a commit to sankalpsthakur/node that referenced this pull request Aug 22, 2026
Empty ALPN buffer/array means skip ALPN (same as historical
behavior for []). Zero-length protocol entries and malformed
wire buffers still throw from convertALPNProtocols.

Revert the C++ THROW_ERR_INVALID_ARG_VALUE back to CHECK_EQ:
after JS validation, a non-zero SSL_set_alpn_protos return is
an internal invariant failure, not user-facing input.

Refs: nodejs#65076
@sankalpsthakur

Copy link
Copy Markdown
Author

rebased onto main (a48e33f), merge commit dropped, six commits linear now. diff is unchanged: lib/tls.js and the two tls tests.

tls.connect() with malformed ALPNProtocols hit
CHECK_EQ(0, SSL_set_alpn_protos(...)) in the C++ layer and aborted
the process with SIGABRT.

Validate in JS instead, in convertALPNProtocols, so both client and
server fail early with a recoverable ERR_INVALID_ARG_VALUE:

- zero-length string protocols now throw from convertProtocols
- wire-format buffers are checked for zero-length and truncated
  entries
- an empty buffer or array is still accepted and means skip ALPN,
  matching the historical behavior for []

The C++ CHECK_EQ is left unchanged: once JS has validated the input,
a non-zero SSL_set_alpn_protos return is an internal invariant
failure rather than user-facing input.

Fixes: nodejs#65069
@sankalpsthakur
sankalpsthakur force-pushed the fix/65069-alpn-sigabrt branch from 1e49721 to eaaedf8 Compare August 22, 2026 07:25
@sankalpsthakur

Copy link
Copy Markdown
Author

correction to my last note: squashed to a single commit (eaaedf8) rather than the six i mentioned, message rewritten to describe the final js-only validation since the earlier ones still described the reverted c++ change. diff is unchanged.

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

Labels

c++ Issues and PRs that require attention from people who are familiar with C++. crypto Issues and PRs related to the crypto subsystem. needs-ci PRs that need a full CI run. request-ci Add this label to start a Jenkins CI on a PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tls.connect() aborts process on malformed ALPNProtocols instead of throwing an error

5 participants