grpc/grpc-go · error

spiffe: no bundle found for peer certificates trust domain

Error message

spiffe: no bundle found for peer certificates trust domain %q but verification with a SPIFFE trust map was configured

What it means

Raised by GetRootsFromSPIFFEBundleMap when the peer's leaf cert had a valid SPIFFE ID but its trust domain is not present as a key in the configured SPIFFE bundle map. The connection is rejected because no trusted roots exist for that trust domain.

Solutions

  1. Add the missing trust domain's bundle to the SPIFFE Bundle Map sourced from that domain's SPIFFE Bundle Endpoint.
  2. Verify the bundle map loaded at runtime contains the peer's trust domain name as a key.
  3. Confirm the peer is connecting from the trust domain you expect (check its SPIFFE ID) and is not a misconfigured or hostile workload.
  4. After updating the map, ensure it is hot-reloaded by the credential provider rather than cached stale.

Example fix

// before: map = {"example.org": bundle}
// peer cert spiffe ID = spiffe://partner.io/svc -> error
// after: map = {"example.org": bundle, "partner.io": partnerBundle}
Defensive patterns

Strategy: validation

Validate before calling

func bundleMapCovers(bundleMap map[string]*spiffebundle.Bundle, td string) bool {
    _, ok := bundleMap[td]
    return ok
}
// before GetRootsFromSPIFFEBundleMap, extract peer TD via idFromCert and check coverage

Try / catch

Treat this error as a federation gap: log the missing trust domain, surface it to operators, and fail the connection closed. Do not retry without updating the map.

Prevention

When it happens

Trigger: A peer presents a cert with SPIFFE ID `spiffe://partner.io/svc` but the bundle map only contains `example.org`. Federation is incomplete: the peer's trust domain was never added.

Common situations: Onboarding a new partner trust domain but forgetting to add their bundle to the map; bundle map rotation that dropped a trust domain; environment mismatch (prod map used in staging with different trust domains).

Understand the failure class

Related errors


AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11). Data as JSON: /api/errors/6263555ae3f7a098. Report an issue: GitHub.

Appendix: source

Thrown at internal/credentials/spiffe/spiffe.go:82

}

// 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 certificate
// does not have a valid SPIFFE ID, returns an error.
func idFromCert(cert *x509.Certificate) (*spiffeid.ID, error) {
	if cert == nil {
		return nil, fmt.Errorf("input cert is nil")
	}
	// A valid SPIFFE Certificate should have exactly one URI.
	if len(cert.URIs) != 1 {
		return nil, fmt.Errorf("input cert has %v URIs but should have 1", len(cert.URIs))

View on GitHub (pinned to 0c51461d27)