grpc/grpc-go · error
trailing data after AKID extension
Error message
trailing data after AKID extension
What it means
Returned by parseCRLExtensions when asn1.Unmarshal of the AuthorityKeyIdentifier extension consumed the value but left non-empty trailing bytes. RFC 5280 expects a single SEQUENCE encoding with no leftover; trailing bytes indicate the extension is malformed or has been tampered with, and grpc-go refuses to use the CRL.
Solutions
- Re-download the CRL from the CA's distribution point to rule out transfer corruption.
- Validate the CRL with openssl crl -inform DER -text -noout and confirm no ASN.1 errors are reported.
- If the CA's CRL is genuinely non-conformant, request a fixed CRL or disable CRL checking for that issuer (with documented risk).
Defensive patterns
Strategy: try-catch
Validate before calling
// Verify a CRL's AKID extension parses cleanly before installing it.
func precheckAKID(crlDER []byte) error {
l, err := x509.ParseRevocationList(crlDER)
if err != nil { return err }
for _, ext := range l.Extensions {
if ext.Id.Equal(oidAuthorityKeyIdentifier) {
var a authKeyID
rest, err := asn1.Unmarshal(ext.Value, &a)
if err != nil { return err }
if len(rest) != 0 { return errors.New("AKID has trailing bytes") }
}
}
return nil
} Try / catch
When loading a CRL, wrap the parse in error handling: on malformed-extension errors, log the CRL URL and skip installing it (do not crash the server). Re-fetch after backoff.
Prevention
- Download CRLs over a transport that checks integrity (TLS) and validate bytes before parsing.
- Run openssl crl -noout -CAfile <issuer> on every refreshed CRL in CI.
- Keep the last good CRL on disk so a corrupt refresh does not wipe revocation data.
When it happens
Trigger: The CRL's AuthorityKeyIdentifier extension value decodes to a valid authKeyID struct but extra bytes remain (len(rest) != 0). Encountered when loading/parsing a CRL file via the advancedtls CRL provider.
Common situations: Corrupted or truncated CRL file. CRL produced by non-conformant CA software that appended extra fields to the AKID extension. Hand-edited/DER-patched CRL used for testing.
Related errors
- extractCRLIssuer: invalid ASN.1 encoding
- trailing data after IssuingDistributionPoint extension
- no DN found in certificate issuer
- authority key identifier extension missing
- CRL only contains some certificate types
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/8e3933183fbf8313.
Report an issue: GitHub.
Appendix: source
Thrown at security/advancedtls/crl.go:332
// parseCRLExtensions parses the extensions for a CRL
// and checks that they're supported by the parser.
func parseCRLExtensions(c *x509.RevocationList) (*CRL, error) {
if c == nil {
return nil, errors.New("c is nil, expected any value")
}
certList := &CRL{certList: c}
for _, ext := range c.Extensions {
switch {
case oidDeltaCRLIndicator.Equal(ext.Id):
return nil, fmt.Errorf("delta CRLs unsupported")
case oidAuthorityKeyIdentifier.Equal(ext.Id):
var a authKeyID
if rest, err := asn1.Unmarshal(ext.Value, &a); err != nil {
return nil, fmt.Errorf("asn1.Unmarshal failed: %v", err)
} else if len(rest) != 0 {
return nil, errors.New("trailing data after AKID extension")
}
certList.authorityKeyID = a.ID
case oidIssuingDistributionPoint.Equal(ext.Id):
var dp issuingDistributionPoint
if rest, err := asn1.Unmarshal(ext.Value, &dp); err != nil {
return nil, fmt.Errorf("asn1.Unmarshal failed: %v", err)
} else if len(rest) != 0 {
return nil, errors.New("trailing data after IssuingDistributionPoint extension")
}
if dp.OnlyContainsUserCerts || dp.OnlyContainsCACerts || dp.OnlyContainsAttributeCerts {
return nil, errors.New("CRL only contains some certificate types")
}
if dp.IndirectCRL {
return nil, errors.New("indirect CRLs unsupported")
}
if dp.OnlySomeReasons.BitLength != 0 {View on GitHub (pinned to 0c51461d27)