{"record":{"id":"892656517f6b6fd5","repo":"grpc/grpc-go","slug":"extractcrlissuer-invalid-asn-1-encoding","errorCode":null,"errorMessage":"extractCRLIssuer: invalid ASN.1 encoding","messagePattern":"extractCRLIssuer: invalid ASN\\.1 encoding","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"security/advancedtls/crl.go","lineNumber":417,"sourceCode":"\treturn crlBytes\n}\n\n// extractCRLIssuer extracts the raw ASN.1 encoding of the CRL issuer. Due to the design of\n// pkix.CertificateList and pkix.RDNSequence, it is not possible to reliably marshal the\n// parsed Issuer to its original raw encoding.\nfunc extractCRLIssuer(crlBytes []byte) ([]byte, error) {\n\tif bytes.HasPrefix(crlBytes, crlPemPrefix) {\n\t\tcrlBytes = crlPemToDer(crlBytes)\n\t}\n\tder := cryptobyte.String(crlBytes)\n\tvar issuer cryptobyte.String\n\t// This doubled der.ReadASN1 is intentional, it modifies the input buffer\n\tif !der.ReadASN1(&der, cbasn1.SEQUENCE) ||\n\t\t!der.ReadASN1(&der, cbasn1.SEQUENCE) ||\n\t\t!der.SkipOptionalASN1(cbasn1.INTEGER) ||\n\t\t!der.SkipASN1(cbasn1.SEQUENCE) ||\n\t\t!der.ReadASN1Element(&issuer, cbasn1.SEQUENCE) {\n\t\treturn nil, errors.New(\"extractCRLIssuer: invalid ASN.1 encoding\")\n\t}\n\treturn issuer, nil\n}\n\n// parseRevocationList comes largely from here\n// x509.go:\n// https://github.com/golang/go/blob/e2f413402527505144beea443078649380e0c545/src/crypto/x509/x509.go#L1669-L1690\n// We must first convert PEM to DER to be able to use the new\n// x509.ParseRevocationList instead of the deprecated x509.ParseCRL\nfunc parseRevocationList(crlBytes []byte) (*x509.RevocationList, error) {\n\tif bytes.HasPrefix(crlBytes, crlPemPrefix) {\n\t\tcrlBytes = crlPemToDer(crlBytes)\n\t}\n\tcrl, err := x509.ParseRevocationList(crlBytes)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn crl, nil","sourceCodeStart":399,"sourceCodeEnd":435,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/security/advancedtls/crl.go#L399-L435","documentation":"Returned by extractCRLIssuer when the cryptobyte walk over the CRL's DER structure fails one of: outer SEQUENCE, tbsCertList SEQUENCE, optional version INTEGER, signature AlgorithmIdentifier SEQUENCE, or the issuer Name SEQUENCE. Any failure means the bytes are not a well-formed CRL and the issuer DN cannot be extracted, so the CRL is unusable.","triggerScenarios":"extractCRLIssuer is given bytes that are not a valid X.509 CRL DER encoding (or PEM that decodes to such). Common when the bytes are actually a different ASN.1 structure, a truncated file, or text with embedded newlines that were not stripped.","commonSituations":"CRL URL returns an HTML error page or JSON status instead of DER/PEM bytes. PEM-to-DER conversion bug leaves the header text in place. Wrong distribution point served (e.g. a DeltaCRL or a cert instead of a CRL). Network proxy injecting content.","solutions":["Verify the bytes are a CRL: decode PEM (type \"X509 CRL\") or pass valid DER; check with openssl crl -inform DER/PEM -text -noout.","Fetch the CRL URL with curl -sS to confirm the response Content-Type and body are a CRL, not an error page.","Strip any text artifacts (HTTP headers, leading whitespace) before parsing.","Point the CRL provider at the correct distributionPoint URI listed in the certificate's CRLDistributionPoints extension."],"exampleFix":"// before: feeding the raw HTTP response body that included headers\n//   der := resp.Body // contains \"HTTP/1.1 200 OK\\r\\n...\"\n//   issuer, _ := extractCRLIssuer(der)\n// after: decode as PEM or pass only the DER body\n//   der := crlPemToDer(resp.Body) // strips PEM framing if present\n//   issuer, err := extractCRLIssuer(der)\n//   if err != nil { /* log and skip this CRL */ }","handlingStrategy":"try-catch","validationCode":"// Sanity-check bytes look like a CRL (PEM or DER SEQUENCE) before parsing.\nfunc looksLikeCRL(b []byte) bool {\n    if bytes.HasPrefix(b, []byte(\"-----BEGIN X509 CRL\")) { return true }\n    if len(b) > 1 && b[0] == 0x30 { return true } // DER SEQUENCE tag\n    return false\n}","typeGuard":null,"tryCatchPattern":"Wrap CRL loading: if extractCRLIssuer or x509.ParseRevocationList fails, log the URL and bytes length, do not install, and retry with backoff. Keep previous CRL on disk.","preventionTips":["Fetch CRLs from distributionPoint URIs embedded in the cert, not hard-coded URLs.","Verify HTTP responses are actually CRL bytes (Content-Type / magic bytes) before parsing.","Run CRL bytes through openssl crl -inform DER -noout as a pre-check in your refresh job."],"tags":["tls","crl","advancedtls","asn1","malformed","pkix"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}