web: fix panic when client_allowed_sans is used with an optional client certificate - #436
Open
mrueg wants to merge 1 commit into
Open
web: fix panic when client_allowed_sans is used with an optional client certificate#436mrueg wants to merge 1 commit into
mrueg wants to merge 1 commit into
Conversation
…nt cert VerifyPeerCertificate indexed rawCerts[0] without checking the length. crypto/tls calls VerifyPeerCertificate even when the client sent no certificate, as long as the client auth type does not require one, so combining client_allowed_sans with RequestClientCert or VerifyClientCertIfGiven panicked on every certificate-less client. The panic is recovered by net/http's per-connection handler, so the process survives, but the connection is aborted with a stack trace in the log instead of a clean TLS alert. Return an error for an empty rawCerts slice, and reject the combination at configuration load time: client_allowed_sans is only meaningful when the client is required to present a certificate. With NoClientCert the callback is never invoked at all, so the configured SANs were silently ignored, which is the more dangerous half of this. All existing client_allowed_sans test fixtures use RequireAndVerifyClientCert, which is why this went unnoticed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Manuel Rüger <manuel@rueg.eu>
mrueg
force-pushed
the
fix/verifypeercertificate-empty-rawcerts
branch
from
September 2, 2026 11:31
2672aae to
0089e78
Compare
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.
TLSConfig.VerifyPeerCertificateindexesrawCerts[0]without checking the length:crypto/tlsinvokesVerifyPeerCertificateeven when the client sent no certificate, as long as the configured client auth type does not require one. InprocessCertsFromClientthe "client didn't provide a certificate" bail-out is guarded byrequiresClientCert(c.config.ClientAuth), and control still reaches the unconditional callback at the end of the function with an empty slice.So this configuration panics for every client that connects without a certificate:
net/http's per-connectionrecovercatches it, so the process survives, but the connection is aborted with a stack trace in the log rather than a cleanbad certificatealert.Changes
rawCertsis empty.client_allowed_sansis only meaningful when the client is required to present a certificate — and withNoClientCertthe callback is never invoked at all, so the configured SANs were silently ignored. That silent-bypass case seems worth failing loudly on, but it is the one behavioural change here, so happy to drop it to just (1) if you'd rather not reject configs that start today.Docs updated to state the constraint.
Testing
Every existing
client_allowed_sansfixture usesRequireAndVerifyClientCert, which is why this went unnoticed. Added a unit test for the nil/empty slice, a real TLS handshake test where the client presents no certificate, and two config fixtures for the rejected combinations. Reverting the guard makes the handshake test fail withindex out of range [0] with length 0.