grpc/grpc-go · error
indirect CRLs unsupported
Error message
indirect CRLs unsupported
What it means
Returned by parseCRLExtensions when the IssuingDistributionPoint extension has indirectCRL=true. An indirect CRL is signed by an authority other than the cert issuer and uses per-entry Certificate Issuer extensions; grpc-go's CRL support is intentionally limited to direct CRLs signed by the same chain as the cert, so indirect CRLs are rejected.
Solutions
- Switch to a direct CRL signed by the same CA that issued the certificate (matching subject/issuer DN and AKID).
- If only indirect CRLs exist for the chain, disable CRL revocation and rely on OCSP.
- Verify the CRL distributionPoint URI in the certificate points to the direct CRL.
Defensive patterns
Strategy: validation
Validate before calling
// Detect indirect CRLs before installing them.
func isDirectCRL(crlDER []byte) (bool, error) {
l, err := x509.ParseRevocationList(crlDER)
if err != nil { return false, err }
for _, ext := range l.Extensions {
if ext.Id.Equal(oidIssuingDistributionPoint) {
var dp issuingDistributionPoint
if _, err := asn1.Unmarshal(ext.Value, &dp); err != nil { return false, err }
if dp.IndirectCRL { return false, nil }
}
}
return true, nil
} Try / catch
On 'indirect CRLs unsupported', log and continue with the previous (direct) CRL. Surface the issue so PKI can provide a direct CRL.
Prevention
- Confirm CRL issuer DN matches the certificate's issuer DN before installing.
- Avoid pointing grpc-go's CRL provider at delegated-CRL-issuer distribution points.
- Run a CI gate that rejects indirect CRLs for grpc-go deployments.
When it happens
Trigger: The CRL's IDP extension sets IndirectCRL=true (or the CRL otherwise carries a different issuer than the certificate's issuer). Triggered during CRL parsing in advancedtls.
Common situations: A third-party CA delegates CRL signing to a dedicated CRL issuer (common in large PKIs). The CRL distribution point serves an indirect CRL by default. Operator reused a CRL intended for a different trust chain.
Related errors
- no DN found in certificate issuer
- authority key identifier extension missing
- CRL only contains some certificate types
- extractCRLIssuer: invalid ASN.1 encoding
- onlySomeReasons unsupported
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/bf2de4de755a1766.
Report an issue: GitHub.
Appendix: source
Thrown at security/advancedtls/crl.go:348
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 {
return nil, errors.New("onlySomeReasons unsupported")
}
case ext.Critical:
return nil, fmt.Errorf("unsupported critical extension: %v", ext.Id)
}
}
if len(certList.authorityKeyID) == 0 {
return nil, errors.New("authority key identifier extension missing")
}
return certList, nil
}
func verifyCRL(crl *CRL, chain []*x509.Certificate) error {
// RFC5280, 6.3.3 (f) Obtain and validate the certification path for the issuer of the complete CRLView on GitHub (pinned to 0c51461d27)