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

  1. Switch to a direct CRL signed by the same CA that issued the certificate (matching subject/issuer DN and AKID).
  2. If only indirect CRLs exist for the chain, disable CRL revocation and rely on OCSP.
  3. 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

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


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 CRL

View on GitHub (pinned to 0c51461d27)