grpc/grpc-go · error
xds: received DNS SANs: %v do not match the SNI: %s
Error message
xds: received DNS SANs: %v do not match the SNI: %s
What it means
Returned by the peer verifier when SNI-based SAN validation is enabled (envconfig.XDSSNIEnabled && hi.validateSANUsingSNI && sni != "") and none of the leaf cert's DNS SANs match the SNI value via dnsMatch. dnsMatch supports exact and single-label wildcard matching; if every DNS SAN fails, the connection is rejected. This protects against a server presenting a cert valid for a different hostname than the one requested.
Source
Thrown at internal/credentials/xds/handshake_info.go:311
} else {
opts.KeyUsages = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}
}
if _, err := certs[0].Verify(opts); err != nil {
return err
}
// If XDSSNIEnabled and AutoSNISANValidation are both true and the SNI is
// non-empty, validate only DNS SANs against the SNI. Otherwise, fallback to
// validating all received SANs against the control plane provided SAN
// matchers.
if envconfig.XDSSNIEnabled && hi.validateSANUsingSNI && sni != "" {
// Verify SAN of leaf certificate with SNI using exact DNS matcher.
for _, san := range certs[0].DNSNames {
if dnsMatch(sni, san) {
return nil
}
}
return fmt.Errorf("xds: received DNS SANs: %v do not match the SNI: %s", certs[0].DNSNames, sni)
}
// The SANs sent by the xDS control plane are encoded as SPIFFE IDs. We need to
// only look at the SANs on the leaf cert.
if cert := certs[0]; !hi.MatchingSANExists(cert) {
// TODO: Print the complete certificate once the x509 package
// supports a String() method on the Certificate type.
return 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)
}
return nil
}
}
// serverSideTLSConfigInternal constructs a tls.Config to be used in a
// server-side handshake based on the contents of the HandshakeInfo.
func (hi *HandshakeInfo) serverSideTLSConfigInternal(ctx context.Context) (*tls.Config, error) {
cfg := &tls.Config{
ClientAuth: tls.NoClientCert,
NextProtos: []string{"h2"},View on GitHub (pinned to 03255a9237)
Solutions
- Issue a server certificate whose DNS SANs include the hostname(s) clients connect by (or a covering wildcard).
- Disable useAutoHostSNI so the control-plane SNI value is used and matches the cert.
- Connect via a hostname that is actually present in the server cert's DNS SANs.
- Re-check the xDS Cluster configuration for the intended SNI vs. the certificate served by the endpoint.
Defensive patterns
Strategy: validation
Validate before calling
func certCoversSNI(c *x509.Certificate, sni string) bool {
for _, san := range c.DNSNames {
if dnsMatch(sni, san) { return true }
}
return false
}
func dnsMatch(host, san string) bool {
host = strings.ToLower(strings.TrimSuffix(host, ".") + ".")
san = strings.ToLower(strings.TrimSuffix(san, ".") + ".")
if !strings.Contains(san, "*") { return host == san }
if san == "*." || !strings.HasPrefix(san, "*.") || strings.Contains(san[1:], "*") { return false }
if len(host) < len(san) || !strings.HasSuffix(host, san[1:]) { return false }
return !strings.Contains(strings.TrimSuffix(host, san[1:]), ".")
} Prevention
- Issue server certs whose DNS SANs cover every hostname clients (or AutoHostSNI) will use.
- Audit cert SAN sets after renewal against the configured SNI.
- Avoid enabling useAutoHostSNI against endpoints whose certs cover only a wildcard-free name.
When it happens
Trigger: buildVerifyFunc at handshake_info.go:304-311: the client connected with SNI=foo.example.com but the server cert's DNS SANs are only [bar.example.com] or [*.other.com]. AutoHostSNI substituted the endpoint hostname as SNI, and that hostname is not covered by the cert.
Common situations: AutoHostSNI enabled with a load balancer whose cert SANs don't include the per-endpoint hostname; cert renewed with a narrower SAN set; connecting by IP or short name that's not in the cert; SNI propagation broken by a proxy.
Related errors
- xds: received SANs {DNSNames: %v, EmailAddresses: %v, IPAddr
- spiffe: verify function could not parse input certificate: %
- spiffe: verify function has no valid input certificates
- spiffe: x509 certificate Verify failed: %v
- xds: CertificateProvider to fetch trusted roots is missing,
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/f0a5ba988155476f.
Report an issue: GitHub.