{"record":{"id":"a5c3046ee2f0159a","repo":"grpc/grpc-go","slug":"spiffe-bundlemapfrombytes-failed-to-parse-bundl","errorCode":null,"errorMessage":"spiffe: BundleMapFromBytes() failed to parse bundle for trust domain %q: %v","messagePattern":"spiffe: BundleMapFromBytes\\(\\) failed to parse bundle for trust domain %q: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/credentials/spiffe/spiffe.go","lineNumber":59,"sourceCode":"// behavior occurs which causes the last processed entry to be the entry in the\n// parsed map.\nfunc BundleMapFromBytes(bundleMapBytes []byte) (map[string]*spiffebundle.Bundle, error) {\n\tvar result partialParsedSPIFFEBundleMap\n\tif err := json.Unmarshal(bundleMapBytes, &result); err != nil {\n\t\treturn nil, err\n\t}\n\tif result.Bundles == nil {\n\t\treturn nil, fmt.Errorf(\"spiffe: BundleMapFromBytes() no bundles parsed from spiffe bundle map bytes\")\n\t}\n\tbundleMap := map[string]*spiffebundle.Bundle{}\n\tfor td, jsonBundle := range result.Bundles {\n\t\ttrustDomain, err := spiffeid.TrustDomainFromString(td)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"spiffe: BundleMapFromBytes() invalid trust domain %q found when parsing SPIFFE Bundle Map: %v\", td, err)\n\t\t}\n\t\tbundle, err := spiffebundle.Parse(trustDomain, jsonBundle)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"spiffe: BundleMapFromBytes() failed to parse bundle for trust domain %q: %v\", td, err)\n\t\t}\n\t\tbundleMap[td] = bundle\n\t}\n\treturn bundleMap, nil\n}\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","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/credentials/spiffe/spiffe.go#L41-L77","documentation":"Raised when spiffebundle.Parse fails for an individual trust domain's bundle JSON inside the Bundle Map. The trust domain key was valid, but the bundle value is not a conformant SPIFFE Bundle (missing x509_authorities, malformed certificates, bad JWT keys, or wrong structure).","triggerScenarios":"A bundle value whose `x509_authorities` entries are not valid base64/PEM certificates, a bundle missing the required `keys`/`x509_authorities` fields, or a bundle with an incompatible spec version.","commonSituations":"Truncated or corrupted bundle bytes from a secret; a producer using a different SPIFFE Bundle revision; base64 encoding vs raw bytes mismatch; expired/rotated bundle not yet propagated.","solutions":["Fetch the bundle for the named trust domain directly from its SPIFFE Bundle Endpoint and diff it against your input.","Verify each x509_authorities entry is valid PEM/base64 DER that x509.ParseCertificate accepts.","Confirm the bundle JSON includes the required fields per the SPIFFE Bundle spec (e.g. `x509_authorities`, `sequence_number`).","If the corruption is from transport, re-fetch over a trusted channel and store atomically."],"exampleFix":"// before\n{\"trust_domains\": {\"example.org\": {\"x509_authorities\": [\"not-a-cert\"]}}}\n// after\n{\"trust_domains\": {\"example.org\": {\"x509_authorities\": [{\"X509\": \"<base64 DER>\"}], \"sequence_number\": 1}}}","handlingStrategy":"try-catch","validationCode":"func preCheckBundles(b []byte) error {\n    var probe struct{ TD map[string]json.RawMessage `json:\"trust_domains\"` }\n    if err := json.Unmarshal(b, &probe); err != nil { return err }\n    for td, raw := range probe.TD {\n        var bundle struct{ X509 []json.RawMessage `json:\"x509_authorities\"` }\n        if err := json.Unmarshal(raw, &bundle); err != nil { return fmt.Errorf(\"bundle %s: %w\", td, err) }\n        if len(bundle.X509) == 0 { return fmt.Errorf(\"bundle %s: no x509_authorities\", td) }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"Wrap BundleMapFromBytes in a recover/error-return; on failure, identify the offending trust domain from the error text and re-fetch just that bundle from its endpoint, then retry once.","preventionTips":["Fetch bundles over their HTTPS SPIFFE Bundle Endpoint and verify the signature/fingerprint.","Validate each x509_authorities entry parses as a cert before publishing.","Store bundles atomically to avoid half-written files."],"tags":["grpc","spiffe","tls","security","certificates","parsing"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}