From 38544cc2f27e20c9ff70b8095b9ab879f4be6771 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Thu, 22 Oct 2026 05:25:24 +0000 Subject: [PATCH] gh-161104: Check the http.client tunnel host after IDNA encoding IDNA normalization maps U+00A0 and similar characters to an ASCII space, so check the encoded host that is put into the CONNECT request line. --- Lib/http/client.py | 8 ++++++-- Lib/test/test_httplib.py | 5 +++++ .../2026-10-22-05-23-04.gh-issue-161104.rvNPjJ.rst | 4 ++++ 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-10-22-05-23-04.gh-issue-161104.rvNPjJ.rst diff --git a/Lib/http/client.py b/Lib/http/client.py index fe67d0f7963f78..0d7300e51e41a4 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -1010,11 +1010,15 @@ def _wrap_ipv6(self, ip): return ip def _tunnel(self): - if _contains_disallowed_url_pchar_re.search(self._tunnel_host): + # Check the host as it is sent: the IDNA codec normalizes the name + # first (NFKC), which maps some non-ASCII characters to ASCII ones, + # e.g. U+00A0 (NO-BREAK SPACE) to a space. + tunnel_host = self._tunnel_host.encode("idna") + if _contains_disallowed_url_pchar_re.search(tunnel_host.decode("ascii")): raise ValueError('Tunnel host can\'t contain control characters %r' % (self._tunnel_host,)) connect = b"CONNECT %s:%d %s\r\n" % ( - self._wrap_ipv6(self._tunnel_host.encode("idna")), + self._wrap_ipv6(tunnel_host), self._tunnel_port, self._http_vsn_str.encode("ascii")) headers = [connect] diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 1e5ec0d4e43c27..6979bc8edc7fdc 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -405,6 +405,11 @@ def test_invalid_tunnel_host(self): 'invalid.host\r\n', 'invalid.host\x00', 'invalid host', + # The IDNA codec normalizes these to an ASCII space + 'invalid\xa0host', + 'invalid\u3000host', + # ... and this one to a space and a combining character + 'invalid\xa8host', ) for tunnel_host in cases: with self.subTest(tunnel_host): diff --git a/Misc/NEWS.d/next/Library/2026-10-22-05-23-04.gh-issue-161104.rvNPjJ.rst b/Misc/NEWS.d/next/Library/2026-10-22-05-23-04.gh-issue-161104.rvNPjJ.rst new file mode 100644 index 00000000000000..acae526043a297 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-10-22-05-23-04.gh-issue-161104.rvNPjJ.rst @@ -0,0 +1,4 @@ +Fix :meth:`http.client.HTTPConnection.set_tunnel` accepting a tunnel host +containing a non-ASCII character that IDNA encoding maps to a space, such as +U+00A0 NO-BREAK SPACE. Connecting now raises :exc:`ValueError`, as it already +does for an ASCII space.