Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions SPECS/python-wheel/CVE-2026-24049.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
From 5d21b0f9ba9d397f45bb9003635be81df846f894 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20Gr=C3=B6nholm?= <alex.gronholm@nextday.fi>
Date: Thu, 22 Jan 2026 01:41:14 +0200
Subject: [PATCH] Fixed security issue around wheel unpack (#675)

A maliciously crafted wheel could cause the permissions of a file outside the unpack tree to be altered.

Fixes CVE-2026-24049.

Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
Upstream-reference: https://github.com/pypa/wheel/commit/7a7d2de96b22a9adf9208afcc9547e1001569fef.patch
---
src/wheel/cli/unpack.py | 4 ++--
tests/cli/test_unpack.py | 23 +++++++++++++++++++++++
2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/src/wheel/cli/unpack.py b/src/wheel/cli/unpack.py
index d48840e..83dc742 100644
--- a/src/wheel/cli/unpack.py
+++ b/src/wheel/cli/unpack.py
@@ -19,12 +19,12 @@ def unpack(path: str, dest: str = ".") -> None:
destination = Path(dest) / namever
print(f"Unpacking to: {destination}...", end="", flush=True)
for zinfo in wf.filelist:
- wf.extract(zinfo, destination)
+ target_path = Path(wf.extract(zinfo, destination))

# Set permissions to the same values as they were set in the archive
# We have to do this manually due to
# https://github.com/python/cpython/issues/59999
permissions = zinfo.external_attr >> 16 & 0o777
- destination.joinpath(zinfo.filename).chmod(permissions)
+ target_path.chmod(permissions)

print("OK")
diff --git a/tests/cli/test_unpack.py b/tests/cli/test_unpack.py
index ae584af..75fe193 100644
--- a/tests/cli/test_unpack.py
+++ b/tests/cli/test_unpack.py
@@ -34,3 +34,26 @@ def test_unpack_executable_bit(tmp_path):
unpack(str(wheel_path), str(tmp_path))
assert not script_path.is_dir()
assert stat.S_IMODE(script_path.stat().st_mode) == 0o755
+
+
+@pytest.mark.skipif(
+ platform.system() == "Windows", reason="Windows does not support chmod()"
+)
+def test_chmod_outside_unpack_tree(tmp_path_factory: TempPathFactory) -> None:
+ wheel_path = tmp_path_factory.mktemp("build") / "test-1.0-py3-none-any.whl"
+ with WheelFile(wheel_path, "w") as wf:
+ wf.writestr(
+ "test-1.0.dist-info/METADATA",
+ "Metadata-Version: 2.4\nName: test\nVersion: 1.0\n",
+ )
+ wf.writestr("../../system-file", b"malicious data")
+
+ extract_root_path = tmp_path_factory.mktemp("extract")
+ system_file = extract_root_path / "system-file"
+ extract_path = extract_root_path / "subdir"
+ system_file.write_bytes(b"important data")
+ system_file.chmod(0o755)
+ run_command("unpack", "--dest", extract_path, wheel_path)
+
+ assert system_file.read_bytes() == b"important data"
+ assert stat.S_IMODE(system_file.stat().st_mode) == 0o755
--
2.45.4

6 changes: 5 additions & 1 deletion SPECS/python-wheel/python-wheel.spec
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
Summary: Built-package format for Python
Name: python-%{pypi_name}
Version: 0.43.0
Release: 1%{?dist}
Release: 2%{?dist}
License: MIT
Vendor: Microsoft Corporation
Distribution: Azure Linux
URL: https://github.com/pypa/wheel
Source0: %{url}/archive/%{version}/%{pypi_name}-%{version}.tar.gz
Patch0: CVE-2026-24049.patch
%global pypi_name wheel
%global python_wheel_name %{pypi_name}-%{version}-py3-none-any.whl
%global python_wheeldir %{_datadir}/python-wheels
Expand Down Expand Up @@ -115,6 +116,9 @@ pip3 install iniconfig
%endif

%changelog
* Thu Apr 02 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 0.43.0-2
- Patch for CVE-2026-24049

* Fri May 10 2024 Betty Lakes <bettylakes@microsoft.com> - 0.43.0-1
- Updated to 0.43.0

Expand Down
4 changes: 2 additions & 2 deletions toolkit/resources/manifests/package/toolchain_aarch64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ procps-ng-lang-4.0.4-1.azl3.aarch64.rpm
pyproject-rpm-macros-1.12.0-2.azl3.noarch.rpm
pyproject-srpm-macros-1.12.0-2.azl3.noarch.rpm
python-markupsafe-debuginfo-2.1.3-1.azl3.aarch64.rpm
python-wheel-wheel-0.43.0-1.azl3.noarch.rpm
python-wheel-wheel-0.43.0-2.azl3.noarch.rpm
python3-3.12.9-10.azl3.aarch64.rpm
python3-audit-3.1.2-1.azl3.aarch64.rpm
python3-cracklib-2.9.11-1.azl3.aarch64.rpm
Expand All @@ -557,7 +557,7 @@ python3-rpm-generators-14-11.azl3.noarch.rpm
python3-setuptools-69.0.3-5.azl3.noarch.rpm
python3-test-3.12.9-10.azl3.aarch64.rpm
python3-tools-3.12.9-10.azl3.aarch64.rpm
python3-wheel-0.43.0-1.azl3.noarch.rpm
python3-wheel-0.43.0-2.azl3.noarch.rpm
readline-8.2-2.azl3.aarch64.rpm
readline-debuginfo-8.2-2.azl3.aarch64.rpm
readline-devel-8.2-2.azl3.aarch64.rpm
Expand Down
4 changes: 2 additions & 2 deletions toolkit/resources/manifests/package/toolchain_x86_64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ procps-ng-lang-4.0.4-1.azl3.x86_64.rpm
pyproject-rpm-macros-1.12.0-2.azl3.noarch.rpm
pyproject-srpm-macros-1.12.0-2.azl3.noarch.rpm
python-markupsafe-debuginfo-2.1.3-1.azl3.x86_64.rpm
python-wheel-wheel-0.43.0-1.azl3.noarch.rpm
python-wheel-wheel-0.43.0-2.azl3.noarch.rpm
python3-3.12.9-10.azl3.x86_64.rpm
python3-audit-3.1.2-1.azl3.x86_64.rpm
python3-cracklib-2.9.11-1.azl3.x86_64.rpm
Expand All @@ -565,7 +565,7 @@ python3-rpm-generators-14-11.azl3.noarch.rpm
python3-setuptools-69.0.3-5.azl3.noarch.rpm
python3-test-3.12.9-10.azl3.x86_64.rpm
python3-tools-3.12.9-10.azl3.x86_64.rpm
python3-wheel-0.43.0-1.azl3.noarch.rpm
python3-wheel-0.43.0-2.azl3.noarch.rpm
readline-8.2-2.azl3.x86_64.rpm
readline-debuginfo-8.2-2.azl3.x86_64.rpm
readline-devel-8.2-2.azl3.x86_64.rpm
Expand Down
Loading