{"record":{"id":"98d5ce9976a14ade","repo":"grpc/grpc-go","slug":"spiffe-x509-certificate-verify-failed-v","errorCode":null,"errorMessage":"spiffe: x509 certificate Verify failed: %v","messagePattern":"spiffe: x509 certificate Verify failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/bootstrap/tlscreds/bundle.go","lineNumber":190,"sourceCode":"\t\t}\n\t\tleafCert := rawCertList[0]\n\t\troots, err := spiffe.GetRootsFromSPIFFEBundleMap(spiffeBundleMap, leafCert)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\topts := x509.VerifyOptions{\n\t\t\tRoots:         roots,\n\t\t\tCurrentTime:   time.Now(),\n\t\t\tIntermediates: x509.NewCertPool(),\n\t\t}\n\n\t\tfor _, cert := range rawCertList[1:] {\n\t\t\topts.Intermediates.AddCert(cert)\n\t\t}\n\t\t// The verified chain is (surprisingly) unused.\n\t\tif _, err = rawCertList[0].Verify(opts); err != nil {\n\t\t\treturn fmt.Errorf(\"spiffe: x509 certificate Verify failed: %v\", err)\n\t\t}\n\t\treturn nil\n\t}\n}\n","sourceCodeStart":172,"sourceCodeEnd":195,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/xds/bootstrap/tlscreds/bundle.go#L172-L195","documentation":"The SPIFFE verify callback builds x509.VerifyOptions with roots derived from the SPIFFE bundle map and runs the leaf certificate through x509.Certificate.Verify (bundle.go:185-190). If the certificate chain cannot be validated against the SPIFFE roots — expired cert, untrusted root, broken chain, wrong trust domain — Verify returns an error that is wrapped here.","triggerScenarios":"The server's leaf certificate does not chain to any root in the SPIFFE trust bundle map for the certificate's trust domain; the certificate is expired; the current time (time.Now()) is outside the cert's validity window; the trust domain in the cert's SPIFFE ID has no matching bundle.","commonSituations":"The SPIFFE bundle map file is stale and does not contain the server's current trust domain; the server rotated its CA but the bundle map was not refreshed; clock skew between client and server makes a valid cert appear expired; wrong trust domain mapping.","solutions":["Check the wrapped error — it indicates the specific x509 failure (e.g. x509: certificate signed by unknown authority, certificate has expired).","Refresh the spiffe_trust_bundle_map_file so it includes the server's current trust domain and root CA.","Correct any clock skew on the client (VerifyOptions uses time.Now()).","Confirm the server's SPIFFE ID trust domain matches an entry in the bundle map."],"exampleFix":"# inspect the failing cert and its trust domain:\n#   openssl s_client -connect xds-server:443 -showcerts\n# ensure the trust domain's root in spiffe_trust_bundle_map_file\n# matches the CA that signed the server cert","handlingStrategy":"try-catch","validationCode":"// Validate the server cert chains to a root in the SPIFFE bundle map.\nfunc verifyAgainstBundle(addr string, bundleFile string) error {\n    b, err := os.ReadFile(addr) // placeholder: load bundle map\n    _ = b\n    conf := &tls.Config{ServerName: addr}\n    conn, err := tls.Dial(\"tcp\", addr, conf)\n    if err != nil { return err }\n    defer conn.Close()\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err := creds.ClientHandshake(ctx, authority, conn); err != nil {\n    if strings.Contains(err.Error(), \"Verify failed\") {\n        // likely expired/untrusted cert or stale bundle; refresh and retry\n    }\n    return err\n}","preventionTips":["Keep the spiffe_trust_bundle_map_file current with the server's CA rotation.","Sync clocks (NTP) to avoid false expiry failures from clock skew.","Verify the server cert's SPIFFE trust domain is present in the bundle map before connecting."],"tags":["xds","tls","spiffe","mtls","certificate","trust-chain","grpc"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}