crowdsecurity/crowdsec · error
no verified cert in request
Error message
no verified cert in request
What it means
Even when a peer certificate was presented, ValidateCert requires the TLS handshake to have completed full verification: tls.ConnectionState.VerifiedChains must be non-empty. An empty VerifiedChains means the certificate chain was never validated, so the cert cannot be trusted and auth fails.
Source
Thrown at pkg/apiserver/middlewares/v1/tls_auth.go:110
for _, ou := range ous {
if slices.Contains(ta.AllowedOUs, ou) {
return nil
}
}
return fmt.Errorf("client certificate OU %v doesn't match expected OU %v", ous, ta.AllowedOUs)
}
func (ta *TLSAuth) ValidateCert(c *gin.Context) (string, error) {
// Checks cert validity, Returns true + CN if client cert matches requested OU
var leaf *x509.Certificate
if c.Request.TLS == nil || len(c.Request.TLS.PeerCertificates) == 0 {
return "", errors.New("no certificate in request")
}
if len(c.Request.TLS.VerifiedChains) == 0 {
return "", errors.New("no verified cert in request")
}
// although there can be multiple chains, the leaf certificate is the same
// we take the first one
leaf = c.Request.TLS.VerifiedChains[0][0]
if err := ta.checkAllowedOU(leaf.Subject.OrganizationalUnit); err != nil {
return "", err
}
if ta.isExpired(leaf) {
return "", errors.New("client certificate is expired")
}
if validErr, cached := ta.revocationCache.Get(leaf); cached {
if validErr != nil {
return "", fmt.Errorf("(cache) %w", validErr)
}View on GitHub (pinned to 909b515798)
Solutions
- Set the server's TLS ClientAuth mode to tls.RequireAndVerifyClientCert
- Ensure the server trusts the CA that signed client certificates (client_ca certificate loaded correctly)
- Restart the API server and reconnect with the client cert
Example fix
// before tlsConfig.ClientAuth = tls.RequestClientCert // after tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert tlsConfig.ClientCAs = caPool
Defensive patterns
Strategy: type-guard
Validate before calling
if len(req.TLS.VerifiedChains) == 0 {
return errors.New("client cert chain was not verified")
} Type guard
func hasVerifiedChain(req *http.Request) bool {
return req.TLS != nil && len(req.TLS.VerifiedChains) > 0 && len(req.TLS.VerifiedChains[0]) > 0
} Try / catch
cn, err := ta.ValidateCert(c)
if err != nil {
log.Debugf("cert auth rejected: %v", err)
c.AbortWithStatus(http.StatusUnauthorized)
return
} Prevention
- Use tls.RequireAndVerifyClientCert, not RequestClientCert
- Ensure the CA bundle signing client certs is loaded into ClientCAs
- Test mTLS with curl --cert/--key before going live
When it happens
Trigger: ValidateCert sees len(c.Request.TLS.VerifiedChains) == 0 — typically because the server accepted the connection with client auth set to RequestClientCert (or VerifyClientCertIfGiven without verification succeeding at handshake level), so certs are present but not verified.
Common situations: Go TLS config with ClientAuth: tls.RequestClientCert instead of RequireAndVerifyClientCert; handshake verification errors tolerated; custom TLS wrapper that drops VerifiedChains.
Related errors
- certificate revoked by OCSP
- certificate revoked by CRL
- no certificate in request
- client certificate is expired
- tls authentication required
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/f039ab275cbf2f8b.
Report an issue: GitHub.