gh-158182: http.client: don't assert on non-IPv6-zone percent-encoding in putrequest's netloc - #158184
Open
not-ekalabya wants to merge 1 commit into
Open
gh-158182: http.client: don't assert on non-IPv6-zone percent-encoding in putrequest's netloc#158184not-ekalabya wants to merge 1 commit into
not-ekalabya wants to merge 1 commit into
Conversation
…ent-encoded netloc _strip_ipv6_iface() is meant to strip an IPv6 zone id from a bracketed literal like [fe80::1%eth0], but putrequest() passes it the entire netloc of an absolute-URL request (the normal shape for HTTP-proxy requests). Any RFC 3986-legal percent-encoding earlier in the netloc than a zone id -- most plausibly percent-encoded userinfo, required whenever a username or password contains '@', ':', '/', or '%' -- made the function assert that the part before the first '%' starts with '[', raising a raw AssertionError instead of sending the request. Only treat the input as a bracketed IPv6 literal (and strip the zone id) when it actually starts with '['; otherwise return it unchanged. This also fixes the case the assertion was meant to guard when both userinfo and a zone id are present, since the previous code partitioned on the userinfo's '%' first.
1137MOM
reviewed
Sep 25, 2026
| @@ -0,0 +1,3 @@ | |||
| Fix :exc:`AssertionError` in :meth:`http.client.HTTPConnection.putrequest` | |||
| when an absolute-URL request's netloc contains RFC 3986 percent-encoding | |||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixes #158182.
_strip_ipv6_iface()is meant to strip an IPv6 zone id from a bracketedliteral like
[fe80::1%eth0], butHTTPConnection.putrequest()passes itthe entire netloc of an absolute-URL request -- the normal shape for
HTTP-proxy requests, which is exactly what
urllib.requestuses whengoing through a proxy. Any RFC 3986-legal percent-encoding earlier in the
netloc than an IPv6 zone id -- most plausibly percent-encoded userinfo,
which is required whenever a username or password contains
@,:,/, or%-- made the function'sassert enc_name.startswith(b'[')fail,raising a raw
AssertionErrorinstead of sending the request.The fix only treats the input as a bracketed IPv6 literal (and strips the
zone id) when it actually starts with
[; otherwise it's returnedunchanged. This also fixes the case the original assertion was meant to
guard against when both userinfo and a zone id are present (e.g.
user%41@[fe80::1%eth0]/), since the previous code partitioned on theuserinfo's
%first and never reached the real zone id.I kept this fix scoped to the crash. There's a separate, arguably more
correct improvement -- stripping userinfo from the netloc entirely before
generating the
Hostheader, since RFC 7230 forbids userinfo inHostregardless -- which I left out to keep this PR minimal; happy to add it if
you'd rather have both in one PR.
Found via
Found via an automated code-review pass using GLM-5.3-flash paired with
scopegrep, a semantic code-retrieval tool; independently re-verified and
fixed by hand.
Testing
Same environment limitation as gh-158181/#158183: this environment's
installed Python is 3.12, and main's stdlib can't be imported/parsed by it
directly, so I could not run
Lib/test/test_httplib.py. I verified with astandalone harness loading
Lib/http/client.pyviaimportlib:AssertionError(percent-encodeduserinfo, percent-encoded hostname) now return the netloc unchanged.
test_ipv6host_headertest's four assertions(
[2001::]:81,[2001:102A::],[fe80::%2]->[fe80::],[fe80::%2]:81->[fe80::]:81) were manually re-run against the fixedmodule and still pass exactly as before -- no regression to the actual
IPv6-zone-stripping behavior this function exists for.
Please run the real test suite as part of review, since I could not do so
myself here.
Drafted with Claude Sonnet 5 (Anthropic); reviewed by @not-ekalabya before merge.