Skip to main content

virtualenv EUVDEUVD-2026-105298

| CVE-2026-113717 LOW
Download of Code Without Integrity Check (CWE-494)
2026-10-20 GitHub_M GHSA-cx28-75q4-x26q
2.3
CVSS 4.0 · Vendor: GitHub_M
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Serve matching candidate from non-PyPI index
  2. Delivery
    User runs virtualenv --seeder pip --download
  3. Exploit
    Digest comparison path bypassed
  4. Execution
    pip installs unverified wheel
  5. Impact
    Low-integrity code seeded into environment

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

Requires virtualenv prior to 21.14.9 invoked with --seeder pip and --download, while pip/virtualenv index environment variables remain unset so the default-index PyPI SHA-256 comparison policy stays active, AND a non-PyPI index is in use that offers a candidate matching the bundled package name and version. The user must actively run the virtualenv seeding operation (UI:P). Explicit custom-index configurations already opt out of the comparison and are outside this issue. Strong limiting factors: the bypass does not defeat TLS and does not give the attacker control of the index response, exploitation is high-complexity with specific attack requirements, and resulting impact is only low integrity - so realistic risk is far below what the network vector alone suggests.

Impact

This is a genuinely low-priority issue despite a network attack vector. The vendor CVSS 4.0 base score is only 2.3, and the composite signals explain why: AV:N but AC:H (high complexity) and AT:P (specific attack requirements must be present), with UI:P meaning a user must actively run virtualenv seeding, and only Low vulnerable-system impact (VC:L/VI:L/VA:L). No EPSS score, KEV listing, or public POC is present in the provided data, so exploitation likelihood signals are all absent rather than elevated. The flaw is a narrow integrity-verification gap (CWE-494): the pip seeder's --download path bypassed virtualenv's download_wheel()/verify_wheel_digest() SHA-256 comparison against PyPI metadata. Critically, the description itself states this condition does NOT defeat TLS or grant control of the index response, so an attacker cannot trivially inject a malicious wheel - they would need an index that already legitimately serves a candidate matching the bundled name and version. PR:N (unauthenticated per the 4.0 vector) is technically accurate but misleading in isolation: real-world abuse depends on an attacker already being positioned as a non-PyPI index source. Treat this as a defense-in-depth hardening fix, not an actively-weaponizable vulnerability.

Exploit ScenarioDerived

An organization bootstraps environments with virtualenv (< 21.14.9) using --seeder pip --download while index environment variables are left unset, so the default-index PyPI digest comparison policy is active but a non-PyPI index is in use. pip is allowed to consult that index and select a candidate matching the bundled package name and version without virtualenv comparing its SHA-256 against PyPI metadata, so an unverified wheel can be seeded into the new environment. No public exploit identified at time of analysis, and the condition does not by itself defeat TLS or let the attacker forge the index response.

Monitor Track and reassess. Why: LOW severity (CVSS 0.1-3.9).
Patch available 0.3% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – Oct 20, 2026

Integrity-verification bypass in PyPA virtualenv before 21.14.9 allows a non-PyPI package index response to be consumed for a bundled seeder wheel without the default PyPI SHA-256 digest comparison ever being performed. The condition is narrow: it only arises when virtualenv is invoked with --seeder pip and --download, index environment variables are left unset so the default-index comparison policy is still active, and a non-PyPI index is configured that offers a candidate matching the bundled distribution name and version. Per our assessment (CVSS:3.1 AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:L) this is unauthenticated but high-complexity and user-initiated, does not defeat TLS, does not give an attacker control of the index response, and produces only a low, integrity-focused outcome; no public exploit code has been identified at time of analysis and there is no KEV listing. The vendor fixed the flaw in 21.14.9 by staging downloads in a private temporary directory and installing pinned wheels with --no-index.

RemediationAI

