grpc/grpc-go · error
spiffe: could not get spiffe ID from peer leaf cert but…
Error message
spiffe: could not get spiffe ID from peer leaf cert but verification with spiffe trust map was configured: %v
What it means
Raised by GetRootsFromSPIFFEBundleMap when idFromCert fails on the peer's leaf certificate. A SPIFFE trust map was configured (so SPIFFE verification is expected), but the peer cert is not a valid SPIFFE leaf: it is nil, has a URI SAN count other than 1, or its URI is not a parseable SPIFFE ID. The underlying idFromCert error is appended.
Solutions
- Ensure the peer workload's certificate is minted by a SPIFFE-compatible CA (SPIRE, Istio CA, etc.) and carries exactly one spiffe:// URI SAN.
- If non-SPIFFE clients must connect, separate them onto a listener that does not use a SPIFFE trust map.
- Inspect the peer cert with openssl x509 -text and check the URI SAN section.
- Confirm the certificate chain is assembled correctly so the leaf reaches idFromCert non-nil.
Example fix
// before: peer cert has DNS SANs only, verified via SPIFFE map -> error // after: mint peer cert with one spiffe://example.org/workload URI SAN
Defensive patterns
Strategy: type-guard
Validate before calling
func peerCertIsSpiffe(c *x509.Certificate) bool {
return c != nil && len(c.URIs) == 1 && strings.HasPrefix(c.URIs[0].String(), "spiffe://")
}
// gate GetRootsFromSPIFFEBundleMap on this Type guard
func isSPIFFELeaf(c *x509.Certificate) bool {
if c == nil || len(c.URIs) != 1 { return false }
if _, err := spiffeid.FromURI(c.URIs[0]); err != nil { return false }
return true
} Try / catch
In a custom VerifyPeerCertificate callback, check isSPIFFELeaf on the parsed leaf first; if false, return a clear non-SPIFFE error rather than calling GetRootsFromSPIFFEBundleMap.
Prevention
- Only enable SPIFFE trust-map verification on listeners that exclusively receive SPIFFE workloads.
- Issue certs from a SPIFFE-aware CA that guarantees one spiffe:// URI SAN.
- Unit-test verification with both SPIFFE and non-SPIFFE peer certs.
When it happens
Trigger: A client connects with mTLS but presents a certificate without a SPIFFE URI SAN (a traditional DNS-SAN cert), with multiple URIs, with a non-spiffe:// URI, or the cert chain arrived as nil during verification.
Common situations: Mixing SPIFFE-based mTLS verification with non-SPIFFE workloads on the same listener; a workload cert generated by a non-SPIFFE CA; cert rotation producing a cert with zero URIs; misconfigured cert chain assembly delivering nil.
Related errors
- input cert has URIs but should have 1
- input cert is nil
- invalid spiffeid
- spiffe: BundleMapFromBytes() failed to parse bundle for…
- spiffe: no bundle found for peer certificates trust domain
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/759b5fbd856242a1.
Report an issue: GitHub.
Appendix: source
Thrown at internal/credentials/spiffe/spiffe.go:74
}
bundle, err := spiffebundle.Parse(trustDomain, jsonBundle)
if err != nil {
return nil, fmt.Errorf("spiffe: BundleMapFromBytes() failed to parse bundle for trust domain %q: %v", td, err)
}
bundleMap[td] = bundle
}
return bundleMap, nil
}
// GetRootsFromSPIFFEBundleMap returns the root trust certificates from the
// SPIFFE bundle map for the given trust domain from the leaf certificate.
func GetRootsFromSPIFFEBundleMap(bundleMap map[string]*spiffebundle.Bundle, leafCert *x509.Certificate) (*x509.CertPool, error) {
// 1. Upon receiving a peer certificate, verify that it is a well-formed SPIFFE
// leaf certificate. In particular, it must have a single URI SAN containing
// a well-formed SPIFFE ID ([SPIFFE ID format]).
spiffeID, err := idFromCert(leafCert)
if err != nil {
return nil, fmt.Errorf("spiffe: could not get spiffe ID from peer leaf cert but verification with spiffe trust map was configured: %v", err)
}
// 2. Use the trust domain in the peer certificate's SPIFFE ID to lookup
// the SPIFFE trust bundle. If the trust domain is not contained in the
// configured trust map, reject the certificate.
spiffeBundle, ok := bundleMap[spiffeID.TrustDomain().Name()]
if !ok {
return nil, fmt.Errorf("spiffe: no bundle found for peer certificates trust domain %q but verification with a SPIFFE trust map was configured", spiffeID.TrustDomain().Name())
}
roots := spiffeBundle.X509Authorities()
rootPool := x509.NewCertPool()
for _, root := range roots {
rootPool.AddCert(root)
}
return rootPool, nil
}
// idFromCert parses the SPIFFE ID from the x509.Certificate. If the certificateView on GitHub (pinned to 0c51461d27)