Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessCompromise index or MITM PyPI TLS
-
DeliveryServe malicious wheel with matching name/version/filename
-
ExploitUser runs virtualenv seed/download on default index
-
ExecutionUnverified wheel cached and seeded
-
ImpactAttacker code runs in created environments
Vulnerability Assessment
| Weakness |
CWE
OWASP Top 10:2025
A08:2025 - Software or Data Integrity Failures
ASVS 5.0
V15 - Secure Coding and Architecture Code integrity verification
|
| Exploitation Conditions | Exploitation requires all of: (1) the attacker occupies the wheel delivery path - a compromised package index, a stale/poisoned mirror, or an intercepted TLS connection to PyPI (AC:H/AT:P); (2) virtualenv fetches seed wheels via a periodic update or the --download option; (3) the environment uses the DEFAULT PyPI path - the digest check (and thus this fix) is intentionally skipped when PIP_INDEX_URL, PIP_EXTRA_INDEX_URL, or PIP_INDEX is set, and a pip.conf custom index is invisible to the check entirely; and (4) a user actually creates/seeds a virtual environment (UI:P). Limiting factors: affected virtualenv versions prior to 21.7.12, the need for an active MITM or index/mirror compromise, and required user action. Note that even after patching, custom-index configurations remain unverified by design. |
| Impact | This is a genuine supply-chain integrity flaw but not a top-tier emergency. The vendor CVSS 4.0 vector (AV:N/AC:H/AT:P/PR:N/UI:P) shows the two features that temper the 7.7 score: AC:H and AT:P mean the attacker must already control the delivery path (compromise the index, poison a mirror, or actively MITM the TLS connection to PyPI), and UI:P means a user must actually create/seed a virtual environment. There is no EPSS score, no CISA KEV listing, and no public exploit identified at time of analysis, so this is a latent risk rather than one under active mass exploitation. The impact if the preconditions are met is severe (VC:H/VI:H/VA:H - attacker-controlled pip/setuptools wheels seeded into every subsequently created environment, i.e. code execution), which justifies treating it as a real priority for organizations that pull seed wheels over untrusted networks or through mirrors. Note the CWE and the vendor 'Information Disclosure' tag conflict: this is CWE-494 (download of code without integrity check) with integrity/availability impact, not an information-disclosure bug. The verification fix also only applies to the default PyPI path and is deliberately skipped for custom indexes, so environments using PIP_INDEX_URL/pip.conf remain unverified by design - a limitation defenders should understand. |
| Exploit ScenarioDerived | An attacker who controls a corporate PyPI mirror, a poisoned package index, or a position to MITM the TLS connection substitutes a malicious pip or setuptools wheel that keeps the requested distribution name, version, and filename. When a developer or CI job runs virtualenv against the default PyPI index (periodic seed update or --download), the unverified wheel is cached and seeded into every new environment, executing attacker code. No public PoC is known, and the attack requires both an active man-in-the-middle/index-compromise position (AC:H/AT:P) and a user creating an environment (UI:P). |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Sep 29, 2026
virtualenv versions prior to 21.7.12 cache and seed pip/setuptools wheels without verifying their bytes, so an attacker who controls the wheel delivery path can substitute a different wheel under the requested distribution, version, and filename and have it injected into every environment virtualenv subsequently creates. The flaw is exploitable unauthenticated but requires an active man-in-the-middle position, a compromised index, or a stale/poisoned mirror, and requires a user to actually create or seed a virtual environment. No public exploit code was identified at time of analysis, and the digest check is intentionally skipped whenever PIP_INDEX_URL, PIP_EXTRA_INDEX_URL, or PIP_INDEX points at a custom index - meaning custom-index users remain unverified even after upgrading.
RemediationAI
Upgrade to virtualenv 21.7.12 or later (vendor-released patch: 21.7.12), which enables SHA-256 verification of downloaded seed wheels against PyPI's published release digests before they are cached or seeded - see the advisory at https://github.com/pypa/virtualenv/security/advisories/GHSA-94p9-xgh2-xp45 and the fix in PR #3251 / commit a01ed3e2f239d6ab1fce62c5c7664ccf268fff6d. Because the check is deliberately bypassed when PIP_INDEX_URL, PIP_EXTRA_INDEX_URL, or PIP_INDEX is set (and is blind to a pip.conf-defined index), operators who rely on a private or internal index get no digest protection even on 21.7.12 and must enforce integrity at the index layer: serve seed wheels only over TLS with certificate validation, mirror PyPI artifacts by hash rather than accepting at re-upload time, and monitor for rebuilt wheels published under upstream filenames - the trade-off is that mirror re-packaging workflows must now maintain their own trusted digest manifest. Environments that can tolerate it should clear the PIP_INDEX* variables before running virtualenv so the default index path (and its verification) is used, at the cost of losing access to internal packages. As a compensating control, disable periodic seed-wheel updates and avoid the --download option where possible, or pre-seed environments from a hash-verified local wheel bundle, accepting the operational overhead of manual wheel curation. Finally, treat environments created with affected versions as potentially contaminated: identify cached wheels in the virtualenv app-data seed cache and re-create affected environments after patching.
Affected VersionsENISA
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 1 package in pypi
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
The root cause is CWE-494 (Download of Code Without Integrity Check): virtualenv's download_wheel() in src/virtualenv/seed/wheels/acquire.py shelled out to pip download, which trusts whatever index it is configured to use, and then cached and seeded the returned artifact with no validation of its contents. This contrasts with virtualenv's own embedded seed wheels, which are already covered by an internal BUNDLE_SHA256 verification. The upstream fix (PR #3251, commit a01ed3e2f239d6ab1fce62c5c7664ccf268fff6d) adds verify_wheel_digest() in periodic_update.py, which queries PyPI's JSON API release metadata, finds the entry whose filename matches the downloaded wheel, computes the file's SHA-256 locally, and raises RuntimeError on mismatch - a fatal error that guarantees the wheel is never cached or seeded. A missing PyPI release record or absent sha256 field only logs a debug message and lets the wheel through, since the artifact may legitimately come from a private index PyPI has never seen. The fix also gates the check behind _uses_default_index(), which returns False when any of PIP_INDEX_URL, PIP_EXTRA_INDEX_URL, or PIP_INDEX is set in the environment; the code comments explicitly acknowledge that a pip.conf-defined custom index has the same effect but is invisible to this check, so the authors describe the guard as a conservative false-rejection-avoidance signal rather than proof that verification ran when it safely could have.
Know when Virtualenv gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
AC:H because the attacker must control the index/mirror or MITM the download; UI:R since a user must create/seed an environment; C/I/A:H as attacker wheels execute code in created environments.
Primary rating from Vendor (GitHub_M).
CVSS VectorVendor: GitHub_M
Lifecycle Timeline
2DescriptionCVE.org
virtualenv is a tool for creating isolated virtual python environments. Prior to 21.7.12, download_wheel() accepts pip and setuptools seed wheels fetched for periodic updates or the --download option without checking their bytes against an authoritative digest equivalent to the embedded wheels' BUNDLE_SHA256 verification. A compromised index, stale mirror, or intercepted TLS connection can substitute a different wheel under the requested distribution, version, and filename, after which virtualenv caches and seeds the attacker-controlled wheel into subsequently created environments. The verification applies to the default PyPI path and is intentionally skipped when PIP_INDEX_URL, PIP_EXTRA_INDEX_URL, or PIP_INDEX configures a custom index that may legitimately publish rebuilt wheels. This issue is fixed in version 21.7.12.
Technical POC Analysis
The flaw is CWE-494 (Download of Code Without Integrity Check) in virtualenv's downloadwheel().
Full technical POC analysis - root cause, step-by-step exploitation and patch breakdown - is part of the Pro and Business plans.
Latest POC
1 public PoC link from github
Sign in to open the public PoC links collected for this CVE.
Executive ViewAI
virtualenv versions prior to 21.7.12 can inject attacker-supplied pip/setuptools wheels into every subsequently created Python environment when an adversary controls the wheel delivery path, creating a supply-chain risk across development, build, and CI/CD pipelines. No public exploit identified at time of analysis, and no vendor-released patch identified at time of analysis. Leadership should prioritize this due to the broad blast radius and the potential for malicious code execution in many downstream environments.
No vendor-released patch identified at time of analysis. Interim mitigations: avoid custom package indexes (PIP_INDEX_URL, PIP_EXTRA_INDEX_URL, PIP_INDEX) because digest checks are intentionally skipped for them; use virtualenv --no-seed where possible to prevent seeding of pip/setuptools wheels; restrict and monitor network paths to package indexes and wheel caches to prevent man-in-the-middle or poisoned-mirror substitution; enforce TLS certificate validation and DNS security; use an internal, immutable mirror with manual SHA256 verification of all pip/setuptools wheels before caching or seeding; and monitor for unexpected wheel changes or suspicious index configurations in CI/CD pipelines.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
More in Virtualenv
View allvirtualenv before 20.26.6 allows command injection through the activation scripts for a virtual environment. Rated high
Configuration injection in PyPA virtualenv before 21.7.11 lets a line boundary embedded in a prompt value inject extra k
Command injection in the bash, zsh, and fish activation scripts generated by virtualenv releases prior to 21.7.13 lets a
Command injection in PyPA virtualenv before 21.7.12 allows an attacker who controls the environment's prompt value - via
Virtualenv versions up to 20.36.1 is affected by improper link resolution before file access (CVSS 4.5).
EUVD-2026-89462
GHSA-94p9-xgh2-xp45
NVD
CVE.org
EPSS
Vulnrichment
Exploit-DB