Skip to content

crypto/x509: excessive chain-building work in Verify with many candidate parents (CVE-2026-32280) #78282

@jake-ciolek

Description

@jake-ciolek

Go version

go 1.26.1

Output of go env in your module/workspace:

GOARCH=arm64

What did you do?

Note: This was reported to security@golang.org and assigned a PUBLIC track.

Confirmed on Go 1.26.1 that x509.Certificate.Verify can become pathologically slow during chain building when the intermediates pool contains many distinct certificates that all look like plausible parents for the same child.

A representative TLS mTLS setup with a client certificate message just under the TLS certificate-message size limit caused about 434 ms in verification on Apple M2 before failing with:

x509: signature check attempts limit reached while verifying certificate chain

The same buildChains path is also reachable outside TLS when applications call Verify on attacker-controlled intermediate pools.

What did you see happen?

In crypto/x509/cert_pool.go, findPotentialParents returns all certificates whose raw subject matches the child certificate's issuer, ordered by key identifier plausibility.

In crypto/x509/verify.go, buildChains then walks those candidates recursively. Its loop prevention is alreadyInChain, which considers two certificates the same only if their subject, subject public key info, and SAN extension (if present) match.

That means many otherwise similar intermediates can still be treated as distinct by varying SAN bytes, so chain building explores far more candidates than expected.

This also seems related to the ordering in buildChains: alreadyInChain is checked before the signature-attempt limit is incremented and enforced. As a result, after the verification is already heading toward the maxChainSignatureChecks failure path, the verifier can still spend substantial time rescanning the existing chain for the remaining candidates.

In practice this can cause significant CPU use before verification fails. In TLS, this is constrained by the 256 KiB certificate-message limit and only applies when a server is configured to verify client certificates (for example VerifyClientCertIfGiven or RequireAndVerifyClientCert). Outside TLS, the practical impact depends on how much attacker-controlled certificate data an application accepts.

What did you expect to see?

Chain building should avoid spending large amounts of CPU on many lookalike parent candidates, and once the signature-attempt limit has effectively determined failure it should not keep paying the full alreadyInChain cost for the remaining candidates.

Additional reproduction details were shared with the security team.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugReportIssues describing a possible bug in the Go implementation.NeedsFixThe path to resolution is known, but the work has not been done.Security

    Type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions