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

Returned by GetRootsFromSPIFFEBundleMap when the peer's SPIFFE ID parses fine but its trust domain has no entry in the configured Bundle Map. The bundle map lookup at spiffe.go:80 returns ok==false, so the chain cannot be verified against any trusted roots. This enforces explicit trust-domain allowlisting: only domains present in the map are trusted.

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 03255a9237)

Solutions

  1. Refresh the SPIFFE Bundle Map from the federation/bundle endpoint so it contains the peer's trust domain.
  2. Confirm the trust domain spelling in the peer cert matches a key in the map (case, dashes, TLD).
  3. Establish SPIFFE federation between the two trust domains if not already done.
  4. If the domain should not be trusted, treat this as expected and reject the connection at the policy layer.
Defensive patterns

Strategy: validation

Validate before calling

func bundleMapCoversPeerTD(bm map[string]*spiffebundle.Bundle, peerCert *x509.Certificate) error {
    id, err := spiffeid.FromURI(peerCert.URIs[0])
    if err != nil { return err }
    if _, ok := bm[id.TrustDomain().Name()]; !ok {
        return fmt.Errorf("trust domain %q missing from bundle map", id.TrustDomain().Name())
    }
    return nil
}

Type guard

func bundleMapHasDomain(bm map[string]*spiffebundle.Bundle, td string) bool {
    _, ok := bm[td]
    return ok
}

Try / catch

if _, err := spiffe.GetRootsFromSPIFFEBundleMap(bm, leaf); err != nil {
    if strings.Contains(err.Error(), "no bundle found") {
        // refresh the federated bundle map and retry once
    }
}

Prevention

When it happens

Trigger: The peer cert's spiffe:// URI names a trust domain (e.g. spiffe://staging.example/...) that is absent from the Bundle Map supplied to the credentials. Common during federation gaps or when the map only lists production domains.

Common situations: Cross-cluster calls where the consumer's Bundle Map was not refreshed to include the producer's trust domain; a federated trust relationship not yet established; typo in a trust domain name in the map vs. the issued cert; stale locally cached bundle.

Understand the failure class

Related errors


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