Error message
x509: certificate relies on legacy Common Name field, use SANs instead
Also printed as
- tls: failed to verify certificate: x509: certificate relies on legacy Common Name field, use SANs instead
Inside TLS dials (Go 1.20+) the text is prefixed with "tls: failed to verify certificate: ", and HTTP clients add "Get \"https://…\": ". Programs built with Go (kubectl, Terraform, Docker, Prometheus, Vault CLI) print the same text.
Go crypto/x509 — HostnameError for a certificate without subjectAltName (Go 1.15+)
What it means
The server's certificate has no Subject Alternative Name extension, so the host name exists only in the subject's Common Name. Go stopped accepting host names from the Common Name in Go 1.15 (fully in 1.17), following RFC 6125 and the CA/Browser Forum rules, and says so explicitly when the CN would have matched. The fix is a certificate with SANs; there is no client-side switch left.
Why it happens
The certificate was generated without subjectAltName
commonopenssl req -x509 -subj "/CN=host" without -addext subjectAltName, or openssl x509 -req signing a CSR without -copy_extensions/-extfile, produces exactly this kind of certificate.
An internal CA profile that predates the SAN requirement
commonOld Active Directory Certificate Services templates, legacy scripts and appliance CAs often issue CN-only certificates.
Self-generated certificates of devices and old software
occasionalSome appliances, databases and middleware generate CN-only certificates on first start.
How to fix it
- 1.
Confirm that the SAN extension is missing
Print the subject and subjectAltName of the served certificate.
bash echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \ | openssl x509 -noout -subject -ext subjectAltName # No "X509v3 Subject Alternative Name" in the output -> reissue the certificate - 2.
Reissue with subjectAltName
Put every DNS name (and IP address, if clients use one) into subjectAltName. When signing CSRs with openssl x509 -req, extensions from the CSR are dropped unless you pass -copy_extensions copy or an -extfile.
bash openssl req -new -key server.key -subj "/CN=api.example.com" \ -addext "subjectAltName=DNS:api.example.com" -out server.csr # when signing with "openssl x509 -req", keep the extension: openssl x509 -req -in server.csr -CA ca.pem -CAkey ca.key -days 90 -copy_extensions copy -out server.pem - 3.
Do not look for a Go flag
The temporary GODEBUG=x509ignoreCN=0 escape hatch was removed in Go 1.17, so reissuing the certificate is the only fix.
text GODEBUG=x509ignoreCN=0 only worked in Go 1.15–1.16 and was removed in Go 1.17; there is no switch left in current Go releases. The certificate must carry SANs.
Related errors
x509: certificate is valid for example.com, not api.example.comGo crypto/x509x509: certificate is not valid for any names, but wanted to match api.example.c…Go crypto/x509No subject alternative names presentJava (JSSE HostnameChecker)tls: failed to verify certificate: x509: certificate signed by unknown authorityGo crypto/tls (Go ≥ 1.20)