Bug 2460927 (CVE-2026-8643) - CVE-2026-8643 python-pip: Path traversal via malicious entry point name in pip wheel installation allows arbitrary file overwrite
Summary: CVE-2026-8643 python-pip: Path traversal via malicious entry point name in pi...
Keywords:
Status: NEW
Alias: CVE-2026-8643
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
high
high
Target Milestone: ---
Assignee: Product Security DevOps Team
QA Contact:
URL:
Whiteboard:
Depends On: 2482684 2482685 2482686
Blocks:
TreeView+ depends on / blocked
 
Reported: 2026-04-22 23:09 UTC by OSIDB Bzimport
Modified: 2026-05-28 13:48 UTC (History)
97 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed:
Embargoed:


Attachments (Terms of Use)

Description OSIDB Bzimport 2026-04-22 23:09:58 UTC
AI_ONLY_REPORT
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 `console_scripts` or  
`gui_scripts` names with `../` traversal or absolute-path components in  
`entry_points.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 `get_entrypoints(...) -> get_console_script_specs(...) ->  
ScriptMaker._write_script(...)` 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  
`entry_points.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, exist_ok=True)
absolute_target = os.path.join(tempfile.gettempdir(), 'pip-owned')
maker = PipScriptMaker(None, scripts)
maker.clobber = True
maker.variants = {''}
maker.set_mode = False
for spec in [f'../../outside = os:path.join', f'{absolute_target} =  
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 `entry_points.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 `entry_points.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:
`get_entrypoints(distribution)` reads `console_scripts` and `gui_scripts`  
names from wheel metadata.

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

`PipScriptMaker.make_multiple()` forwards the names to vendored `distlib`.

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


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 `target_dir` 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.target_dir, name)
+            target_dir = os.path.abspath(self.target_dir)
+            outname_abs = os.path.abspath(outname)
+            if os.path.commonpath([target_dir, outname_abs]) != target_dir:
+                raise ValueError("Invalid script name %r: path  
traversal/absolute path" % name)
if use_launcher:  # 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


Note You need to log in before you can comment on or make changes to this bug.