Where
-Infinity
0
Severity
4.1
EPSS
0.32%
Path Traversal
CVSS:4.0/AV:L/AC:L/AT:P/PR:L/UI:A/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

AIONLYREPORT package: python-pip-26.0.1-2.1.hum1 ------ Summary: Path Traversal via Malicious Entry Point Name in Wheel Metadata: A malicious wheel can use traversal or absolute entry-point names so pip writes generated script wrappers outside the intended scheme.scripts directory and overwrites files writable by the installing user. Requirements to exploit: An attacker must induce a victim to install a malicious wheel. The wheel must contain crafted consolescripts or guiscripts names with ../ traversal or absolute-path components in entrypoints.txt. The resulting overwrite is limited by the permissions of the installing user, but pip’s wheel-install flow reaches the vulnerable write path in normal operation and sets maker.clobber = True, so existing writable files are replaced when reachable. Component affected: github.com/pypa/pip - wheel installation flow in src/pip/internal/operations/install/wheel.py, vendored distlib script generation in src/pip/vendor/distlib/scripts.py, and entry-point parsing in src/pip/vendor/distlib/util.py Version affected: 26.0.1 (confirmed). Likely affects versions containing the same getentrypoints(...) -> getconsolescriptspecs(...) -> ScriptMaker.writescript(...) flow without target-directory enforcement. Patch available: no (a minimal proposed fix is included below; upstream release status unknown) Version fixed (if any already): unknown Upstream coordination: Not yet notified. This report is the initial triage. CVSS: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H AV:N - An attacker can distribute a malicious wheel through a package source or other network-delivered artifact. AC:L - Crafting traversal or absolute entry-point names in entrypoints.txt is straightforward. PR:N - The attacker needs no privileges on the victim system. UI:R - The victim must install the malicious wheel. S:U - Impact remains within the installing user's security scope. C:N - The primitive is attacker-controlled file overwrite, not direct data disclosure by default. I:H - Escaping scheme.scripts can overwrite writable files outside the intended install directory. A:H - Overwriting critical writable files can break applications or system behavior. Impact: Likely Important. This is a real arbitrary file overwrite/path traversal flaw in pip’s wheel installation flow. Exploitation requires a victim to install a malicious wheel, and the overwrite is limited to paths writable by the installing user. The written content is constrained to pip’s generated entry-point wrapper format rather than fully arbitrary bytes, which narrows the direct confidentiality impact, but escaping scheme.scripts can still severely affect integrity and availability and can lead to code execution when privileged or security-sensitive targets are overwritten. Embargo: yes Reason: No official fix is available, and the bug turns a malicious wheel into a write primitive outside the intended installation directory during a normal pip install flow. Public disclosure before a fix would make malicious package distribution campaigns easier, especially where wheels are installed with elevated privileges. Suggested public date: 15-Jul-2026 Acknowledgement: Aisle Research Steps to reproduce: 1. From the unpacked source tree, run: bash python - <<'PY' import os, tempfile, sys sys.path.insert(0, 'src') from pip.internal.operations.install.wheel import PipScriptMaker base = tempfile.mkdtemp(prefix='pip-script-test-') scripts = os.path.join(base, 'bin') os.makedirs(scripts, existok=True) absolutetarget = os.path.join(tempfile.gettempdir(), 'pip-owned') maker = PipScriptMaker(None, scripts) maker.clobber = True maker.variants = {''} maker.setmode = False for spec in [f'../../outside = os:path.join', f'{absolutetarget} = os:path.join']: files = maker.make(spec) print(spec, '->', files[0], '=>', os.path.abspath(files[0])) PY 2. Observe that the generated output path resolves outside scripts and that the file is written. 3. In a real installation context, a malicious wheel that places the same crafted names in entrypoints.txt reaches the same write sink during pip install and can overwrite attacker-chosen files writable by the installing user. Mitigation: Do not install untrusted wheels, especially in privileged contexts.

Avoid sudo pip install or other elevated wheel-install workflows until a fix is available.

Reject or inspect wheels whose entrypoints.txt contains path separators, .., or absolute entry-point names.

Vulnerability Details

pip already enforces path-traversal checks for wheel archive members extracted from the .whl, but generated entry-point wrappers are created later from metadata and do not go through that containment check. The vulnerable flow is: getentrypoints(distribution) reads consolescripts and guiscripts names from wheel metadata.

getconsolescriptspecs() formats those names into script specifications without sanitizing the name component.

PipScriptMaker.makemultiple() forwards the names to vendored distlib.

ScriptMaker.writescript() uses os.path.join(self.targetdir, name) and writes the generated wrapper without verifying that the resolved path stays inside targetdir.

Additional stage-5 verification confirmed that this is not limited to a direct PipScriptMaker API call: the full wheel-metadata path is reachable in both supported metadata backends, and absolute entry-point names are accepted in addition to ../ traversal. Relevant CWEs: CWE-22 (Path Traversal)

CWE-73 (External Control of File Name or Path)

Proposed Fix

A minimal defense-in-depth fix is to enforce that each generated script path remains inside targetdir before writing: diff diff --git a/src/pip/vendor/distlib/scripts.py b/src/pip/vendor/distlib/scripts.py @@ for name in names: outname = os.path.join(self.targetdir, name) + targetdir = os.path.abspath(self.targetdir) + outnameabs = os.path.abspath(outname) + if os.path.commonpath([targetdir, outnameabs]) != targetdir: + raise ValueError("Invalid script name %r: path traversal/absolute path" % name) if uselauncher: # pragma: no cover n, e = os.path.splitext(outname) Optionally, reject path separators and absolute paths earlier when parsing or validating entry-point names. ------ This report was generated using AI technology. Always review AI-generated content prior to use

1 / 3
Source: Red Hat
First published (updated )
Severity
1

A vulnerability was discovered in pip (all versions), because it installs the version with the highest version number, even if the user had intended to obtain a private package from a private index. This only affects use of the --extra-index-url option, and exploitation requires that the package does not already exist in the public index (and thus the attacker can put the package there with an arbitrary version number).

First published (updated )

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203