Skip to content

fix(ext/node): TLSSocket.authorized=false when client presents no cert#34381

Merged
bartlomieju merged 1 commit into
mainfrom
fix/tls-no-client-cert-authorized
May 26, 2026
Merged

fix(ext/node): TLSSocket.authorized=false when client presents no cert#34381
bartlomieju merged 1 commit into
mainfrom
fix/tls-no-client-cert-authorized

Conversation

@bartlomieju

Copy link
Copy Markdown
Member

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 #34366

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 fibibot left a comment

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.

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 fibibot left a comment

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.

CI is green now, promoting prior review to APPROVE.

@bartlomieju
bartlomieju merged commit 8ab9700 into main May 26, 2026
136 checks passed
@bartlomieju
bartlomieju deleted the fix/tls-no-client-cert-authorized branch May 26, 2026 07:30
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
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.

node:tls TLSSocket.authorized incorrectly true on server when client presents no certificate (requestCert+rejectUnauthorized:false)

2 participants