Skip to content
Merged
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
121 changes: 121 additions & 0 deletions SPECS/python-setuptools/CVE-2026-59890.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
From cd37ab11e615e585ad359bdabf859e4aea68d43a Mon Sep 17 00:00:00 2001
From: "Jason R. Coombs" <jaraco@jaraco.com>
Date: Sat, 27 Jun 2026 10:46:34 -0400
Subject: [PATCH] Normalize Unicode form when matching MANIFEST.in patterns

FileList matched MANIFEST.in patterns against on-disk names byte-for-byte
with no Unicode normalization. On macOS APFS/HFS+, a file stored NFD and a
pattern authored NFC denote the same file but differ byte-for-byte, so an
exclude/global-exclude/recursive-exclude/prune rule could silently fail to
drop a non-ASCII-named file, publishing it in the sdist despite the rule.

Normalize both the pattern and the candidate path to NFC before matching,
via a new unicode_utils.normalize() helper and a _NormalizedMatcher wrapper
around the compiled pattern in translate_pattern.

Fixes GHSA-h35f-9h28-mq5c.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
Upstream-reference: https://github.com/pypa/setuptools/commit/dd9f436a36486b4cb8a4c70a2321548b0be09b8f.patch
---
newsfragments/+ghsa-h35f-9h28-mq5c.bugfix.rst | 7 +++++
setuptools/command/egg_info.py | 28 ++++++++++++++++++-
setuptools/unicode_utils.py | 14 ++++++++++
3 files changed, 48 insertions(+), 1 deletion(-)
create mode 100644 newsfragments/+ghsa-h35f-9h28-mq5c.bugfix.rst

diff --git a/newsfragments/+ghsa-h35f-9h28-mq5c.bugfix.rst b/newsfragments/+ghsa-h35f-9h28-mq5c.bugfix.rst
new file mode 100644
index 0000000..42d6c4c
--- /dev/null
+++ b/newsfragments/+ghsa-h35f-9h28-mq5c.bugfix.rst
@@ -0,0 +1,7 @@
+``MANIFEST.in`` matching (via ``FileList``) is now insensitive to Unicode
+normalization form. A pattern authored in one form (e.g. NFC, as typically
+saved by editors) now matches a file whose name is stored on disk in another
+(e.g. NFD, as produced by macOS APFS/HFS+). Previously an ``exclude``,
+``global-exclude``, ``recursive-exclude``, or ``prune`` rule could silently
+fail to drop a non-ASCII-named file from the source distribution, publishing
+it despite the exclusion -- see GHSA-h35f-9h28-mq5c.
diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py
index 7c7f57a..604a7b3 100644
--- a/setuptools/command/egg_info.py
+++ b/setuptools/command/egg_info.py
@@ -34,6 +34,27 @@ from ..warnings import SetuptoolsDeprecationWarning
PY_MAJOR = '{}.{}'.format(*sys.version_info)


+class _NormalizedMatcher:
+ """
+ Wrap a compiled pattern so that matching is insensitive to Unicode
+ normalization form.
+
+ File names walked from disk (NFD on macOS APFS/HFS+) and patterns from
+ ``MANIFEST.in`` (typically NFC) can denote the same file while differing
+ byte-for-byte. Normalizing both sides before matching keeps an exclusion
+ (or inclusion) from silently failing. See GHSA-h35f-9h28-mq5c.
+ """
+
+ def __init__(self, pattern: re.Pattern) -> None:
+ self._pattern = pattern
+
+ def match(self, path):
+ return self._pattern.match(unicode_utils.normalize(path))
+
+ def search(self, path):
+ return self._pattern.search(unicode_utils.normalize(path))
+
+
def translate_pattern(glob): # noqa: C901 # is too complex (14) # FIXME
"""
Translate a file path glob like '*.txt' in to a regular expression.
@@ -43,6 +64,11 @@ def translate_pattern(glob): # noqa: C901 # is too complex (14) # FIXME
"""
pat = ''

+ # Normalize the pattern so it matches paths regardless of the Unicode
+ # normalization form used on disk (GHSA-h35f-9h28-mq5c). Candidate paths
+ # are normalized to the same form by ``_NormalizedMatcher``.
+ glob = unicode_utils.normalize(glob)
+
# This will split on '/' within [character classes]. This is deliberate.
chunks = glob.split(os.path.sep)

@@ -114,7 +140,7 @@ def translate_pattern(glob): # noqa: C901 # is too complex (14) # FIXME
pat += sep

pat += r'\Z'
- return re.compile(pat, flags=re.MULTILINE | re.DOTALL)
+ return _NormalizedMatcher(re.compile(pat, flags=re.MULTILINE | re.DOTALL))


