Skip to content

match spki pins only against the peer's signing chain - #933

Open
Hsnmohd wants to merge 1 commit into
apache:masterfrom
Hsnmohd:spki-pin-signing-chain
Open

Hsnmohd wants to merge 1 commit into
apache:masterfrom
Hsnmohd:spki-pin-signing-chain

Conversation

@Hsnmohd

@Hsnmohd Hsnmohd commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

chainSpkiSha256 hashed every certificate in SSLSession.getPeerCertificates(), the chain as sent rather than the path the trust manager validated, so a server holding any CA-trusted certificate for a pinned host could append the real pinned certificate (public, and ignored by JSSE path building) and pass enforcePins (same bypass as OkHttp CVE-2016-2402, reproduced with real handshakes on the classic and async clients); pins now only match the leaf and the presented certificates that verifiably sign it.

@arturobernalg

Copy link
Copy Markdown
Member

SSLSession.getPeerCertificates() does not necessarily represent the certificate path validated by the trust manager.

cert.verify() only verifies the signature. It does not establish that the certificate was part of the validated path.

@Hsnmohd

Hsnmohd commented Nov 8, 2026

Copy link
Copy Markdown
Contributor Author

Agreed, the walk only proves signatures; it isn't path validation. It skips basicConstraints, validity and name constraints, takes the first candidate that matches, and nothing ties it to where the trust manager's path ended, so it can still be steered. A trusted interception CA can issue the leaf through an intermediate whose subject and key match a CA=false DV certificate it obtained for that same key from the pinned CA. Send the DV cert ahead of the intermediate and the walk goes through it to the pinned key, while JSSE validates the leaf through the intermediate to the interception root.

Matching against the validated path needs the trust anchors, and an SSLContext doesn't expose its trust manager. What I'd do is add a builder overload that takes the X509TrustManager, rebuild the path with PKIX CertPathBuilder against its accepted issuers, and match pins only on that path and its anchor. If you'd rather not grow the API for this, I'll close the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants