{"record":{"id":"f0a5ba988155476f","repo":"grpc/grpc-go","slug":"xds-received-dns-sans-v-do-not-match-the-sni","errorCode":null,"errorMessage":"xds: received DNS SANs: %v do not match the SNI: %s","messagePattern":"xds: received DNS SANs: (.+?) do not match the SNI: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/credentials/xds/handshake_info.go","lineNumber":311,"sourceCode":"\t\t} else {\n\t\t\topts.KeyUsages = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}\n\t\t}\n\t\tif _, err := certs[0].Verify(opts); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// If XDSSNIEnabled and AutoSNISANValidation are both true and the SNI is\n\t\t// non-empty, validate only DNS SANs against the SNI. Otherwise, fallback to\n\t\t// validating all received SANs against the control plane provided SAN\n\t\t// matchers.\n\t\tif envconfig.XDSSNIEnabled && hi.validateSANUsingSNI && sni != \"\" {\n\t\t\t// Verify SAN of leaf certificate with SNI using exact DNS matcher.\n\t\t\tfor _, san := range certs[0].DNSNames {\n\t\t\t\tif dnsMatch(sni, san) {\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"xds: received DNS SANs: %v do not match the SNI: %s\", certs[0].DNSNames, sni)\n\t\t}\n\t\t// The SANs sent by the xDS control plane are encoded as SPIFFE IDs. We need to\n\t\t// only look at the SANs on the leaf cert.\n\t\tif cert := certs[0]; !hi.MatchingSANExists(cert) {\n\t\t\t// TODO: Print the complete certificate once the x509 package\n\t\t\t// supports a String() method on the Certificate type.\n\t\t\treturn fmt.Errorf(\"xds: received SANs {DNSNames: %v, EmailAddresses: %v, IPAddresses: %v, URIs: %v} do not match any of the accepted SANs\", cert.DNSNames, cert.EmailAddresses, cert.IPAddresses, cert.URIs)\n\t\t}\n\t\treturn nil\n\t}\n}\n\n// serverSideTLSConfigInternal constructs a tls.Config to be used in a\n// server-side handshake based on the contents of the HandshakeInfo.\nfunc (hi *HandshakeInfo) serverSideTLSConfigInternal(ctx context.Context) (*tls.Config, error) {\n\tcfg := &tls.Config{\n\t\tClientAuth: tls.NoClientCert,\n\t\tNextProtos: []string{\"h2\"},","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/credentials/xds/handshake_info.go#L293-L329","documentation":"Raised in the SNI-based SAN validation branch when envconfig.XDSSNIEnabled and hi.validateSANUsingSNI are both true and sni is non-empty, but none of the leaf certificate's DNS SANs match the SNI value via dnsMatch. The connection is rejected because the server cert does not attest the name the client used for SNI.","triggerScenarios":"Client sets SNI to `api.example.org` but the server cert only has DNS SAN `svc.internal`, or a wildcard `*.internal` that does not match `api.example.org`; auto-host SNI picked an IP or hostname not covered by the cert; DNS SANs present but on a different domain.","commonSituations":"Connecting via a VIP or alias not listed in the cert; auto-host SNI enabled so the endpoint hostname becomes SNI, but the cert was issued for the cluster's virtual host; cert rotation to a new domain while clients still dial the old name; wildcard mismatch across domain levels.","solutions":["Make the SNI value match a DNS SAN on the server certificate (exact or valid wildcard).","If using useAutoHostSNI, ensure the endpoint hostname is a DNS SAN on the cert, or disable auto-host SNI and set sni to the certified name.","Re-issue the server certificate to include the name clients dial.","If SNI/SAN validation should not apply, disable validateSANUsingSNI on the cluster security config (it then falls back to SAN matchers)."],"exampleFix":"// before: SNI=api.example.org, cert DNS SANs=[svc.internal] -> error\n// after: re-issue cert with DNS SAN api.example.org, or set sni=\"svc.internal\"","handlingStrategy":"validation","validationCode":"func sniMatchesCertSANs(sni string, dnsSANs []string) bool {\n    for _, san := range dnsSANs {\n        if dnsMatch(sni, san) { return true }\n    }\n    return false\n}\n// validate against the expected server cert's DNS SANs before dialing","typeGuard":null,"tryCatchPattern":"When validateSANUsingSNI is on and the dial fails with this error, catch it at the RPC layer, log the SNI and the cert's DNS SANs, and either correct the SNI/dial target or re-issue the cert; do not silently retry with the same SNI.","preventionTips":["Keep the SNI (or auto-host-SNI hostname) within the set of DNS SANs on the server cert.","Disable useAutoHostSNI if endpoint hostnames are not all covered by the cert.","Coordinate cert issuance with the names clients dial; add a CI check comparing dial targets to DNS SANs."],"tags":["grpc","xds","tls","san","sni","security","handshake"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}