{"record":{"id":"8f161f75a77f3d9a","repo":"crowdsecurity/crowdsec","slug":"client-certificate-is-expired","errorCode":null,"errorMessage":"client certificate is expired","messagePattern":"client certificate is expired","errorType":"http","errorClass":null,"httpStatus":401,"severity":"critical","filePath":"pkg/apiserver/middlewares/v1/tls_auth.go","lineNumber":122,"sourceCode":"\n\tif c.Request.TLS == nil || len(c.Request.TLS.PeerCertificates) == 0 {\n\t\treturn \"\", errors.New(\"no certificate in request\")\n\t}\n\n\tif len(c.Request.TLS.VerifiedChains) == 0 {\n\t\treturn \"\", errors.New(\"no verified cert in request\")\n\t}\n\n\t// although there can be multiple chains, the leaf certificate is the same\n\t// we take the first one\n\tleaf = c.Request.TLS.VerifiedChains[0][0]\n\n\tif err := ta.checkAllowedOU(leaf.Subject.OrganizationalUnit); err != nil {\n\t\treturn \"\", err\n\t}\n\n\tif ta.isExpired(leaf) {\n\t\treturn \"\", errors.New(\"client certificate is expired\")\n\t}\n\n\tif validErr, cached := ta.revocationCache.Get(leaf); cached {\n\t\tif validErr != nil {\n\t\t\treturn \"\", fmt.Errorf(\"(cache) %w\", validErr)\n\t\t}\n\n\t\treturn leaf.Subject.CommonName, nil\n\t}\n\n\tokToCache := true\n\n\tvar (\n\t\tvalidErr   error\n\t\tcouldCheck bool\n\t)\n\n\tfor _, chain := range c.Request.TLS.VerifiedChains {","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/apiserver/middlewares/v1/tls_auth.go#L104-L140","documentation":"After OU checks pass, ValidateCert checks the leaf certificate's NotAfter via ta.isExpired. If the certificate's validity period has elapsed, the client cert is rejected even if it would otherwise authenticate; it must be renewed.","triggerScenarios":"ValidateCert called by authTLS when the presented client certificate's expiration time is before the current time.","commonSituations":"Long-lived deployments where the bouncer/user certificate quietly expired; clocks skewed on server or client; certificate issued with a short validity and never rotated.","solutions":["Generate a new client certificate (cscli bouncers new / cscli users new for the client) and install it","Sync clocks via NTP if a clock skew is suspected","Set up rotation/monitoring so certificates are renewed before expiry"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// preflight: fail fast on an expired cert before calling the API\nif time.Now().After(cert.NotAfter) {\n    return errors.New(\"client cert expired; reissue via cscli\")\n}","typeGuard":null,"tryCatchPattern":"_, err := ta.ValidateCert(c)\nif err != nil && strings.Contains(err.Error(), \"expired\") {\n    // signal re-enrollment to the client rather than plain 401\n}","preventionTips":["Automate certificate renewal before NotAfter","Monitor certificate expiry (alert at e.g. 30 days remaining)","Run NTP on server and clients to avoid clock-skew false expiry"],"tags":["tls","certificate","expired","mtls"],"backgroundTag":"certificate-expired","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}