{"record":{"id":"8e3933183fbf8313","repo":"grpc/grpc-go","slug":"trailing-data-after-akid-extension","errorCode":null,"errorMessage":"trailing data after AKID extension","messagePattern":"trailing data after AKID extension","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"security/advancedtls/crl.go","lineNumber":332,"sourceCode":"// parseCRLExtensions parses the extensions for a CRL\n// and checks that they're supported by the parser.\nfunc parseCRLExtensions(c *x509.RevocationList) (*CRL, error) {\n\tif c == nil {\n\t\treturn nil, errors.New(\"c is nil, expected any value\")\n\t}\n\tcertList := &CRL{certList: c}\n\n\tfor _, ext := range c.Extensions {\n\t\tswitch {\n\t\tcase oidDeltaCRLIndicator.Equal(ext.Id):\n\t\t\treturn nil, fmt.Errorf(\"delta CRLs unsupported\")\n\n\t\tcase oidAuthorityKeyIdentifier.Equal(ext.Id):\n\t\t\tvar a authKeyID\n\t\t\tif rest, err := asn1.Unmarshal(ext.Value, &a); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"asn1.Unmarshal failed: %v\", err)\n\t\t\t} else if len(rest) != 0 {\n\t\t\t\treturn nil, errors.New(\"trailing data after AKID extension\")\n\t\t\t}\n\t\t\tcertList.authorityKeyID = a.ID\n\n\t\tcase oidIssuingDistributionPoint.Equal(ext.Id):\n\t\t\tvar dp issuingDistributionPoint\n\t\t\tif rest, err := asn1.Unmarshal(ext.Value, &dp); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"asn1.Unmarshal failed: %v\", err)\n\t\t\t} else if len(rest) != 0 {\n\t\t\t\treturn nil, errors.New(\"trailing data after IssuingDistributionPoint extension\")\n\t\t\t}\n\n\t\t\tif dp.OnlyContainsUserCerts || dp.OnlyContainsCACerts || dp.OnlyContainsAttributeCerts {\n\t\t\t\treturn nil, errors.New(\"CRL only contains some certificate types\")\n\t\t\t}\n\t\t\tif dp.IndirectCRL {\n\t\t\t\treturn nil, errors.New(\"indirect CRLs unsupported\")\n\t\t\t}\n\t\t\tif dp.OnlySomeReasons.BitLength != 0 {","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/security/advancedtls/crl.go#L314-L350","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Verify a CRL's AKID extension parses cleanly before installing it.\nfunc precheckAKID(crlDER []byte) error {\n    l, err := x509.ParseRevocationList(crlDER)\n    if err != nil { return err }\n    for _, ext := range l.Extensions {\n        if ext.Id.Equal(oidAuthorityKeyIdentifier) {\n            var a authKeyID\n            rest, err := asn1.Unmarshal(ext.Value, &a)\n            if err != nil { return err }\n            if len(rest) != 0 { return errors.New(\"AKID has trailing bytes\") }\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"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.","preventionTips":["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."],"tags":["tls","crl","advancedtls","asn1","pkix","malformed"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}