ARGEMMA BLOG

Notes on Go's CVE-2026-27137 and CVE-2026-27138

Kelby Ludwig
Kelby Ludwig Security Engineer

Go 1.26.1 is out

Yesterday afternoon the Go team published a minor point release of Go 1.26 that fixed five security issues, including two CVEs in crypto/x509:

You should just update to Go 1.26.1 and remove the possibility of an issue altogether, but unless you operate Go code deep in the X.509 weeds you are probably not affected by the crypto/x509 issues.

Regardless, they are interesting bugs if you consider PKI and PKI accessories interesting, so I took some notes on them.

CVE-2026-27137

CVE-2026-27137 is a failure of enforcing X.509 Name Constraints. Name constraints allow a certificate authority (CA) to place restrictions on which names are considered valid in certificates chained through it. A root CA may want to trust an intermediate CA to issue certificates, but only for subdomains of example.com, so the root puts a name constraint on the intermediate certificate. When verifying a certificate chain, an otherwise validly signed and trusted certificate only passes verification if it's a subdomain of example.com. Name constraints can be applied to multiple types of names (e.g. domain names, IP addresses, URLs) and are specified as some combination of permitted or excluded names. In Go, these are expressed like:

// relevant x509.Certificate fields from
// https://pkg.go.dev/crypto/x509#Certificate

// Name constraints
PermittedDNSDomains         []string
ExcludedDNSDomains          []string
PermittedIPRanges           []*net.IPNet
ExcludedIPRanges            []*net.IPNet
PermittedEmailAddresses     []string
ExcludedEmailAddresses      []string
PermittedURIDomains         []string
ExcludedURIDomains          []string

This issue applies to email addresses specifically. The list of Permitted/ExcludedEmailAddresses was previously stored in a map[string]string which mapped the "local" part of an email address to the email address' domain. E.g. foo@example.com would be the map {"foo":"example.com"}. This is an issue because the map is lossy if name constraints specify multiple local names but different domains.

If a CA that intended to delegate issuance with ExcludedEmailAddresses set to []string{"admin@company.com", "admin@company-internal.com"} only the last constraint would be enforced as both have the same map key of admin. This means a certificate issued by an intermediate with the name admin@company.com would be considered valid despite the CA's intended name constraint exclusion. The fix was to use a map key that contained a normalized version of the full email address.

CVE-2026-27138

With all the name constraint background out of the way, CVE-2026-27138 is simpler to explain. CVE-2026-27138 is a panic in the DNS name constraint checking logic. If a CA specified any ExcludedDNSDomains, a certificate with the name "" (Specifically a subjectAltName) would cause a panic in this branch:

// Snippet from `src/crypto/x509/constraints.go`

// if `len(s) == 0` s[0] will panic
if !dnc.permitted && s[0] == '*' {

An empty name, according to the Go release notes, is a malformed certificate and RFC 5280 also seems to imply this:

In addition, while the string " " is a legal domain name, subjectAltName extensions with a dNSName of " " MUST NOT be used.

(Note: the RFC uses " " but it likely means "" here.)

If an attacker can generate a validly signed and trusted certificate with an intentionally empty SAN, they could force the program to panic. The fix here was to defensively check the string length.