node:tls: skip checkServerIdentity on resumed sessions - #33734
Conversation
Node's onConnectSecure gates the identity check on !this.isSessionReused(): the peer's identity was established on the full handshake that issued the ticket, so a resumed session does not run checkServerIdentity or the default hostname/SAN match again. Bun ran the check unconditionally, so a custom checkServerIdentity fired on every resumed connection, and a resumed connection with a servername absent from the cert (or a pinning callback that returns an Error) was torn down with ERR_TLS_CERT_ALTNAME_INVALID where Node connects cleanly. Gate both client handshake handlers on !socket.isSessionReused().
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 56 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
Comment |
|
Updated 4:19 AM PT - Jul 8th, 2026
✅ @autofix-ci[bot], your commit c1078851a5acc9bdcef9b95918e853f544d68d8a passed in 🧪 To try this PR locally: bunx bun-pr 33734That installs a local version of the PR into your bun-33734 --bun |
There was a problem hiding this comment.
I didn't find any issues and the change correctly mirrors Node's onConnectSecure gate — but since this alters when TLS server-identity verification runs, it's worth a human sign-off.
Extended reasoning...
Overview
Two-line change in src/js/node/net.ts: adds !socket.isSessionReused() to the checkServerIdentity gate in both client handshake handlers (SocketHandlers and SocketHandlers2), matching Node's lib/internal/tls/wrap.js onConnectSecure. A new test in test/js/node/tls/node-tls-connect.test.ts covers three resume scenarios (counting callback, error-returning callback, servername not in SAN).
Security risks
This removes the hostname/identity check on resumed TLS sessions. That is the standard TLS model — a successful resume proves the peer holds the session secret from the originally-verified full handshake — and is exactly what Node does. socket.isSessionReused() is a native binding (sockets.classes.ts) reporting BoringSSL's SSL_session_reused, not a user-tamperable JS property, so the gate can't be spoofed from userland. I don't see a way this weakens the security posture relative to Node, but any change to when cert verification runs warrants a second pair of eyes.
Level of scrutiny
High. TLS peer-identity verification is core security-sensitive code; even a small, well-justified change here should be reviewed by a human familiar with Bun's TLS stack.
Other factors
The fix is applied symmetrically to both handshake handlers, the PR description cites the exact Node source and includes a before/after comparison table, and the author reports the relevant Node parallel tests (test-tls-client-resume*.js, test-https-client-resume.js, test-tls-check-server-identity.js, etc.) still pass. The new test is well-constructed (waits for the ticket, wires error → resolve, asserts reused: true so it can't vacuously pass on a fallback full handshake). No prior human reviews or outstanding comments.
|
CI status for build #70358: 284/287 jobs passed, including all lanes that ran The two remaining jobs are both The diff itself is green on every completed lane. |
|
The |
What does this PR do?
Node's
onConnectSecure(lib/internal/tls/wrap.js) gates the server-identity check on!this.isSessionReused():Bun ran the check unconditionally in both client handshake handlers in
src/js/node/net.ts, so on a resumed session:checkServerIdentitywas invoked again (call counts / side effects calibrated to full handshakes fired on every connection),checkServerIdentitythat returns anError(certificate pinning) tore the resumed connection down,servernameabsent from the certificate's SAN failed withERR_TLS_CERT_ALTNAME_INVALIDeven though the server accepted the ticket.Node connects cleanly in all three cases because the peer's identity was established on the full handshake that issued the ticket.
Reproduction
checkServerIdentityreused=true csi=0reused=true csi=1reused=true csi=0servernamenot in certreused=true okERR_TLS_CERT_ALTNAME_INVALIDreused=true okcheckServerIdentityreturns Errorreused=true okEPINreused=true okFix
Add
!socket.isSessionReused()to the identity-check gate in bothhandshakehandlers (SocketHandlersandSocketHandlers2).How did you verify your code works?
New test in
test/js/node/tls/node-tls-connect.test.tscovering all three cases; fails onUSE_SYSTEM_BUN=1withcalls: 1vs expected0, passes with this change.test-tls-client-resume.js,test-tls-client-resume-12.js,test-https-client-resume.js,test-https-client-checkServerIdentity.js,test-tls-check-server-identity.js,test-tls-ticket*.jsandnode-tls-connect.test.tsall pass.