class InfoCommon:
diff --git a/setuptools/unicode_utils.py b/setuptools/unicode_utils.py
index e84e65e..b50e040 100644
--- a/setuptools/unicode_utils.py
+++ b/setuptools/unicode_utils.py
@@ -15,6 +15,20 @@ def decompose(path):
return path


+def normalize(text):
+ """
+ Return *text* in a canonical Unicode form (NFC) so that names which are
+ visually identical but encoded differently compare equal.
+
+ macOS APFS/HFS+ store file names in decomposed form (NFD), while patterns
+ in ``MANIFEST.in`` are typically authored composed (NFC). The two denote
+ the same file but differ byte-for-byte, so matching them directly lets an
+ exclusion silently fail. Normalizing both the walked path and the pattern
+ to a single form before matching avoids that (GHSA-h35f-9h28-mq5c).
+ """
+ return unicodedata.normalize('NFC', text) if isinstance(text, str) else text
+
+
def filesys_decode(path):
"""
Ensure that the given path is decoded,
--
2.45.4

6 changes: 5 additions & 1 deletion SPECS/python-setuptools/python-setuptools.spec
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Setuptools is a fully-featured, actively-maintained, and stable library designed
Summary: Easily build and distribute Python packages
Name: python-setuptools
Version: 69.0.3
Release: 5%{?dist}
Release: 6%{?dist}
License: MIT
Vendor: Microsoft Corporation
Distribution: Azure Linux
Expand All @@ -15,6 +15,7 @@ URL: https://pypi.python.org/pypi/setuptools
Source0: https://pypi.org/packages/source/s/setuptools/setuptools-%{version}.tar.gz
Patch0: CVE-2024-6345.patch
Patch1: CVE-2025-47273.patch
Patch2: CVE-2026-59890.patch

%description %{_description}

Expand Down Expand Up @@ -59,6 +60,9 @@ EOF
%{python3_sitelib}/setuptools-%{version}.dist-info/*

%changelog
* Sat Jul 11 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 69.0.3-6
- Patch for CVE-2026-59890

* Mon May 26 2025 <mayansingh@microsoft.com> - 69.0.3-5
- Fix CVE-2025-47273 with an upstream patch

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ unzip-6.0-22.azl3.aarch64.rpm
python3-3.12.9-13.azl3.aarch64.rpm
python3-devel-3.12.9-13.azl3.aarch64.rpm
python3-libs-3.12.9-13.azl3.aarch64.rpm
python3-setuptools-69.0.3-5.azl3.noarch.rpm
python3-setuptools-69.0.3-6.azl3.noarch.rpm
python3-pygments-2.7.4-2.azl3.noarch.rpm
which-2.21-8.azl3.aarch64.rpm
libselinux-3.6-4.azl3.aarch64.rpm
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ unzip-6.0-22.azl3.x86_64.rpm
python3-3.12.9-13.azl3.x86_64.rpm
python3-devel-3.12.9-13.azl3.x86_64.rpm
python3-libs-3.12.9-13.azl3.x86_64.rpm
python3-setuptools-69.0.3-5.azl3.noarch.rpm
python3-setuptools-69.0.3-6.azl3.noarch.rpm
python3-pygments-2.7.4-2.azl3.noarch.rpm
which-2.21-8.azl3.x86_64.rpm
libselinux-3.6-4.azl3.x86_64.rpm
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ python3-pip-24.2-9.azl3.noarch.rpm
python3-pygments-2.7.4-2.azl3.noarch.rpm
python3-rpm-4.18.2-1.azl3.aarch64.rpm
python3-rpm-generators-14-11.azl3.noarch.rpm
python3-setuptools-69.0.3-5.azl3.noarch.rpm
python3-setuptools-69.0.3-6.azl3.noarch.rpm
python3-test-3.12.9-13.azl3.aarch64.rpm
python3-tools-3.12.9-13.azl3.aarch64.rpm
python3-wheel-0.43.0-2.azl3.noarch.rpm
Expand Down
2 changes: 1 addition & 1 deletion toolkit/resources/manifests/package/toolchain_x86_64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ python3-pip-24.2-9.azl3.noarch.rpm
python3-pygments-2.7.4-2.azl3.noarch.rpm
python3-rpm-4.18.2-1.azl3.x86_64.rpm
python3-rpm-generators-14-11.azl3.noarch.rpm
python3-setuptools-69.0.3-5.azl3.noarch.rpm
python3-setuptools-69.0.3-6.azl3.noarch.rpm
python3-test-3.12.9-13.azl3.x86_64.rpm
python3-tools-3.12.9-13.azl3.x86_64.rpm
python3-wheel-0.43.0-2.azl3.noarch.rpm
Expand Down
Loading