Skip to content

Normalize trailing dot when matching hostnames against certificate pins - #9734

Open
adityaanikam wants to merge 1 commit into
lysine-dev:mainfrom
adityaanikam:fix-certpinner-trailing-dot-9724
Open

Normalize trailing dot when matching hostnames against certificate pins#9734
adityaanikam wants to merge 1 commit into
lysine-dev:mainfrom
adityaanikam:fix-certpinner-trailing-dot-9724

Conversation

@adityaanikam

@adityaanikam adityaanikam commented Aug 28, 2026

Copy link
Copy Markdown

Fixes #9724.

Credit to Joshua Rogers (MegaManSec) for finding and reporting this, with a clear write-up and working PoC in the issue.

CertificatePinner.Pin.matchesHostname() compares hostname against pattern with plain string equality (or region matching for wildcard patterns), with no normalization of either side. hostname comes from address.url.host in ConnectPlan, which explicitly preserves a trailing dot for an absolute DNS name. A pin's pattern is developer-authored config and never has one. So a pin for example.com provides no protection at all against a connection to example.com. -- same host at the DNS level, but the pin is silently skipped, and the connection is verified against an ordinary CA-issued certificate instead.

OkHostnameVerifier already treats both spellings as equivalent for exactly this reason (it normalizes both hostname and pattern to absolute form before comparing). CertificatePinner never got the same treatment.

Fix: strip a single trailing dot from hostname at the top of matchesHostname, before the wildcard/exact-match dispatch. All three branches (**., *., and exact) already reference the same hostname identifier, so this one change covers them uniformly. pattern is left untouched -- it is never legitimately going to carry a trailing dot in practice, and the reported issue is specifically about the hostname side.

Added testMatchesHostnameWithTrailingDot to CertificatePinnerKotlinTest, covering both the exact-match and wildcard branches directly on Pin.matchesHostname, plus the reporter's own findMatchingPins() shape.

Verified with a decisive negative control: reverting only the source fix (keeping the new test) reproduces the exact reported behavior -- the test fails with "expected: but was: " on the trailing-dot assertion, confirming the old code silently skips the pin for the dotted hostname.

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

CertificatePinner isn't pinning the hostname properly

1 participant