Skip to content

Commit 8d65ea1

Browse files
authored
Merge pull request from GHSA-5phf-pp7p-vc2r
* Enable hostname verification for HTTPS proxies with default cert. Signed-off-by: Jorge Lopez Silva <jalopezsilva@gmail.com> * Adjust exception check for Python 3.9+ Signed-off-by: Jorge Lopez Silva <jalopezsilva@gmail.com> * Use a SAN instead of a common name. Signed-off-by: Jorge Lopez Silva <jalopezsilva@gmail.com>
1 parent 5e34326 commit 8d65ea1

File tree

3 files changed

+37
-0
lines changed

3 files changed

+37
-0
lines changed

src/urllib3/connection.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,10 @@ def _connect_tls_proxy(self, hostname, conn):
490490
self.ca_cert_dir,
491491
self.ca_cert_data,
492492
)
493+
# By default urllib3's SSLContext disables `check_hostname` and uses
494+
# a custom check. For proxies we're good with relying on the default
495+
# verification.
496+
ssl_context.check_hostname = True
493497

494498
# If no cert was provided, use only the default options for server
495499
# certificate validation

test/conftest.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,17 @@ def no_san_server(tmp_path_factory):
6464
yield cfg
6565

6666

67+
@pytest.fixture
68+
def no_localhost_san_server(tmp_path_factory):
69+
tmpdir = tmp_path_factory.mktemp("certs")
70+
ca = trustme.CA()
71+
# non localhost common name
72+
server_cert = ca.issue_cert(u"example.com")
73+
74+
with run_server_in_thread("https", "localhost", tmpdir, ca, server_cert) as cfg:
75+
yield cfg
76+
77+
6778
@pytest.fixture
6879
def ip_san_server(tmp_path_factory):
6980
tmpdir = tmp_path_factory.mktemp("certs")

test/with_dummyserver/test_proxy_poolmanager.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,3 +543,25 @@ def test_basic_ipv6_proxy(self):
543543

544544
r = http.request("GET", "%s/" % self.https_url)
545545
assert r.status == 200
546+
547+
548+
class TestHTTPSProxyVerification:
549+
@onlyPy3
550+
def test_https_proxy_hostname_verification(self, no_localhost_san_server):
551+
bad_server = no_localhost_san_server
552+
bad_proxy_url = "https://%s:%s" % (bad_server.host, bad_server.port)
553+
554+
# An exception will be raised before we contact the destination domain.
555+
test_url = "testing.com"
556+
with proxy_from_url(bad_proxy_url, ca_certs=bad_server.ca_certs) as https:
557+
with pytest.raises(MaxRetryError) as e:
558+
https.request("GET", "http://%s/" % test_url)
559+
assert isinstance(e.value.reason, SSLError)
560+
assert "hostname 'localhost' doesn't match" in str(e.value.reason)
561+
562+
with pytest.raises(MaxRetryError) as e:
563+
https.request("GET", "https://%s/" % test_url)
564+
assert isinstance(e.value.reason, SSLError)
565+
assert "hostname 'localhost' doesn't match" in str(
566+
e.value.reason
567+
) or "Hostname mismatch" in str(e.value.reason)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy