Repository navigation
pip 26.0.1.post3 (Py3.9): vendored urllib3 1.26.20.post4; requests CVE-2026-25645 - #15
Merged
Merged
Conversation
…E-2026-25645 Review follow-up from ActiveState/cpython#110. pip 26.0.1 vendors urllib3 1.26.20, which is open to CVE-2025-66418, CVE-2025-66471, CVE-2026-21441, CVE-2026-44431, CVE-2026-97687, CVE-2026-97689 and CVE-2025-50181. Replace it with ActiveState's urllib3 1.26.20.post4, which fixes all seven (ports of the upstream 2.x fixes to the 1.26 line). The vendored copy is the fork's src/urllib3 from the 1.26.20.post4 sdist with pip's existing vendoring diff replayed on top (pip._vendor import paths, Brotli disabled, LICENSE.txt); every hunk applied cleanly, and the fork's new Brotli code is all behind "if brotli is not None". urllib3.__version__ stays "1.26.20", so requests' version check is unaffected. Also backport the requests 2.33.0 fix for CVE-2026-25645 (GHSA-gc5v-m9x4-r6x2, psf/requests 66d21cb07b) to the vendored requests 2.32.5: extract_zipped_paths() extracted to a predictable name in the shared temp directory and reused an existing file. pip's vendored requests calls it from HTTPAdapter.cert_verify() for the default CA bundle, which matters when pip runs from a zip. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ezequielp-activestate
approved these changes
Oct 28, 2026
ezequielp-activestate
left a comment
There was a problem hiding this comment.
No blockers.
- Vendored urllib3: I replayed pip's own vendoring diff (upstream urllib3 1.26.20 against the vendored copy on
26.0.1.x) ontosrc/urllib3from the ActiveState urllib3 1.26.20.post4 release sdist. All 8 hunks apply cleanly, and the result is byte-identical tosrc/pip/_vendor/urllib3in this PR.LICENSE.txtis unchanged. The five files that differ from the base are exactly the five post4 changes relative to upstream 1.26.20. - requests CVE-2026-25645: the
extract_zipped_paths()change is identical to upstream psf/requests 66d21cb07b, and upstream hasn't changed that function since. - Through pip on Python 3.9: pip reports 26.0.1.post3, and importing it under
-W errorraises noRequestsDependencyWarning. The vendored urllib3 refuses a 6-linkContent-Encodingchain ('Too many content encodings in the chain: 6 > 5'), and a 64 MiB deflate bomb throughstream(65536)yields pieces of at most 65,536 bytes.pip download six==1.16.0works.
⚪ Two small notes:
- The description overstates the zip case. It says the requests fix matters when pip runs from a zip, but on 3.9 that path isn't reached. Run from a zip, pip's vendored certifi extracts
cacert.pemto a real file itself, soextract_zipped_paths()returns early. ThreeHTTPAdapter.cert_verify()calls created no temp files. The fix is still correct to carry. - Optional companion commit. Upstream's companion commit e331a288f3 (also in 2.33.0) drops that
extract_zipped_paths(DEFAULT_CA_BUNDLE_PATH)call fromHTTPAdapter.cert_verify(adapters.py:300here). Porting it would remove the path entirely, but nothing reaches it today.
Review follow-up (#15). Port upstream's companion commit to the CVE-2026-25645 fix, psf/requests e331a288f3 (pypa#7292, also in 2.33.0): HTTPAdapter.cert_verify() uses DEFAULT_CA_BUNDLE_PATH directly instead of passing it through extract_zipped_paths(), since certifi already extracts its bundle to a real file. The NEWS entry said the fix mattered when pip runs from a zip. On this line it does not: pip's vendored certifi extracts cacert.pem itself, so extract_zipped_paths() returned early and pip never reached the vulnerable path. The entry now says so; the fix is defense in depth. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Author
|
Both notes are addressed in 9dac45c.
|
ezequielp-activestate
approved these changes
Oct 28, 2026
ezequielp-activestate
left a comment
There was a problem hiding this comment.
Re-review of 9dac45c: still approved. Both notes are addressed:
- e331a288f3: the
adapters.pyandutils.pychanges are identical to upstream's.cert_verify()now usesDEFAULT_CA_BUNDLE_PATHdirectly.extract_zipped_paths()is still defined, but nothing in pip calls it any more. - NEWS: the entry now describes the requests fix as defense in depth, which matches what pip actually reaches.
Running pip from a zip of this tree, on Python 3.9 and 3.10, under -W error: pip 26.0.1.post3 imports with vendored urllib3 1.26.20 (the fork) and requests 2.32.5. DEFAULT_CA_BUNDLE_PATH is the real temp file certifi extracts, and pip download six==1.16.0 works.
This was referenced Oct 28, 2026
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.
Security release pip 26.0.1.post3 for the Python 3.9 line, also bundled by 3.10.22.1. It follows up the review of ActiveState/cpython#110: moving 3.10 from pip 26.2.2 to 26.0.1.post2 also moved its vendored urllib3 back to an unpatched 1.26.20.
Changes
Vendored urllib3 1.26.20 → ActiveState urllib3 1.26.20.post4. That release carries 1.26-line ports of these fixes:
Content-Encodingdecoder chainPoolManagerretriesdid not limit redirectssrc/urllib3from the 1.26.20.post4 sdist and replayed pip's existing vendoring diff on top: thepip._vendorimport paths, Brotli disabled, andLICENSE.txt. Every hunk applied cleanly. The fork's new Brotli code is all behindif brotli is not None.urllib3.__version__stays1.26.20, so requests' version check doesn't warn.Vendored requests 2.32.5: CVE-2026-25645 (GHSA-gc5v-m9x4-r6x2)
extract_zipped_paths()extracted to a predictable name in the shared temporary directory and reused any file already there. It now extracts to a newmkstempfile.HTTPAdapter.cert_verify()now uses the default CA bundle path directly instead of passing it throughextract_zipped_paths().cacert.pemto a real file itself, soextract_zipped_paths()returned early even when pip runs from a zip. Both changes are defense in depth.Validation
urllib3's own test suite, in
python:3.9-slimandpython:3.10-slim, comparing the fork's sdist with upstream urllib3 1.26.20 and without Brotli, as in pip:test_recent_date, twotest_tunneling_proxy_request_timeoutcases andtest_ssl_read_timeout.test_proxy_https_target_tls_error[https-True]. That test expects an SSLError for forwarding through an HTTPS proxy, which only happened because of CVE-2026-97687: the target's TLS context was applied to the proxy. Upstream 2.7.0 skips that case as a known bug (urllib3#2577), and 2.8.0, which has the fix, drops it. So it's a stale test in the fork, not a regression. I'll fix that test in ActiveState/urllib3 separately.pip wheel, built with
python -m build, inpython:3.9-slimandpython:3.10-slim:RequestsDependencyWarning, even under-W error.python pip-26.0.1.post3-py3-none-any.whl/pip download six==1.16.0works with the companion change.cacert.pemin the temp directory,extract_zipped_paths()returns a new file with the zip's content, not the planted file, and a different path on every call.pip download six==1.16.0and apip install --dry-run requests==2.32.3resolution against PyPI both work.pip/__init__.py,vendor.txt,requests/utils.pyand five urllib3 files, plusRECORDand the metadata version. The urllib3 files in the wheel are identical to the vendored tree in this PR.After merge: tag
26.0.1.post3and publish the release. Then bundle it in CPython 3.9.25.1 and 3.10.22.1 (ActiveState/cpython#110).