Add support for matching certificate hostnames and IPs.
Review Request #15017 — Created April 16, 2026 and submitted
This introduces
Certificate.matches_host(), which takes a hostname or
IPv4/IPv6 address and matches it against the Subject and SAN values
stored in the certificate. This supports hostnames, IPv4 addresses, and
IPv6 addresses.
matches_host()starts by determining if this is an IP address or a
hostname, and then performs only the checks needed for that type.For IP checks, comparisons between instances are performed.
For hostname checks,
matches_host()wraps a new utility function,
get_cert_hostname_matches(), which can be used without aCertificate
instance. This supports bare hostnames, hostnames with multiple labels,
and wildcard patterns.Wildcard matching takes care to only match the first label in a hostname
(such as*.example.com) and to avoid matching bare hostnames. It does
not support partial wildcards, such asfoo*,*bar, orfoo*bar, as
these are largely unsupported by browsers, servers, and Certificate
Authorities these days (Chrome treats them as a security issue).
Certificate.subject_alternative_nameshas been updated to return
ipaddress.*instances for IP address/network values and strings for
hostnames. This allowsmatch_host()(and other callers) to handle each
entry correctly.
Unit tests pass.
| Summary | ID |
|---|---|
| cce7da0183927547aa7733a36ddaee6e39f97245 |
| Description | From | Last Updated |
|---|---|---|
|
Can we add some additional tests? Certificate with cert_data (exercising the subject path) Test to verify rejection of partial wildcards … |
|
|
|
self.subject can be None Based on the implementation of the tests (and the docstring), it looks like maybe you had … |
|
|
|
SAN can contain IP addresses. While the wildcard logic in get_cert_hostname_matches works incidentally for that, it might be nice to … |
|
|
|
Typo: futher -> further |
|
|
|
Can we add a debug log in case this fails because of a partial wildcard? |
|
|
|
This is no longer just string values. |
|
|
|
This stray line got left over from a previous iteration. |
|
- Change Summary:
-
Hostname matching now uses the Subject instead of the caller-provided hostname.
- Commits:
-
Summary ID 2cde0d4733368274e342a5aa748efe875ff6d72b 8db5a6fef00d888a815fe6768ea804686cdff372
Checks run (2 succeeded)
-
-
Can we add some additional tests?
Certificatewithcert_data(exercising thesubjectpath)- Test to verify rejection of partial wildcards
- IPv4 and IPv6 address in SAN entries
- Bare cert hostname (like "localhost")
-
self.subjectcan beNoneBased on the implementation of the tests (and the docstring), it looks like maybe you had this as
self.hostnameinitially?The tests are constructing the cert without
cert_data(therefore without a subject), so I would expect this to raise if you ran them. -
SAN can contain IP addresses. While the wildcard logic in
get_cert_hostname_matchesworks incidentally for that, it might be nice to detect these and force a direct comparison instead. -
-
- Change Summary:
-
subject_alternative_namesnow returns strings for hostnames andipaddress.*instances for IPs.matches_hostname()has been renamed tomatch_host(), and supports IPv4/IPv6 address checks.- Hostname checks now handle a lack of a Subject Common Name.
- Added
normalize_cert_hostname(), which takes a valid hostname value and normalizes it for comparison/storage. (Note: I want to avoid things like whitespace checks here, as cert data should be valid or treated as a bad match, and user input should be explicitly validated elsewhere.) - Added more unit tests for testing with the various SAN value types, and testing against SSL cert data.
- Fixed a typo in docs.
- Summary:
-
Add support for matching certificate hostnames.Add support for matching certificate hostnames and IPs.
- Description:
-
~ This introduces
Certificate.matches_hostname(), which takes a hostname~ and matches it against the hostnames and/or wildcard hostnames stored in ~ the certificate (as both the primary hostname and in the SAN fields). ~ This introduces
Certificate.matches_host(), which takes a hostname or~ IPv4/IPv6 address and matches it against the Subject and SAN values ~ stored in the certificate. This supports hostnames, IPv4 addresses, and + IPv6 addresses. ~ It wraps a utility function,
get_cert_hostname_matches(), which can be~ used without a Certificateinstance.~ matches_host()starts by determining if this is an IP address or a~ hostname, and then performs only the checks needed for that type. + + For IP checks, comparisons between instances are performed.
+ + For hostname checks,
matches_host()wraps a new utility function,+ get_cert_hostname_matches(), which can be used without aCertificate+ instance. This supports bare hostnames, hostnames with multiple labels, + and wildcard patterns. Wildcard matching takes care to only match the first label in a hostname
(such as *.example.com) and to avoid matching bare hostnames. It doesnot support partial wildcards, such as foo*,*bar, orfoo*bar, asthese are largely unsupported by browsers, servers, and Certificate Authorities these days (Chrome treats them as a security issue). + + Certificate.subject_alternative_nameshas been updated to return+ ipaddress.*instances for IP address/network values and strings for+ hostnames. This allows match_host()(and other callers) to handle each+ entry correctly. - Commits:
-
Summary ID 8db5a6fef00d888a815fe6768ea804686cdff372 cce7da0183927547aa7733a36ddaee6e39f97245