https://github.com/python/cpython/commit/8dde46eaa6baf5f027a7234845b20d50b509624e
commit: 8dde46eaa6baf5f027a7234845b20d50b509624e
branch: main
author: Brett Smith <[email protected]>
committer: StanFromIreland <[email protected]>
date: 2026-11-07T19:07:53Z
summary:
gh-161503: Check hostname in `ssl.get_server_certificate` with custom
`ca_certs` (#161507)
files:
A Misc/NEWS.d/next/Security/2026-11-06-16-22-47.gh-issue-161503.FkIl87.rst
M Doc/library/ssl.rst
M Lib/ssl.py
M Lib/test/test_ssl.py
diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst
index d177abd48fa9cd4..020a8ab7301b6b7 100644
--- a/Doc/library/ssl.rst
+++ b/Doc/library/ssl.rst
@@ -432,7 +432,8 @@ Certificate handling
same format as used for the *cafile* parameter in
:meth:`SSLContext.load_verify_locations`. The call will attempt to
validate the
server certificate against that set of root certificates, and will fail
- if the validation attempt fails. A timeout can be specified with the
+ if the validation attempt fails or the certificate hostname does not match
+ the server hostname. A timeout can be specified with the
``timeout`` parameter.
.. versionchanged:: 3.3
@@ -445,6 +446,11 @@ Certificate handling
.. versionchanged:: 3.10
The *timeout* parameter was added.
+ .. versionchanged:: next
+ The function now raises :exc:`SSLCertVerificationError` if *ca_certs* is
+ specified but the certificate hostname does not match the server
+ hostname.
+
.. function:: DER_cert_to_PEM_cert(der_cert_bytes)
Given a certificate as a DER-encoded blob of bytes, returns a PEM-encoded
diff --git a/Lib/ssl.py b/Lib/ssl.py
index df2eece13f2b138..49eec9cde0b6317 100644
--- a/Lib/ssl.py
+++ b/Lib/ssl.py
@@ -1638,7 +1638,8 @@ def get_server_certificate(addr,
ssl_version=PROTOCOL_TLS_CLIENT,
ca_certs=None, timeout=_GLOBAL_DEFAULT_TIMEOUT):
"""Retrieve the certificate from the server at the specified address,
and return it as a PEM-encoded string.
- If 'ca_certs' is specified, validate the server cert against it.
+ If 'ca_certs' is specified, validate the server cert against it and
+ check that it matches the hostname.
If 'ssl_version' is specified, use it in the connection attempt.
If 'timeout' is specified, use it in the connection attempt.
"""
@@ -1650,6 +1651,7 @@ def get_server_certificate(addr,
ssl_version=PROTOCOL_TLS_CLIENT,
cert_reqs = CERT_NONE
context = _create_stdlib_context(ssl_version,
cert_reqs=cert_reqs,
+ check_hostname=ca_certs is not None,
cafile=ca_certs)
with create_connection(addr, timeout=timeout) as sock:
with context.wrap_socket(sock, server_hostname=host) as sslsock:
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
index 5b4e4f080607726..b0e3cbaa548e8d5 100644
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -3112,6 +3112,10 @@ def test_get_server_certificate_fail(self):
# independent test method
_test_get_server_certificate_fail(self, *self.server_addr)
+ def test_get_server_certificate_fail_by_hostname(self):
+ _, port = self.server_addr
+ _test_get_server_certificate_fail(self, socket_helper.HOSTv4, port,
SIGNING_CA)
+
def test_get_server_certificate_timeout(self):
def servername_cb(ssl_sock, server_name, initial_context):
time.sleep(0.2)
@@ -3364,10 +3368,10 @@ def _test_get_server_certificate(test, host, port,
cert=None):
if support.verbose:
sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host,
port ,pem))
-def _test_get_server_certificate_fail(test, host, port):
+def _test_get_server_certificate_fail(test, host, port, ca_certs=CERTFILE):
with warnings_helper.check_no_resource_warning(test):
try:
- pem = ssl.get_server_certificate((host, port), ca_certs=CERTFILE)
+ pem = ssl.get_server_certificate((host, port), ca_certs=ca_certs)
except ssl.SSLError as x:
#should fail
if support.verbose:
diff --git
a/Misc/NEWS.d/next/Security/2026-11-06-16-22-47.gh-issue-161503.FkIl87.rst
b/Misc/NEWS.d/next/Security/2026-11-06-16-22-47.gh-issue-161503.FkIl87.rst
new file mode 100644
index 000000000000000..308ba0c83f3efe4
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2026-11-06-16-22-47.gh-issue-161503.FkIl87.rst
@@ -0,0 +1,4 @@
+.. cve: CVE-2026-19552
+
+:func:`ssl.get_server_certificate` now verifies that the server hostname
matches
+its certificate when the caller specifies *ca_certs*.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]