grpc/grpc-go · error

spiffe: BundleMapFromBytes() invalid trust domain

Error message

spiffe: BundleMapFromBytes() invalid trust domain %q found when parsing SPIFFE Bundle Map: %v

What it means

Raised while iterating the parsed `trust_domains` map: a key could not be turned into a SPIFFE trust domain via spiffeid.TrustDomainFromString. Trust domain names must conform to the SPIFFE spec (lowercase RFC 1123 domain label: letters, digits, hyphens, dots per segment; no scheme, no path).

Solutions

  1. Ensure each trust_domains key is the bare trust domain name (e.g. `example.org`), not a URI.
  2. Restrict keys to lowercase letters, digits, hyphens, and dots; no underscores, spaces, or slashes.
  3. Regenerate the bundle map from your SPIFFE federation endpoint so keys match the spec.
  4. If you control the producer, write keys with spiffeid.TrustDomain.String() to guarantee validity.

Example fix

// before
{"trust_domains": {"spiffe://example.org": {...}}}
// after
{"trust_domains": {"example.org": {...}}}
Defensive patterns

Strategy: validation

Validate before calling

var trustDomainRe = regexp.MustCompile(`^[a-z0-9]([a-z0-9\-\.]*[a-z0-9])?$`)
func validTrustDomainKeys(b []byte) error {
    var probe struct{ TD map[string]json.RawMessage `json:"trust_domains"` }
    if err := json.Unmarshal(b, &probe); err != nil { return err }
    for td := range probe.TD {
        if !trustDomainRe.MatchString(td) { return fmt.Errorf("bad trust domain key: %q", td) }
    }
    return nil
}

Try / catch

Pre-validate every trust_domains key with spiffeid.TrustDomainFromString before calling BundleMapFromBytes; collect all bad keys in one pass.

Prevention

When it happens

Trigger: A trust_domains key like `spiffe://example.org` (scheme not allowed in a trust domain name), `Example.Org` (uppercase), `my td` (space), `a_b` (underscore), or an empty string.

Common situations: Producer writes the full SPIFFE ID URI as the key instead of the bare trust domain; an upstream system normalizes inconsistently; hand-edited bundle map.

Related errors


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

Appendix: source

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

// BundleMapFromBytes parses bytes into a SPIFFE Bundle Map. See the
// SPIFFE Bundle Map spec for more detail -
// https://github.com/spiffe/spiffe/blob/main/standards/SPIFFE_Trust_Domain_and_Bundle.md#4-spiffe-bundle-format
// If duplicate keys are encountered in the JSON parsing, Go's default unmarshal
// behavior occurs which causes the last processed entry to be the entry in the
// parsed map.
func BundleMapFromBytes(bundleMapBytes []byte) (map[string]*spiffebundle.Bundle, error) {
	var result partialParsedSPIFFEBundleMap
	if err := json.Unmarshal(bundleMapBytes, &result); err != nil {
		return nil, err
	}
	if result.Bundles == nil {
		return nil, fmt.Errorf("spiffe: BundleMapFromBytes() no bundles parsed from spiffe bundle map bytes")
	}
	bundleMap := map[string]*spiffebundle.Bundle{}
	for td, jsonBundle := range result.Bundles {
		trustDomain, err := spiffeid.TrustDomainFromString(td)
		if err != nil {
			return nil, fmt.Errorf("spiffe: BundleMapFromBytes() invalid trust domain %q found when parsing SPIFFE Bundle Map: %v", td, err)
		}
		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 {

View on GitHub (pinned to 0c51461d27)