Skip to content

setuptools 68.0.0.3 (Py3.7): CVE-2026-59890, GHSA-xmj3-9gf7-h52w - #7

Merged
icanhasmath merged 3 commits into
68.0.0.xfrom
68.0.0.3-security
Oct 29, 2026
Merged

icanhasmath merged 3 commits into
68.0.0.xfrom
68.0.0.3-security

Conversation

@icanhasmath

Copy link
Copy Markdown
Collaborator

Security release setuptools 68.0.0.3 for the Python 3.7 line (68.0.0 is the last setuptools that supports 3.7). It fixes the two advisories still open in 68.0.0.2, so CPython 3.7.17.8 (ActiveState/cpython#117) can bundle a setuptools with no known open advisories.

Advisory CVE Severity Upstream fix Status
GHSA-h35f-9h28-mq5c CVE-2026-59890 medium 83.0.0 Patched
GHSA-xmj3-9gf7-h52w — low 84.1.0 Patched

Already fixed on this line: CVE-2024-6345 (68.0.0.1) and CVE-2025-47273 (68.0.0.2). CVE-2022-40897 was fixed upstream in 65.5.1, before 68.0.0.

Changes

CVE-2026-59890: MANIFEST.in exclusions bypassed through Unicode normalization.

  • 68.0.0's translate_pattern() matched patterns against file names byte for byte.
  • A file stored with a decomposed (NFD) name, as on macOS APFS/HFS+, survived an exclude rule written in composed (NFC) form, so it could end up in the sdist.
  • Both the pattern and the path are now normalized to NFC before matching.
  • Taken from the ActiveState 82.0.1.post1 fix (bb32ccb, upstream dd9f436). Only the test module's imports conflicted.

GHSA-xmj3-9gf7-h52w: path escape through namespace_packages.txt.

  • Wheel._fix_namespace_packages() joined each entry onto the destination egg directory as a path.
  • An absolute, drive-qualified or UNC entry made it create an __init__.py outside that directory.
  • Entries must now be dotted module names that resolve inside the egg directory, via upstream's _resolve_namespace_dir() (6d07b8d, released in 84.1.0).
  • Only the deprecated setup_requires path reaches this code.

Release commit: version 68.0.0.3 in setup.cfg and .bumpversion.cfg, plus a CHANGES.rst entry, the same files 68.0.0.2 changed. Both fixes are Python 3.7 compatible.

Validation (python:3.7-slim)

Tests: test_manifest, test_wheel, test_egg_info, test_sdist, plus the doctests in setuptools/wheel.py.

  • This branch: 196 passed, 1 xfailed, 1 failed.
  • The failure: test_wheel_install[extension], which needs a C compiler that the slim image doesn't have. It fails the same way on 68.0.0.2.
  • New tests on the 68.0.0.2 code: all nine fail there (2 for CVE-2026-59890, 7 for GHSA-xmj3), and all pass on this branch.

Wheel: built with setup.py bdist_wheel, the same way as the 68.0.0.2 wheel CPython 3.7.17.8 currently bundles.

  • Diff from 68.0.0.2: only setuptools/command/egg_info.py, setuptools/unicode_utils.py and setuptools/wheel.py change, plus METADATA and RECORD. The file list is identical.

After merge: tag v68.0.0.3, publish the release with the wheel attached, then bundle it in CPython 3.7.17.8.

jaraco and others added 3 commits October 29, 2026 11:54
…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>
(cherry picked from commit dd9f436)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

68.0.0.x: backported from the ActiveState 82.0.1.x fix (bb32ccb); only
the test module's imports conflicted. The fix uses no Python 3.8+
features (re.Pattern exists from 3.7), so 68.0.0.x keeps Python 3.7.
The towncrier fragment is dropped; CHANGES.rst gets the entry in the
release commit.
(cherry picked from commit bb32ccb)
Entries in a wheel's namespace_packages.txt were split on '.' and passed
straight to os.path.join, which interprets its arguments as paths. An entry
that is absolute, drive-qualified, or UNC therefore discarded the
destination egg directory entirely and placed a fixed-content __init__.py
at a path chosen by the wheel.

The report framed this as Windows-only, but only the drive-letter form is;
an absolute POSIX path escapes just as readily. Namespace entries are now
validated as dotted module names on every platform, with a containment
check as defense in depth.

This sink is reachable only through the deprecated setup_requires
mechanism when setup() is invoked outside a PEP 517 frontend. The
setuptools build backend disables setup_requires installation in every
hook, so it does not reach it.

Ref GHSA-xmj3-9gf7-h52w.

(cherry picked from commit 6d07b8d)

68.0.0.x: hand-applied. 68.0.0 reads namespace_packages.txt in
Wheel._fix_namespace_packages() with the same
os.path.join(destination_eggdir, *mod.split('.')) sink; that line now
calls _resolve_namespace_dir(). The helper and tests are taken
unchanged (str.isidentifier() and f-strings are fine on Python 3.7).
The towncrier fragment is dropped; CHANGES.rst gets the entry in the
release commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Security release of the setuptools 68.0.0 line (the last setuptools that
supports Python 3.7): CVE-2026-59890 (GHSA-h35f-9h28-mq5c) and
GHSA-xmj3-9gf7-h52w.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@ezequielp-activestate ezequielp-activestate left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Approving. Both fixes are exact ports, and with them every setuptools advisory affecting 68.0.0 is now fixed on this line.

Provenance

  • CVE-2026-59890 (d5a5c75): the egg_info.py and unicode_utils.py hunks are identical to the fork's 82.0.1 fix (bb32ccb, upstream dd9f436). On 68.0.0 every translate_pattern() caller uses only .match, which _NormalizedMatcher provides. egg_info.py already imports unicode_utils, and unicode_utils.py already imports unicodedata.
  • GHSA-xmj3-9gf7-h52w (ea21ac2): the wheel.py diff matches upstream 6d07b8d line for line.
  • Follow-ups: I walked upstream main after both fixes. Neither has a follow-up in egg_info.py, unicode_utils.py or wheel.py; the only later change there is a Ruff lint pass.
  • Advisory coverage: GitHub's advisory database lists six setuptools advisories. The other four were fixed in 65.5.1 (in 68.0.0 already), 68.0.0.1, 68.0.0.2, and 0.7.

Tests (python:3.7, full image)

  • Suite: test_manifest, test_wheel, test_egg_info, test_sdist plus the setuptools/wheel.py doctests: base 186 passed, 1 xfailed; this branch 197 passed, 1 xfailed. The full image has a compiler, so test_wheel_install[extension] passes too.
  • New tests on the base code: both Unicode tests and the end-to-end test_install_as_egg_rejects_namespace_escape fail on 68.0.0.x. I dropped the _resolve_namespace_dir import so the module would load, which means the helper's unit tests can't run there.

Release commit: the same three files as 68.0.0.2 (setup.cfg, .bumpversion.cfg, CHANGES.rst).

@icanhasmath
icanhasmath merged commit 44540bb into 68.0.0.x Oct 29, 2026
4 of 39 checks passed
@icanhasmath icanhasmath mentioned this pull request Oct 29, 2026
icanhasmath added a commit that referenced this pull request Oct 29, 2026
Release the 68.0.0.3 security fixes (#7) as 68.0.0.post3, following the
X.Y.Z.postN scheme the ActiveState forks now use for security releases.
Only the version strings change.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
icanhasmath added a commit to ActiveState/cpython that referenced this pull request Oct 29, 2026
setuptools 68.0.0.2 still had CVE-2026-59890 (GHSA-h35f-9h28-mq5c,
MANIFEST.in exclusion bypass in sdist) and GHSA-xmj3-9gf7-h52w (path
escape via namespace_packages.txt during legacy wheel installation).
ActiveState setuptools 68.0.0.post3 (ActiveState/setuptools#7, #8) fixes
both. The wheel is the release asset, sha256
95bb21258fbcb75b5d7d3740ce296991641e8c78a0de9590747ba2d11aa81c43.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants