crowdsecurity/crowdsec · critical

certificate revoked by CRL

Error message

certificate revoked by CRL

What it means

Same revocation path as the OCSP case, but the certificate was found on a Certificate Revocation List. The CRL checker reports the certificate as revoked by its issuer, so ValidateCert rejects the mTLS client.

Source

Thrown at pkg/apiserver/middlewares/v1/tls_auth.go:62

	// starting from the root CA and moving towards the leaf certificate,
	// check for revocation of intermediates too
	for i := len(chain) - 1; i > 0; i-- {
		cert := chain[i-1]
		issuer := chain[i]

		revokedByOCSP, checkedByOCSP := ta.ocspChecker.isRevokedBy(ctx, cert, issuer)
		couldCheck = couldCheck && checkedByOCSP

		if revokedByOCSP && checkedByOCSP {
			return errors.New("certificate revoked by OCSP"), couldCheck
		}

		revokedByCRL, checkedByCRL := ta.crlChecker.isRevokedBy(cert, issuer)
		couldCheck = couldCheck && checkedByCRL

		if revokedByCRL && checkedByCRL {
			return errors.New("certificate revoked by CRL"), couldCheck
		}
	}

	return nil, couldCheck
}

func (ta *TLSAuth) setAllowedOu(allowedOus []string) error {
	uniqueOUs := make(map[string]struct{})

	for _, ou := range allowedOus {
		// disallow empty ou
		if ou == "" {
			return errors.New("allowed_ou configuration contains invalid empty string")
		}

		if _, exists := uniqueOUs[ou]; exists {
			ta.logger.Warningf("dropping duplicate ou %s", ou)
			continue

View on GitHub (pinned to 909b515798)

Solutions

  1. Issue and configure a new client certificate
  2. Check the CRL to confirm the revocation and its reason
  3. Update the client to use the new certificate/keystore
  4. If the CA revoked in error, remove the serial from the CRL and refresh it
Defensive patterns

Strategy: validation

Validate before calling

// check the cert serial against the current CRL before deploying
for _, s := range crl.RevokedCertificateSerials {
    if s.Cmp(cert.SerialNumber) == 0 { reissueCert() }
}

Try / catch

if errors.Is(err, errRevoked) || strings.Contains(err.Error(), "revoked by CRL") {
    reissueAndReenroll() // do not retry with the same cert
}

Prevention

When it happens

Trigger: ValidateCert -> checkRevocationPath when ta.crlChecker.isRevokedBy(cert, issuer) returns revoked=true and checked=true for any cert in the client chain.

Common situations: Client certificate serial was added to the CA's CRL (expired bouncer, manually revoked cert); CRL distribution points configured and the CRL is fresh; client still using an old cert.

Understand the failure class

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/248cdc2a61de20ac. Report an issue: GitHub.