Skip to content

[High] Patch python-urllib3 for CVE-2025-66471#16158

Open
akhila-guruju wants to merge 5 commits intomicrosoft:fasttrack/2.0from
akhila-guruju:topic_new-urllib3-2.0
Open

[High] Patch python-urllib3 for CVE-2025-66471#16158
akhila-guruju wants to merge 5 commits intomicrosoft:fasttrack/2.0from
akhila-guruju:topic_new-urllib3-2.0

Conversation

@akhila-guruju
Copy link
Contributor

@akhila-guruju akhila-guruju commented Mar 11, 2026

Merge Checklist

All boxes should be checked before merging the PR (just tick any boxes which don't apply to this PR)

  • The toolchain has been rebuilt successfully (or no changes were made to it)
  • The toolchain/worker package manifests are up-to-date
  • Any updated packages successfully build (or no packages were changed)
  • Packages depending on static components modified in this PR (Golang, *-static subpackages, etc.) have had their Release tag incremented.
  • Package tests (%check section) have been verified with RUN_CHECK=y for existing SPEC files, or added to new SPEC files
  • All package sources are available
  • cgmanifest files are up-to-date and sorted (./cgmanifest.json, ./toolkit/scripts/toolchain/cgmanifest.json, .github/workflows/cgmanifest.json)
  • LICENSE-MAP files are up-to-date (./LICENSES-AND-NOTICES/SPECS/data/licenses.json, ./LICENSES-AND-NOTICES/SPECS/LICENSES-MAP.md, ./LICENSES-AND-NOTICES/SPECS/LICENSE-EXCEPTIONS.PHOTON)
  • All source files have up-to-date hashes in the *.signatures.json files
  • sudo make go-tidy-all and sudo make go-test-coverage pass
  • Documentation has been updated to match any changes to the build system
  • Ready to merge

Summary

Patch python-urllib3 for CVE-2025-66471
Patch Backported: Yes

In noxfile.py
some syntax changes were made because python version in 2.0 is 3.9.x.

In response.py
new class class BytesQueueBuffer has been added in response.py file and related tests were also added in test_response.py.
read() API was backported as per the upstream reference, new API call _raw_read was backported as it was used in backported read() API.
read1() API is not present in this codebase. So, changes made for read1() API in upstream patch are not present in backport patch.

In test_response.py
testcases for zstd are not backported/patched, because this encoding method is not used in v1.26.19 codebase and no testcases were present in test file.

Upstream Patch: https://github.com/urllib3/urllib3/commit/c19571de34c47de3a766541b041637ba5f716ed7.patch
Reference has been taken from Redhat patch: r10s/python-urllib3-1.26.19-3.el10/SOURCES/CVE-2025-66471.patch

redhat patch is taken as reference, there are some files which azl doesn't need, like these are particularly for redhat. So, did not include those files (like changelog/2128.removal.rst)
the test file test/with_dummyserver/test_socketlevel.py is not added because, the test folder is being removed in the %prep section of spec.

Change Log
  • new file: SPECS/python-urllib3/CVE-2025-66471.patch
  • modified: SPECS/python-urllib3/python-urllib3.spec
Does this affect the toolchain?

NO

Associated issues
  • #xxxx
Links to CVEs
Test Methodology

@microsoft-github-policy-service microsoft-github-policy-service bot added Packaging fasttrack/2.0 PRs Destined for Azure Linux 2.0 labels Mar 11, 2026
@Kanishk-Bansal
Copy link
Contributor

Full Build

@Kanishk-Bansal
Copy link
Contributor

re hitting full build

@akhila-guruju akhila-guruju marked this pull request as ready for review March 12, 2026 09:34
@akhila-guruju akhila-guruju requested a review from a team as a code owner March 12, 2026 09:34
@azurelinux-security
Copy link
Contributor

CVE Patch Review: PR #16158 — Patch python-urllib3 for CVE-2025-66471

PR: #16158
Author: akhila-guruju
Target Branch: fasttrack/2.0
Package: python-urllib3 1.26.19
Build (Buddy): https://dev.azure.com/mariner-org/mariner/_build/results?buildId=1067142&view=results
Full Build: https://dev.azure.com/mariner-org/mariner/_build/results?buildId=1067260&view=results


CVE Summary

CVE Severity CVSS Type Description
CVE-2025-66471 HIGH 8.9 (CVSS v4) CWE-409: Improper Handling of Highly Compressed Data (Data Amplification) urllib3's streaming API improperly handles highly compressed data — decompression logic could fully decode a small amount of highly compressed data in a single operation, causing excessive CPU and memory consumption (decompression bomb)
  • Affected versions: >= 1.0, < 2.6.0
  • Fixed upstream in: urllib3 2.6.0
  • Azure Linux package version: 1.26.19 (backport required)

Spec File Review

  • Patch entry: Patch3: CVE-2025-66471.patch — sequential numbering correct (follows Patch2: CVE-2026-21441.patch)
  • Patch application: Uses %autosetup -p1 — patches applied automatically
  • Release bumped: 3 → 4 — correctly incremented
  • Changelog updated: New entry at top, dated Wed Mar 11 2026, references CVE-2025-66471
  • Changelog date: March 11, 2026 is a Wednesday — correct
  • Version-release: 1.26.19-4 — correct

Patch Verification

Patch Origin & Structure

  • Upstream commit: urllib3/urllib3@c19571d
  • Reference backport: Rocky Linux / RHEL 10 patch for python-urllib3-1.26.19-3.el10

The PR patch is a consolidated backport based on the Rocky Linux reference patch, which itself is a 5-commit series cherry-picked and adapted for v1.26.19:

# Commit Purpose
1 (noxfile.py adaptation) Add Python 3.12 to nox config
2 c35033f6 Standardize HTTPResponse.read(X) behavior — foundation for the fix
3 4714836a Continue reading response stream if buffered decompressed data exists
4 02ae65a4 Fix HTTPResponse.read(0) when underlying buffer is empty
5 c19571de Security fix for CVE-2025-66471max_length parameter for decompressors

Files Modified in Patch

File Changes Purpose
docs/advanced-usage.rst Documentation wording "large responses" → "responses of large or unknown length"
docs/user-guide.rst Documentation wording Same wording change
noxfile.py extra_dependencies parameter + test_brotlipy session Testing infrastructure for brotli fallback
src/urllib3/response.py Core fix — 365 lines modified All decoder + response read logic changes
test/test_response.py 341 lines of tests added/modified Comprehensive test coverage for the fix

Core Security Fix Analysis (response.py)

The security fix addresses the decompression bomb vulnerability by adding max_length support throughout the decompression pipeline:

  1. DeflateDecoder.decompress(data, max_length=-1) — Added max_length parameter, _unfed_data buffer for unconsumed input, and has_unconsumed_tail property. Correctly handles RFC 1950 (ZLIB) / RFC 1951 (DEFLATE) fallback.

  2. GzipDecoder.decompress(data, max_length=-1) — Added max_length parameter, _unconsumed_tail tracking, bounds checking on decompressed output (max(max_length - len(ret), 0)), and has_unconsumed_tail property.

  3. BrotliDecoder.decompress(data, max_length=-1) — Added output_buffer_limit support for Brotli >= 1.2.0, graceful fallback with DependencyWarning for older versions, and has_unconsumed_tail via can_accept_more_data().

  4. MultiDecoder.decompress(data, max_length=-1) — Added iterative decompression loop respecting max_length across chained decoders.

  5. BytesQueueBuffer class — New memory-efficient bytes buffer using collections.deque to hold decoded chunks without doubling memory usage. Supports put(), get(n), and __len__().

  6. HTTPResponse._raw_read(amt) — Extracted raw socket reading logic from read() for reuse and clarity.

  7. HTTPResponse.read(amt) — Refactored to use _decoded_buffer and _raw_read(). Passes max_length to _decode() to prevent decompressing beyond the requested amount. Includes unconsumed tail checks for progressive decompression.

  8. HTTPResponse.stream() — Extended loop condition to also check _decoded_buffer and has_unconsumed_tail.

  9. HTTPResponse.read_chunked() — Passes max_length=amt to _decode().

Backport Adaptation Notes

The PR description correctly documents the following backport decisions:

  • read1() API excluded — Not present in v1.26.19 codebase; upstream changes to read1() are correctly omitted
  • zstd tests excluded — zstd encoding is not used in v1.26.19; related test parameters and test functions are correctly omitted (set _zstd_available = False)
  • Python syntax adapted — noxfile.py uses Python 3.9-compatible syntax (e.g., def tests_impl(session, extras="socks,secure,brotli", extra_dependencies=None)) instead of Python 3.10+ list[str] | None type hints
  • test_socketlevel.py changes excluded — The dummyserver integration tests are not included in the PR patch, which is appropriate since these are end-to-end tests that may have different test infrastructure in v1.26.19

Patch Comparison with Rocky Linux Reference

Compared the PR patch against the Rocky Linux RHEL 10 backport:

  • Core logic: Identical in all security-critical areas — decoder max_length support, BytesQueueBuffer, _raw_read(), refactored read(), stream() condition update
  • test_socketlevel.py changes: Not present in PR patch — the Rocky Linux patch includes these, but they are optional integration tests. This is acceptable.
  • noxfile.py differences: Minor syntax adaptation for Python 3.9 compatibility (the Rocky Linux patch targets the same v1.26.19 base)

Verdict: The upstream patch has been correctly backported. All security-critical changes are preserved. Excluded read1(), zstd, and socket-level integration tests are documented and justified.


Build Status

Check Status
PR CI checks ✅ 13/13 passed
Buddy build (1067142) ✅ Linked in PR
Full build (1067260) ✅ Linked in PR conversation

Note: Azure DevOps build logs require authentication and could not be directly inspected. Build status is confirmed from PR conversation and GitHub checks.


Test Coverage

The patch includes comprehensive test coverage:

  • TestBytesQueueBuffer — Unit tests for the new buffer class (single chunk, read too much, multiple chunks, memory usage)
  • test_cache_content / test_cache_content_preload_false — Updated to use bytes, added preload_content=False variant
  • test_read_with_all_data_already_in_decompressor — Parametrized across deflate/gzip/brotli; verifies progressive decompression when all data is already buffered
  • test_decode_with_max_length_close_to_compressed_data_size — Parametrized boundary test with delta=0 and delta=-1
  • test_memory_usage_decode_with_max_length — Memory limit test (10 MB) across read/read_chunked/stream methods against 50 MB compressed payloads — validates the fix prevents decompression bombs
  • test_read_multi_decoding_deflate_deflate — Tests chained multi-decoder with progressive reads
  • test_buffer_memory_usage_decode_one_chunk — Validates memory bounds for single-chunk decode (25 MB limit)
  • test_buffer_memory_usage_no_decoding — Validates memory bounds without decoding (10.5 MB limit)
  • Updated streaming tests to match new behavior (e.g., b"fo" + b"o" instead of b"f" + b"oo")
  • Updated tell() position tests with hardcoded expected values

PR Description Checklist

  • Summary provided with clear explanation of backport decisions
  • CVE link (NVD + GHSA)
  • Upstream patch URL referenced
  • Rocky Linux reference patch URL referenced
  • Buddy build URL provided
  • Full build URLs provided (2 full builds)
  • Merge checklist present
  • read1() exclusion documented
  • zstd test exclusion documented

Minor Observations

  1. Associated issues: PR lists #xxxx as placeholder — should be updated with actual tracking issue if one exists.
  2. noxfile.py changes: The test_brotlipy session addition modifies the test infrastructure. This is part of the upstream security fix to ensure brotlipy fallback works correctly — no concern.
  3. Memory limit tests (@pytest.mark.limit_memory): These tests require pytest-memray which may not be available in all build environments. They should gracefully skip if the marker is not recognized.

APPROVED — Patch correctly backported from upstream with proper exclusions documented. All security-critical decompression bomb mitigations are present. CI checks pass. LGTM.

Copy link
Contributor

@Kanishk-Bansal Kanishk-Bansal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes LGTM

@Kanishk-Bansal Kanishk-Bansal added the CVEFixReadyForMaintainerReview When a CVE fix has been reviewed by release manager and is ready for stable maintainer review label Mar 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CVEFixReadyForMaintainerReview When a CVE fix has been reviewed by release manager and is ready for stable maintainer review fasttrack/2.0 PRs Destined for Azure Linux 2.0 Packaging security

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants