Repository navigation
IPv6 authorities in proxy CONNECT requests are not bracketed #1130
Unanswered
streambinder
asked this question in
Potential Issue
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Bug
In httpcore 1.0.9 (and current
master, 10a6582), both tunnel implementations build the CONNECT target without brackets:httpcore/_async/http_proxy.py(AsyncTunnelHTTPConnection.handle_async_request)httpcore/_sync/http_proxy.py(generated counterpart)For an unbracketed IPv6 remote origin this produces an ambiguous authority on the wire:
Per RFC 9110, Section 9.3.6, the CONNECT target uses the authority form, and per RFC 3986, Section 3.2.2, an IP literal in an authority must be enclosed in brackets. The correct form is:
Proxies that strictly parse the CONNECT authority can reject or misparse HTTPS requests tunnelled to IPv6 destinations.
Prepared fix
I cannot open a pull request or an issue here because both are restricted to collaborators, so the complete fix is included inline as a patch at the end of this post (4 files, based on
master10a6582; it applies cleanly withgit apply).The change is narrow: bracket the host only when formatting the CONNECT authority (when the host contains a colon, i.e. it is an IPv6 literal), and use that authority for both the request target and the
Hostheader. The stored host stays unbracketed for the network connection, TLSserver_hostname, and connection-pool identity. DNS names, IPv4 addresses, proxy headers, and explicit ports are unchanged, and there is no public API change. The sync module and sync tests are regenerated withscripts/unasync.py.Tests
New parametrized regression test
test_proxy_tunneling_connect_authorityintests/_async/test_http_proxy.py(sync version generated), using a recording subclass of the existing mock backend/stream and exercising the real tunnel path. It asserts the exact CONNECT request bytes andHostheader, covers a compressed IPv6 literal on port 443 and on port 8443, an IPv4-mapped IPv6 literal (::ffff:192.0.2.1), unchanged DNS and IPv4 authorities, and that a successful CONNECT proceeds through the mocked TLS upgrade (hostname unbracketed) and the tunneled request.scripts/checkpasses:ruff format --diff,mypy,ruff check,scripts/unasync.py --check.Could a maintainer please apply the patch below (or open a PR from it), or let me know the preferred way to contribute this while PR and issue creation are collaborators-only?
Patch
Fix IPv6 authorities in proxy CONNECT requests (4 files)
All reactions