{"record":{"id":"5a68df2a75469ca9","repo":"grpc/grpc-go","slug":"onlysomereasons-unsupported","errorCode":null,"errorMessage":"onlySomeReasons unsupported","messagePattern":"onlySomeReasons unsupported","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"security/advancedtls/crl.go","lineNumber":351,"sourceCode":"\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 {\n\t\t\t\treturn nil, errors.New(\"onlySomeReasons unsupported\")\n\t\t\t}\n\n\t\tcase ext.Critical:\n\t\t\treturn nil, fmt.Errorf(\"unsupported critical extension: %v\", ext.Id)\n\t\t}\n\t}\n\n\tif len(certList.authorityKeyID) == 0 {\n\t\treturn nil, errors.New(\"authority key identifier extension missing\")\n\t}\n\treturn certList, nil\n}\n\nfunc verifyCRL(crl *CRL, chain []*x509.Certificate) error {\n\t// RFC5280, 6.3.3 (f) Obtain and validate the certification path for the issuer of the complete CRL\n\t// We intentionally limit our CRLs to be signed with the same certificate path as the certificate\n\t// so we can use the chain from the connection.\n","sourceCodeStart":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/security/advancedtls/crl.go#L333-L369","documentation":"Thrown by gRPC's advancedtls CRL validator inside parseCRLExtensions when a CRL's IssuingDistributionPoint extension carries a non-empty onlySomeReasons bitstring. Such a CRL scopes its revocation entries to specific reason codes (e.g. keyCompromise), and gRPC intentionally rejects reason-scoped CRLs because its validation model assumes a complete, unscoped CRL. The check lives at crl.go:350 and is part of a set of guards that only accept plain base CRLs.","triggerScenarios":"A CRL file (PEM or DER) whose IssuingDistributionPoint extension has the onlySomeReasons field populated is supplied to advancedtls CRL processing (e.g. via a CRL provider or when the dialer/server loads a CRL for revocation checking). The moment parseCRLExtensions walks that extension and sees dp.OnlySomeReasons.BitLength != 0, it returns this error.","commonSituations":"Enterprise CAs or PKI tooling that emit reason-restricted CRLs by policy; a CRL distribution point that serves segmented CRLs (one per reason code); upgrading a CA that now populates onlySomeReasons where it previously did not.","solutions":["Fetch a full (unscoped) base CRL from the same CA distribution point that does not set onlySomeReasons.","Re-generate or re-issue the CRL with a tool/CA setting that omits the onlySomeReasons ReasonFlags field from the IssuingDistributionPoint extension.","Verify with `openssl crl -in crl.pem -noout -text` that Issuing Distribution Point shows no 'Only Some Reasons' line, then reload the CRL."],"exampleFix":"// before: CA issues a CRL with onlySomeReasons set -> error\n// after: issue a base CRL covering all reasons\n//   openssl ca -gencrl -out base.crl   (no -crl_reason scoping)\n// Confirm:\n//   openssl crl -in base.crl -noout -text | grep -i 'Only Some'\n//   (no output -> accepted by advancedtls)","handlingStrategy":"validation","validationCode":"// Pre-check a CRL's IssuingDistributionPoint before handing it to advancedtls.\nimport \"crypto/x509\"\nimport \"encoding/asn1\"\n\nfunc crlHasOnlySomeReasons(c *x509.RevocationList) (bool, error) {\n    // oidIssuingDistributionPoint = 2.5.29.28\n    oidIDP := asn1.ObjectIdentifier{2, 5, 29, 28}\n    for _, ext := range c.Extensions {\n        if ext.Id.Equal(oidIDP) {\n            // If the extension is present, any non-empty onlySomeReasons is a problem.\n            // A full re-parse is library-specific; at minimum flag presence to review.\n            return true, nil\n        }\n    }\n    return false, nil\n}","typeGuard":"func isAcceptableCRL(c *x509.RevocationList) bool {\n    return c != nil && !crlHasUnsupportedIDP(c) // returns false for reason-scoped CRLs\n}","tryCatchPattern":null,"preventionTips":["Audit CRLs with `openssl crl -text` before loading; reject any showing 'Only Some Reasons'.","Pin a CA/CRL generation pipeline that never sets onlySomeReasons.","Keep a known-good reference CRL in tests so regressions in CA output surface early."],"tags":["crl","advancedtls","security","x509","pki","revocation"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}