grpc/grpc-go · error
spiffe: could not get spiffe ID from peer leaf cert but veri
Error message
spiffe: could not get spiffe ID from peer leaf cert but verification with spiffe trust map was configured: %v
What it means
Returned by GetRootsFromSPIFFEBundleMap when the peer's leaf certificate cannot yield a SPIFFE ID via idFromCert, even though the caller configured SPIFFE Bundle Map verification. The wrapped error is whatever idFromCert produced (nil cert, wrong URI count, or an unparseable URI). This is a handshake-time failure: verification was requested but the presented cert is not a conformant SPIFFE certificate.
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 03255a9237)
Solutions
- Ensure the peer workload is enrolled in SPIRE and its cert carries exactly one spiffe:// URI SAN.
- If legacy certs must coexist, do not configure SPIFFEBundleMap globally; segment traffic so only SPIFFE-issuing clusters use it.
- Inspect the peer leaf cert with openssl x509 -text and confirm the URI SAN is present and well-formed.
- Re-issue the peer's cert through its SPIRE workload agent.
Defensive patterns
Strategy: validation
Validate before calling
func leafHasValidSVID(c *x509.Certificate) error {
if c == nil { return errors.New("nil cert") }
if len(c.URIs) != 1 { return fmt.Errorf("expected 1 URI SAN, got %d", len(c.URIs)) }
if _, err := spiffeid.FromURI(c.URIs[0]); err != nil { return err }
return nil
} Type guard
func isSPIFFESVID(c *x509.Certificate) bool {
if c == nil || len(c.URIs) != 1 { return false }
_, err := spiffeid.FromURI(c.URIs[0])
return err == nil
} Try / catch
roots, err := spiffe.GetRootsFromSPIFFEBundleMap(bm, leaf)
if err != nil && strings.Contains(err.Error(), "could not get spiffe ID") {
// peer is not a SPIFFE workload; fail closed and audit the cert
} Prevention
- Do not enable SPIFFE bundle map verification on endpoints that serve non-SPIFFE certs.
- Gate SPIFFE mTLS per cluster/listener to avoid mixed-identity failures.
- Audit peer certs in staging to confirm URI SANs before enforcing in production.
When it happens
Trigger: A peer presents a non-SPIFFE cert (no URI SAN, multiple URI SANs, or a URI SAN that is not a spiffe:// URI) while the server/client has km.SPIFFEBundleMap set in its key material. Triggered from buildVerifyFunc at handshake_info.go:281.
Common situations: Mixed environment where some workloads use SPIFFE mTLS and others use traditional mTLS; misconfigured SPIRE agent that issued a cert without the URI SAN; a cert rotated by a non-SPIFFE CA; turning on SPIFFE verification against endpoints that still serve legacy certs.
Related errors
- spiffe: BundleMapFromBytes() no bundles parsed from spiffe b
- spiffe: no bundle found for peer certificates trust domain %
- input cert has %v URIs but should have 1
- xds: fetching trusted roots from CertificateProvider failed:
- xds: fetching identity certificates from CertificateProvider
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/759b5fbd856242a1.
Report an issue: GitHub.