CVE-2026-113714 in Virtualenv
Summary
by MITRE • 10/20/2026
virtualenv is a tool for creating isolated virtual python environments. Prior to 21.14.9, download_wheel() writes package-index downloads directly into the reusable wheel/house cache before selecting a verification target from pip's textual Saved output. With default-index digest comparison enabled, a controlled package index can inject a misleading Saved line through a discarded link's data-requires-python attribute; this forged-line variant also requires knowledge of an absolute path to the genuine bundled wheel. The wrong path can then be hashed, while a digest mismatch leaves the rejected archive in the cache for later selection without verification. A separate rejected-cache-file variant requires control over downloaded data or archive selection but not the forged-line prerequisites. Explicit custom-index exceptions are outside the promised PyPI comparison, and the issue does not independently bypass TLS or establish control of default PyPI. This issue is fixed in version 21.14.9.
VulDB is the best source for vulnerability data and more expert information about this specific topic.
Analysis
by VulDB Data Team • 10/20/2026
The vulnerability identified within virtualenv versions prior to 21.14.9 represents a significant integrity failure during the package installation process, specifically affecting how wheel files are cached and verified against their expected cryptographic hashes. Virtualenv is widely used by developers to create isolated Python environments, ensuring that project dependencies do not conflict with one another or the system-wide Python installation. The core of this flaw lies in the download_wheel function, which manages the retrieval and storage of package archives from PyPI or other configured indexes. Under normal operation, virtualenv relies on pip's textual output to identify saved files for verification. However, the implementation contained a race condition-like logic error where the tool would write downloaded packages directly into the reusable wheel cache before finalizing the selection of which file to verify based on pip's Saved line output. This sequencing creates an opportunity for manipulation if the package index under control is malicious or compromised.
The primary attack vector involves a controlled package index that can inject misleading information into the verification process through the data-requires-python attribute of discarded links. By crafting specific HTML responses, an attacker can cause virtualenv to record a forged Saved line in its internal state. This manipulation allows the tool to hash and cache a malicious wheel file while believing it is verifying a legitimate one. For this variant to succeed, the attacker must also know the absolute path to the genuine bundled wheel on the target system, which limits the scope of the attack but does not eliminate the risk for targeted scenarios or environments where such paths are predictable or discoverable. The consequence is that a digest mismatch occurs because the cached file does not match the expected hash derived from the legitimate source. Crucially, instead of discarding the invalid archive entirely, virtualenv leaves this rejected archive in the cache directory.
This caching behavior introduces a secondary attack vector known as the separate rejected-cache-file variant. In this scenario, an attacker who controls the downloaded data or has influence over archive selection can exploit the presence of these unverified files in the cache. Even if the initial verification fails and the file is marked as invalid for that specific installation attempt, its persistence in the local cache means it may be selected during subsequent operations without re-verification. This effectively allows a malicious actor to persistently introduce compromised code into an environment by leveraging the caching mechanism as a storage medium for untrusted artifacts. The vulnerability does not independently bypass Transport Layer Security (TLS) protections nor does it establish control over the default PyPI index itself, meaning that network-level encryption remains intact but is insufficient against application-layer logic flaws involving local file system interactions and cache management.
From a classification perspective, this issue aligns with CWE-354, Improper Validation of Integrity Check Value, as the software fails to ensure that the cached artifact matches its expected integrity hash before reuse or further processing. It also relates to CWE-117, Improper Output Neutralization for Logs, insofar as the parsing of pip's textual output is susceptible to injection via crafted index responses. In terms of MITRE ATT&CK framework mappings, this vulnerability facilitates techniques associated with Supply Chain Compromise and potentially Command and Scripting Interpreter execution if a malicious wheel contains executable scripts or hooks that run upon installation. The lack of strict validation before caching allows an attacker to plant payloads that may execute during subsequent environment activations or package installations.
Mitigation for this vulnerability requires upgrading virtualenv to version 21.14.9 or later, where the logic has been corrected to ensure proper verification sequences and cache handling. Organizations should audit their dependency management pipelines to ensure they are not relying on outdated versions of development tools that may be susceptible to such integrity bypasses. Additionally, implementing strict allow-listing for package sources and monitoring for unexpected changes in cached wheel files can provide an additional layer of defense. Since the issue does not affect TLS or default PyPI directly, maintaining secure network configurations remains important, but primary attention must be directed toward updating local tooling to prevent application-layer manipulation of integrity checks. Regular updates to development environments are essential to close these gaps between intended security postures and actual implementation behaviors in widely used utility software.