CVE-2026-113723

CVE-2026-113723 is a high-severity OS command injection vulnerability in virtualenv (pip), affecting versions < 21.14.9. It is fixed in 21.14.9.

Does this CVE actually affect you?

Kodem shows which CVEs are reachable and running in your applications, so you fix what's exploitable, not just what's listed.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Runtime intelligence, not another scanner.

Summary

virtualenv: Bash prompt values can change meaning under older compatibility modes

Caller-supplied prompt text can become executable syntax in the bash activation prompt. An attacker must influence the
value passed to virtualenv, and a user must subsequently activate the environment and draw the prompt.

Affected area

Bash runs with compatibility level 4.2 and draws the environment prompt. Its replacement-string behavior differs from
newer compatibility modes, leaving prompt text subject to a second interpretation. The report concerns POSIX activation.
It does not establish exposure through unrelated activators.

Attacker-controlled input

The attacker controls prompt or destination data passed as a virtualenv argument. The user later sources the generated
activation script.

Affected code

The relevant 21.14.8 source is in
bash prompt assembly.

Mechanism

bin/activate copies the prompt into PS1. A shell expands PS1 again when it draws a prompt, so the value must
survive both the assignment and that later expansion. The bash and zsh branches escape for their usual prompt rules.
Three other paths still interpret prompt data as commands: dash sourcing activate directly, a child dash inheriting an
exported PS1 from bash, and bash running at compatibility level 4.2 or lower. A value such as x$(touch MARKER)y then
runs touch on prompt display. Creating the environment does not run the payload.

Reproduction and evidence

The scanner's child-shell reproducer creates an environment with --prompt 'x$(touch MARKER)y', sources bin/activate
in interactive bash, and starts interactive sh (dash). Its control leaves PS1 unexported: neither shell creates
MARKER. With PS1 exported, bash displays the prompt without executing the value, but the child dash creates
MARKER; the reproducer ends in BUG. The report gives separate console reproductions for direct dash activation and
bash compatibility level 4.2. The child-shell path can arise after another environment's activation has exported PS1.

The scanner linked this finding to #3326 and its follow-up #3390. Those
changes cover the usual bash path but leave the three paths above. The proposed change in
#3418 keeps a variable reference in PS1, so prompt text is expanded as
data when drawn. The private report's reproducer was run by the scanner; the later command-execution result was supplied
by the maintainer review. This advisory does not claim that every POSIX shell or every bash mode is affected.

Introduced

The report traces direct dash sourcing to the first 20.x activator (20.0.0b1), and inherited PS1 to #3390 (first
released in 21.14.7). It demonstrates the compatibility-level case on bash 5.2. Those historical boundaries come from
the report; the release confirmed by the maintainer is 21.14.8.

Attack sequence

sequenceDiagram
    participant A as Prompt supplier
    participant V as virtualenv
    participant B as Interactive bash
    participant D as Child dash
    A->>V: --prompt x$(touch MARKER)y
    V->>B: generated bin/activate
    B->>B: assign escaped prompt to PS1
    alt PS1 is not exported
        B->>D: start sh with its own PS1
        D-->>B: marker absent
    else PS1 is exported
        B->>D: start sh with inherited PS1
        D->>D: expand $(touch MARKER) on prompt draw
        D-->>B: marker created
    end

Reproducer files

The following files are from the scanner report for ANT-2026-1MOI2X3T. They were tested against commit a857a7823c73
in the scanner image. The repro entrypoint expects companion files under /tmp/repro.d; cases that change user IDs
need a disposable root-capable container. The last output line is BUG when the reported behavior occurs. These files
are included as evidence and were not rerun for this advisory update.

repro

#!/usr/bin/env python3
import shutil
import subprocess
from pathlib import Path

work = Path("/tmp/repro-inherited-ps1")
shutil.rmtree(work, ignore_errors=True)
work.mkdir()
marker = work / "MARKER"
print("sh is", Path("/bin/sh").resolve())

# attacker: only the text a tool such as tox or hatch relays as --prompt
hostile_prompt = f"x$(touch {marker})y"

