VYPR
Unrated severityNVD Advisory· Published Jun 2, 2026

CVE-2026-27145

CVE-2026-27145

Description

(*x509.Certificate).VerifyHostname previously called matchHostnames in a loop over all DNS Subject Alternative Name (SAN) entries. This caused strings.Split(host, ".") to execute repeatedly on the same input hostname. With a large DNS SAN list, verification costs scaled quadratically based on the number of SAN entries multiplied by the hostname's label count. Because x509.Verify validates hostnames before building the certificate chain, this overhead occurred even for untrusted certificates.

Patches

1
d01955d5d50c

crypto/x509: split candidate hostname only once

https://github.com/golang/goIan AlexanderMay 27, 2026via gerrit-cl
1 file changed · +9 6
  • src/crypto/x509/verify.go+9 6 modified
    @@ -110,7 +110,7 @@ func (h HostnameError) Error() string {
     	c := h.Certificate
     	maxNamesIncluded := 100
     
    -	if !c.hasSANExtension() && matchHostnames(c.Subject.CommonName, h.Host) {
    +	if !c.hasSANExtension() && matchHostnames(c.Subject.CommonName, splitHostname(h.Host)) {
     		return "x509: certificate relies on legacy Common Name field, use SANs instead"
     	}
     
    @@ -872,16 +872,14 @@ func matchExactly(hostA, hostB string) bool {
     	return toLowerCaseASCII(hostA) == toLowerCaseASCII(hostB)
     }
     
    -func matchHostnames(pattern, host string) bool {
    +func matchHostnames(pattern string, hostParts []string) bool {
     	pattern = toLowerCaseASCII(pattern)
    -	host = toLowerCaseASCII(strings.TrimSuffix(host, "."))
     
    -	if len(pattern) == 0 || len(host) == 0 {
    +	if len(pattern) == 0 || len(hostParts) == 0 {
     		return false
     	}
     
     	patternParts := strings.Split(pattern, ".")
    -	hostParts := strings.Split(host, ".")
     
     	if len(patternParts) != len(hostParts) {
     		return false
    @@ -959,6 +957,7 @@ func (c *Certificate) VerifyHostname(h string) error {
     
     	candidateName := toLowerCaseASCII(h) // Save allocations inside the loop.
     	validCandidateName := validHostnameInput(candidateName)
    +	hostParts := splitHostname(candidateName)
     
     	for _, match := range c.DNSNames {
     		// Ideally, we'd only match valid hostnames according to RFC 6125 like
    @@ -967,7 +966,7 @@ func (c *Certificate) VerifyHostname(h string) error {
     		// always allow perfect matches, and only apply wildcard and trailing
     		// dot processing to valid hostnames.
     		if validCandidateName && validHostnamePattern(match) {
    -			if matchHostnames(match, candidateName) {
    +			if matchHostnames(match, hostParts) {
     				return nil
     			}
     		} else {
    @@ -980,6 +979,10 @@ func (c *Certificate) VerifyHostname(h string) error {
     	return HostnameError{c, h}
     }
     
    +func splitHostname(host string) []string {
    +	return strings.Split(toLowerCaseASCII(strings.TrimSuffix(host, ".")), ".")
    +}
    +
     func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool {
     	usages := make([]ExtKeyUsage, len(keyUsages))
     	copy(usages, keyUsages)
    

Vulnerability mechanics

Root cause

"The `matchHostnames` function was repeatedly called within a loop, leading to quadratic performance scaling."

Attack vector

An attacker can trigger this vulnerability by providing a certificate with a large number of DNS Subject Alternative Name (SAN) entries. The `(*x509.Certificate).VerifyHostname` function, which is called during hostname verification, iterates through these SANs. This verification occurs even for untrusted certificates before the certificate chain is built, making it susceptible to performance degradation.

Affected code

The vulnerability exists in the `(*x509.Certificate).VerifyHostname` function within the `src/crypto/x509/verify.go` file. Specifically, the `matchHostnames` function was called repeatedly inside a loop over DNS SAN entries, causing `strings.Split(host, '.')` to execute multiple times on the same input [patch_id=4549445].

What the fix does

The patch modifies the `(*x509.Certificate).VerifyHostname` function to call `splitHostname` only once before the loop that iterates over SAN entries. The `matchHostnames` function is then updated to accept the pre-split hostname parts. This change ensures that the hostname is split into its constituent parts only once, preventing redundant computations and resolving the quadratic performance scaling issue [patch_id=4549445].

Generated on Jun 2, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.