{"record":{"id":"6263555ae3f7a098","repo":"grpc/grpc-go","slug":"spiffe-no-bundle-found-for-peer-certificates-trus","errorCode":null,"errorMessage":"spiffe: no bundle found for peer certificates trust domain %q but verification with a SPIFFE trust map was configured","messagePattern":"spiffe: no bundle found for peer certificates trust domain %q but verification with a SPIFFE trust map was configured","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/credentials/spiffe/spiffe.go","lineNumber":82,"sourceCode":"}\n\n// GetRootsFromSPIFFEBundleMap returns the root trust certificates from the\n// SPIFFE bundle map for the given trust domain from the leaf certificate.\nfunc GetRootsFromSPIFFEBundleMap(bundleMap map[string]*spiffebundle.Bundle, leafCert *x509.Certificate) (*x509.CertPool, error) {\n\t// 1. Upon receiving a peer certificate, verify that it is a well-formed SPIFFE\n\t//    leaf certificate.  In particular, it must have a single URI SAN containing\n\t//    a well-formed SPIFFE ID ([SPIFFE ID format]).\n\tspiffeID, err := idFromCert(leafCert)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"spiffe: could not get spiffe ID from peer leaf cert but verification with spiffe trust map was configured: %v\", err)\n\t}\n\n\t// 2. Use the trust domain in the peer certificate's SPIFFE ID to lookup\n\t//    the SPIFFE trust bundle. If the trust domain is not contained in the\n\t//    configured trust map, reject the certificate.\n\tspiffeBundle, ok := bundleMap[spiffeID.TrustDomain().Name()]\n\tif !ok {\n\t\treturn 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())\n\t}\n\troots := spiffeBundle.X509Authorities()\n\trootPool := x509.NewCertPool()\n\tfor _, root := range roots {\n\t\trootPool.AddCert(root)\n\t}\n\treturn rootPool, nil\n}\n\n// idFromCert parses the SPIFFE ID from the x509.Certificate. If the certificate\n// does not have a valid SPIFFE ID, returns an error.\nfunc idFromCert(cert *x509.Certificate) (*spiffeid.ID, error) {\n\tif cert == nil {\n\t\treturn nil, fmt.Errorf(\"input cert is nil\")\n\t}\n\t// A valid SPIFFE Certificate should have exactly one URI.\n\tif len(cert.URIs) != 1 {\n\t\treturn nil, fmt.Errorf(\"input cert has %v URIs but should have 1\", len(cert.URIs))","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/credentials/spiffe/spiffe.go#L64-L100","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Refresh the SPIFFE Bundle Map from the federation/bundle endpoint so it contains the peer's trust domain.","Confirm the trust domain spelling in the peer cert matches a key in the map (case, dashes, TLD).","Establish SPIFFE federation between the two trust domains if not already done.","If the domain should not be trusted, treat this as expected and reject the connection at the policy layer."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"func bundleMapCoversPeerTD(bm map[string]*spiffebundle.Bundle, peerCert *x509.Certificate) error {\n    id, err := spiffeid.FromURI(peerCert.URIs[0])\n    if err != nil { return err }\n    if _, ok := bm[id.TrustDomain().Name()]; !ok {\n        return fmt.Errorf(\"trust domain %q missing from bundle map\", id.TrustDomain().Name())\n    }\n    return nil\n}","typeGuard":"func bundleMapHasDomain(bm map[string]*spiffebundle.Bundle, td string) bool {\n    _, ok := bm[td]\n    return ok\n}","tryCatchPattern":"if _, err := spiffe.GetRootsFromSPIFFEBundleMap(bm, leaf); err != nil {\n    if strings.Contains(err.Error(), \"no bundle found\") {\n        // refresh the federated bundle map and retry once\n    }\n}","preventionTips":["Subscribe to bundle-map updates so federation additions propagate promptly.","Cross-check the trust domain in issued SVIDs against the consumer's bundle map in CI.","Alert on stale bundle maps older than the rotation interval."],"tags":["grpc","spiffe","trust-domain","mtls","federation"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}