istio/istio · error

failed to parse CRL: %w

Error message

failed to parse CRL: %w

What it means

verifyCert applies certificate revocation when configSource.tlsSettings.caCrl is set: it trims the string, optionally unwraps a PEM block, and calls x509.ParseRevocationList. Failure means the content is neither valid PEM-encoded nor raw DER CRL. Because the code ignores pem.Decode errors and falls through to parsing the raw bytes, both a mangled PEM header and non-CRL DER produce this error. The handshake is rejected.

Source

Thrown at pilot/pkg/bootstrap/configcontroller.go:509

					sanMatchFound = true
					break
				}
			}
		}
		if !sanMatchFound {
			return fmt.Errorf("no matching SAN found")
		}
	}

	if len(tlsSettings.CaCrl) > 0 {
		crlData := []byte(strings.TrimSpace(tlsSettings.CaCrl))
		block, _ := pem.Decode(crlData)
		if block != nil {
			crlData = block.Bytes
		}
		crl, err := x509.ParseRevocationList(crlData)
		if err != nil {
			return fmt.Errorf("failed to parse CRL: %w", err)
		}
		for _, revokedCert := range crl.RevokedCertificateEntries {
			if cert.SerialNumber.Cmp(revokedCert.SerialNumber) == 0 {
				return fmt.Errorf("certificate is revoked")
			}
		}
	}

	return nil
}

// getRootCertFromSecret fetches a map of keys and values from a secret with name in namespace
func (s *Server) getRootCertFromSecret(name, namespace string) (*istioCredentials.CertInfo, error) {
	secret, err := s.kubeClient.Kube().CoreV1().Secrets(namespace).Get(context.Background(), name, v1.GetOptions{})
	if err != nil {
		return nil, fmt.Errorf("failed to get credential with name %v: %v", name, err)
	}
	return kube.ExtractRoot(secret.Data)

View on GitHub (pinned to 8dc789c5cf)

Solutions

  1. Validate the file: openssl crl -in crl.pem -noout -text (add -inform DER if raw).
  2. Re-encode as canonical PEM CRL and update the mesh config or secret.
  3. If you did not intend revocation checking, remove caCrl entirely.
  4. Regenerate a fresh CRL if the old one used deprecated structures.

Example fix

# before: certificate pasted into caCrl -> x509.ParseRevocationList fails -> error 837
tlsSettings:
  caCrl: "-----BEGIN CERTIFICATE-----..."
# after
tlsSettings:
  caCrl: "-----BEGIN X509 CRL-----\nMIIB...\n-----END X509 CRL-----\n"
Defensive patterns

Strategy: validation

Validate before calling

// validate CRL material before it enters tlsSettings
func isParseableCRL(s string) bool {
    data := []byte(strings.TrimSpace(s))
    if b, _ := pem.Decode(data); b != nil { data = b.Bytes }
    _, err := x509.ParseRevocationList(data)
    return err == nil
}

Prevention

When it happens

Trigger: caCrl populated with a certificate instead of a CRL; base64 blob with newlines stripped or added by YAML folding; CRL from an old openssl version the parser rejects; empty-ish whitespace content that survives the len>0 check; secret key holding ca.crt copied into the crl field.

Common situations: Hand-assembled tlsSettings referencing a CRL distributed via secret; CI templating that re-wraps long base64 lines; mixing up which secret key (crl vs crt) got pasted.

Understand the failure class

Related errors


AI-assisted analysis of istio/istio@8dc789c5cf (2026-08-15). Data as JSON: /api/errors/1eb56f4852104abc. Report an issue: GitHub.