Hostname Validator¶
Confirms the certificate was actually issued for the host you connected to. hostname matches the host against the certificate's Subject Alternative Names (SANs) including wildcard certificates (*.example.com). A mismatch is what your browser shows as "this certificate is not valid for this site."
Enabled by default
hostname is one of the three default validators. The host you pass to CertMonitor(...) is the name it checks against. To check a different name, pass validator_args={"hostname": {"expected_identity": "..."}}.
Try it¶
from certmonitor import CertMonitor
with CertMonitor("example.com") as monitor:
monitor.get_cert_info()
print(monitor.validate()["hostname"])
A matching hostname reports which name matched and the SANs it considered:
These examples show selected fields from illustrative scans. validate() also adds status and code, described in the result contract.
{
"is_valid": true,
"alt_names": [
"example.com",
"*.example.com"
],
"identity_source": "subjectAltName",
"common_name": "example.com",
"common_name_matches": true,
"matched_name": "example.com"
}
A mismatch fails with a reason:
{
"is_valid": false,
"alt_names": [
"*.badssl.com",
"badssl.com"
],
"identity_source": "subjectAltName",
"common_name": "*.badssl.com",
"common_name_matches": false,
"reason": "Hostname wrong.host.badssl.com doesn't match any of the certificate's subject alternative names"
}
How matching works¶
- Common Name:
common_nameandcommon_name_matchesreport the CN comparison for reference. CN does not determineis_validor replace missing SANs. - DNS/IP SANs: DNS names are checked case-insensitively after IDNA normalization. IP addresses match IP Address SANs by address equality.
- Wildcards: a
*.example.comSAN matches exactly one label (api.example.com), but not the bare apex (example.com) or nested subdomains (a.b.example.com).
Checking with an IP address?
Connecting by IP will usually fail hostname unless the certificate carries that IP as a SAN (most don't). See Using IP Addresses for how CertMonitor handles IP targets.
SAN-based identity validation follows RFC 9525.
Reference¶
certmonitor.validators.hostname.HostnameValidator ¶
Bases: BaseCertValidator
A validator for checking the hostname in an SSL certificate.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
The name of the validator. |
validate ¶
validate(cert: dict[str, Any], host: str, port: int, *, expected_identity: str | None = None) -> HostnameResult
Validates the hostname against the Subject Alternative Names (SANs) in the provided SSL certificate.
Common Name is also reported in common_name and common_name_matches
for inspection. It never overrides the SAN-based is_valid result.
DNS matching is case-insensitive, and IP identities match IP Address SANs.
matched_name is the SAN entry that matched: the exact name, the
wildcard pattern, or the IP address.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cert
|
dict
|
The SSL certificate. |
required |
host
|
str
|
The hostname to validate. |
required |
port
|
int
|
The port number. |
required |
expected_identity
|
str
|
A DNS name or IP address to check instead
of |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
dict |
HostnameResult
|
A dictionary containing the validation results, including whether the hostname is valid, the reason for validation failure, and the alternative names (SANs) in the certificate. |
Examples:
Example output (success): This example shows a certificate where the hostname matches one of the DNS SANs, so validation passes and the matched name is shown.
{
"is_valid": true,
"matched_name": "example.com",
"alt_names": [
"example.com",
"www.example.com"
]
}
Example output (failure): This example shows a certificate where the hostname does not match any DNS SAN, so validation fails and a reason is provided.
{
"is_valid": false,
"reason": "Hostname test.example.com doesn't match any of the certificate's subject alternative names",
"alt_names": [
"example.com",
"www.example.com"
]
}
Source code in certmonitor/validators/hostname.py
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | |