fix(ext/node): TLSSocket.authorized=false when client presents no cert#34381
Merged
Conversation
A node:tls server configured with `requestCert: true, rejectUnauthorized:
false` was reporting `tlsSocket.authorized === true` and a null
`authorizationError` when the client connected without presenting any
client certificate. Node correctly reports `authorized = false` with
`authorizationError = "UNABLE_TO_GET_ISSUER_CERT"` in this case, so
application code that branches on `if (socket.authorized) { ...trust
the client... }` was mis-trusting unauthenticated connections.
rustls only invokes the `ClientCertVerifier` when the client actually
presents a certificate, so with `rejectUnauthorized: false` the verifier
never runs and `verifyError()` stays empty. `onServerSocketSecure` then
fell through to `this.authorized = true`. Detect the no-cert case
explicitly by checking `getPeerCertificate(false) == null` and surface
it as the matching Node authorization error.
Fixes #34366
fibibot
reviewed
May 25, 2026
fibibot
left a comment
Contributor
There was a problem hiding this comment.
onServerSocketSecure() now keeps the default authorized = false when requestCert is enabled and rustls reports no verify error because the client sent no certificate. The added TLS unit covers that exact rejectUnauthorized: false path and checks both authorizationError and the empty peer cert. Holding approval until CI is green.
fibibot
approved these changes
May 25, 2026
fibibot
left a comment
Contributor
There was a problem hiding this comment.
CI is green now, promoting prior review to APPROVE.
littledivy
pushed a commit
to crowlKats/deno
that referenced
this pull request
Jun 10, 2026
denoland#34381) A `node:tls` server with `requestCert: true, rejectUnauthorized: false` was incorrectly reporting `socket.authorized === true` and a null `authorizationError` when the client connected without presenting any client certificate. Node reports `authorized = false` with `authorizationError = "UNABLE_TO_GET_ISSUER_CERT"` in this case, so application code that gates trust on `socket.authorized` was treating unauthenticated connections as authenticated. rustls only invokes the `ClientCertVerifier` when the client actually sends a certificate, and `client_auth_mandatory` returns the `reject_unauthorized` flag — so with `rejectUnauthorized: false` the verifier never runs and the shared `verifyError` slot stays empty. `onServerSocketSecure` then fell into the `authorized = true` branch. Detect the no-cert case explicitly via `getPeerCertificate(false) == null` and surface it as the matching Node authorization code. Fixes denoland#34366
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A
node:tlsserver withrequestCert: true, rejectUnauthorized: falsewas incorrectly reporting
socket.authorized === trueand a nullauthorizationErrorwhen the client connected without presenting anyclient certificate. Node reports
authorized = falsewithauthorizationError = "UNABLE_TO_GET_ISSUER_CERT"in this case, soapplication code that gates trust on
socket.authorizedwas treatingunauthenticated connections as authenticated.
rustls only invokes the
ClientCertVerifierwhen the client actuallysends a certificate, and
client_auth_mandatoryreturns thereject_unauthorizedflag — so withrejectUnauthorized: falsetheverifier never runs and the shared
verifyErrorslot stays empty.onServerSocketSecurethen fell into theauthorized = truebranch.Detect the no-cert case explicitly via
getPeerCertificate(false) == nulland surface it as the matching Node authorization code.Fixes #34366