# set up: the environment, made with the virtualenv command
subprocess.run(
    ["virtualenv", "--no-periodic-update", "--without-pip", "--activators", "bash",
     "--prompt", hostile_prompt, str(work / "env")],
    check=True, stdout=subprocess.DEVNULL,
)
assert not marker.exists(), "creating the environment must not run the prompt"

# user: in an interactive bash, source bin/activate, then start sh.
# -i makes both shells draw their prompt although stdin is not a terminal; sh draws one, reads EOF and returns
session = Path("/tmp/repro.d/user_session.sh").read_text()
interactive_bash = ["bash", "--norc", "--noprofile", "-i"]

# control: PS1 set in bash but not exported, so sh does not inherit it
control = subprocess.run(interactive_bash, input="PS1='\\$ '\n" + session,
                         stderr=subprocess.PIPE, text=True, check=True)
print(control.stderr)
ran_in_control = marker.exists()
print("CONTROL  PS1 not exported: marker created:", ran_in_control)

# attack: the same session with the one difference that PS1 is exported
attack = subprocess.run(interactive_bash, input="export PS1='\\$ '\n" + session,
                        stderr=subprocess.PIPE, text=True, check=True)
print(attack.stderr)
ran_in_attack = marker.exists()
print("OBSERVED PS1 exported:     marker created:", ran_in_attack)

# check: the prompt text must be drawn, never run, by every shell that draws it
print("BUG" if ran_in_attack and not ran_in_control else "OK")

repro.d/user_session.sh

. /tmp/repro-inherited-ps1/env/bin/activate
sh -i </dev/null

Versions tested

The supplied follow-up review marks command execution as independently confirmed by its author. The implementation
review used source inspection and patched literal-value checks, without rerunning that exploit. The relevant activation
source is identical between release 21.14.8 and upstream/main 233359cb. The maintainer previously confirmed validation
of the reported findings on 21.14.8. The first affected version has not been established. Fixed in 21.14.9.

Known mitigation

Use trusted prompt and destination values. On older releases, disable the environment prompt with
VIRTUAL_ENV_DISABLE_PROMPT=1. Recreate environments with virtualenv 21.14.9 or later.

Affected release

  • The problem reproduces on virtualenv 21.14.8.

Credits

The original report was supplied by Anthropic's OSS Scanner as ANT-2026-1MOI2X3T. The subsequent maintainer-provided
review identified the remaining activation path.

Impact

An affected activation can execute commands with the user's privileges. Severity is high, following the generated-script
precedent in GHSA-p58f-9548-mpm2. The
attack requires control of argument data and subsequent user activation; it does not require replacing an executable or
controlling app-data contents.

Untrusted input reaches a shell command, allowing arbitrary commands to run on the host. Typical impact: code execution in the application's environment.

Affected versions

virtualenv (< 21.14.9)

Security releases

virtualenv → 21.14.9 (pip)

Kodem intelligence

Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.

Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.

Already deployed Kodem?

See it in your environmentNew to Kodem? Get a demo →

Remediation advice

Upgrade virtualenv to 21.14.9 or later to resolve this vulnerability.

Kodem Kai can prioritize this vulnerability in your dependency tree and generate a fix recommendation.

Frequently Asked Questions

  1. What is CVE-2026-113723? CVE-2026-113723 is a high-severity OS command injection vulnerability in virtualenv (pip), affecting versions < 21.14.9. It is fixed in 21.14.9. Untrusted input reaches a shell command, allowing arbitrary commands to run on the host.
  2. Which versions of virtualenv are affected by CVE-2026-113723? virtualenv (pip) versions < 21.14.9 is affected.
  3. Is there a fix for CVE-2026-113723? Yes. CVE-2026-113723 is fixed in 21.14.9. Upgrade to this version or later.
  4. Is CVE-2026-113723 exploitable, and should I be worried? Whether CVE-2026-113723 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
  5. What actually determines whether CVE-2026-113723 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
  6. How do I fix CVE-2026-113723? Upgrade virtualenv to 21.14.9 or later.

Other vulnerabilities in virtualenv

Stop the waste.
Protect your environment with Kodem.