Upgrade to virtualenv 21.14.9 or later, which forces --no-index for seeder installs and routes every downloaded wheel through the private-staging-directory and PyPI digest verification path (see https://github.com/pypa/virtualenv/security/advisories/GHSA-cx28-75q4-x26q and https://github.com/pypa/virtualenv/releases/tag/21.14.9); also pin the virtualenv version in build images and CI so downstream reinstalls cannot silently revert. If upgrading must be deferred, avoid the vulnerable combination entirely: do not run virtualenv with --seeder pip together with --download - use the default app-data or bundled seeder, which goes through download_wheel()/verify_wheel_digest(), or pre-populate the wheel cache with vetted archives and pass --no-download (optionally with --extra-search-dir pointing at a locally curated directory) so no index lookup occurs at all; the trade-off is that seeding then depends on locally mirrored wheels that must be refreshed manually. Because the bypass only matters when resolution can reach an index you do not control, restrict egress from build hosts to a pinned internal mirror via proxy or firewall rules, though this is an infrastructure control rather than a fix and adds maintenance overhead. Setting an explicit custom-index configuration removes the PyPI comparison policy but should not be treated as a remediation - it explicitly opts out of the verification this CVE is about.

Affected VersionsENISA

virtualenv < 21.14.9

Affected Packages

pypi virtualenv fix: 21.14.9

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

virtualenv's pip seeder historically allowed two acquisition paths: its own download_wheel() routine, which invokes pip download and then calls verify_wheel_digest() to compare the fetched archive against PyPI's published SHA-256 metadata when the default index policy is in force, and a passthrough path used by PipInvoke.get_pip_install_cmd(), which called get_wheel(download=False) and let pip itself resolve the requirement against the configured index. Because that second path never touched download_wheel()/verify_wheel_digest(), an index candidate matching the bundled package and version could be installed with no comparison to PyPI digests at all. This is CWE-494 (Download of Code Without Integrity Check): the software fetches an executable artifact and installs it without validating its authenticity or integrity. Note that explicitly configured custom indexes already opt out of the PyPI comparison by design, so the practical attack surface is limited to configurations where the comparison policy is nominally active but the resolution still reaches a non-PyPI index. The upstream fix in PR #3430 restructures the flow so pip always runs with --no-index, each selected wheel is copied into a TemporaryDirectory alongside --find-links, and download_wheel() stages and validates the artifact before anything is moved into the reusable wheel cache, raising UnverifiedWheelError when PyPI cannot supply a digest.

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

Vendor (GitHub_M) PRIMARY 2.3 LOW
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:P/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N
vuln.today AI 5.0 MEDIUM

AC:H and UI:R because an attacker must position a matching non-PyPI index candidate under a specific unset-env config and the victim must run seeding; impact is only low integrity, no TLS/index control.

3.1 AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:L
4.0 AV:N/AC:H/AT:P/PR:N/UI:P/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N

Primary rating from Vendor (GitHub_M).

CVSS VectorVendor: GitHub_M

Attack Vector
Network
Attack Complexity
High
Attack Requirements
Present
Privileges Required
None
User Interaction
Passive
Vulnerable system: Confidentiality
Low
Vulnerable system: Integrity
Low
Vulnerable system: Availability
Low
Subsequent system: Confidentiality
None
Subsequent system: Integrity
None
Subsequent system: Availability
None

Lifecycle Timeline

2
Patch available
Oct 20, 2026 - 21:18 EUVD
CVE Published
Oct 20, 2026 - 19:22 cve.org
LOW 2.3

DescriptionCVE.org

virtualenv is a tool for creating isolated virtual python environments. Prior to 21.14.9, PipInvoke.get_pip_install_cmd() handles --seeder pip --download by calling get_wheel(download=False) and then allowing pip to consult the configured index, bypassing virtualenv's download_wheel() and verify_wheel_digest() path. When virtualenv's default-index PyPI digest comparison remains enabled, an index candidate matching the bundled package and version can therefore be selected without comparison to PyPI SHA-256 metadata. Explicit custom-index settings already opt out of that comparison and remain outside this verification-bypass claim; the demonstrated configuration used a non-PyPI index while leaving the index environment variables unset so the comparison policy remained active. This condition does not independently defeat TLS or establish control of the index response. This issue is fixed in version 21.14.9.

Threat Intelligence Overview

EPSS Score
0.3%
Top 79% exploitable
Prevalence
High
virtualenv is a near-universal Python environment bootstrap tool across dev and CI
Threat Intel
1
1 source
Data Quality
6 sources
Confidence: High
EUVD NVD CVE.org EPSS Vulnrichment GHSA GitHub

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.

SignalValue
Severity LOW
CISA KEV No
Public POC No
EPSS 0.3%
Patch available Yes
Active threat No
Deciding rule
LOW severity (CVSS 0.1-3.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision· derived
Defer
Exploitation
Poc
System Exposure· derived
Open
Automatable
No
Human Impact· derived
Low
Technical Impact
Partial

Priority Score

12
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +12
PoC: 0
Weaponized: 0
Threat intel: 0
Gov advisory: 0
CVE-2024-53899 HIGH POC
7.8 Nov 24

virtualenv before 20.26.6 allows command injection through the activation scripts for a virtual environment. Rated high

CVE-2026-102930 HIGH POC
7.7 Sep 29

virtualenv versions prior to 21.7.12 cache and seed pip/setuptools wheels without verifying their bytes, so an attacker

CVE-2026-102938 MEDIUM POC
5.8 Sep 29

Configuration injection in PyPA virtualenv before 21.7.11 lets a line boundary embedded in a prompt value inject extra k

CVE-2026-113722 HIGH
7.8 Oct 20

Command injection in PyPA virtualenv before 21.14.9 lets an attacker who controls the destination path of a virtual envi

CVE-2026-113725 HIGH
7.8 Oct 20

Command injection in virtualenv's bash activation script prior to 21.14.7 allows a crafted environment name or --prompt

CVE-2026-102925 HIGH
7.8 Sep 29

Command injection in the bash, zsh, and fish activation scripts generated by virtualenv releases prior to 21.7.13 lets a

CVE-2026-102937 HIGH
7.3 Sep 29

Command injection in PyPA virtualenv before 21.7.12 allows an attacker who controls the environment's prompt value - via

CVE-2026-115586 HIGH
7.1 Oct 23

Command injection in virtualenv's bash activator lets an attacker-supplied --prompt value be stored unescaped in PS1 and

CVE-2026-113723 HIGH
7.1 Oct 20

Caller-influenced prompt text in virtualenv's bash activation script prior to 21.14.9 can be re-expanded by bash as exec

CVE-2026-113718 HIGH
7.1 Oct 20

A code injection flaw in PyPA virtualenv before 21.14.9 lets attacker-influenced non-ASCII characters in the xonsh promp

CVE-2026-113724 MEDIUM
4.5 Oct 20

Symlink following in virtualenv's safe_delete() deletion-error handler (all versions prior to 21.14.9) lets a local atta

CVE-2026-113721 MEDIUM
4.5 Oct 20

Symlink-following file writes in virtualenv before 21.14.9 let a second, unprivileged local account redirect generated e

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy