KEVWire

Security intelligence, with context.

Response snapshot Oct 27, 2026, 05:51 UTC

Back to the wire
Permalink
VulnerabilityCVE-2026-113723

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. Bash runs with compatibility level 4.2 and draws the environment prompt.

At a glance

Exploited
Not known
Severity
7.1 High (CVSS 4.0)
Chance of exploitation
0.2% in the next 30 days
Sources
2 independent sources

What to do

GitHub lists first patched versions: virtualenv: 21.14.9. Confirm the affected range and upgrade guidance in the exact advisory.

Read GitHub-reviewed advisory GHSA-6w3r-xr62-4xcp (opens a new tab)

What happened

## Summary

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.

Continue reading

## 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](https://github.com/pypa/virtualenv/blob/a795ab116356afde11039cf2763d77e8a06da738/src/virtualenv/activation/bash/activate.sh).

## 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](https://github.com/pypa/virtualenv/pull/3326) and its follow-up #3390. Those changes cover the usual bash path but leave the three paths above. The proposed change in [#3418](https://github.com/pypa/virtualenv/pull/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

```mermaid 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`**

```text #!/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`**

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

## 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](https

Affected package ranges reported by GitHub: virtualenv: < 21.14.9

Scores and how they were measured

CVSS base severity

7.1

Version 4.0As of

CVSS:4.0/AV:L/AC:H/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N

Measurement source (opens a new tab)

How bad it is if exploited. Not a prediction of exploitation or proof you are exposed.

EPSS probability

0.2%

Scored Percentile 7.3%

Model and measurement source (opens a new tab)

A model's estimate of exploitation in the next 30 days, not certainty or your own risk.

Related technology

Sources

  1. Primary source

    GitHub-reviewed advisory GHSA-6w3r-xr62-4xcp (opens a new tab)

    The public advisory supplies the description, affected package/version ranges, and any listed CVSS metric. GitHub review is not local review.

    Published Checked

  2. Primary source

    GitHub public advisory API page (opens a new tab)

    The API page supplied GHSA-6w3r-xr62-4xcp, its actual identifiers, source dates, and structured metrics.

    Published Date not suppliedChecked

  3. Primary source

    NVD CVE-2026-113723 (opens a new tab)

    NVD record: description, CVSS (the CNA score is preferred), affected products, and publication date. Not evidence of exploitation.

    Published Checked

  4. Primary source

    NVD CVE API 2.0 (opens a new tab)

    The NVD API page that supplied this CVE record.

    Published Date not suppliedChecked

  5. Primary source

    FIRST measured EPSS score (opens a new tab)

    Measured EPSS probability and percentile for CVE-2026-113723, scored 2026-10-26. This is a model estimate, not proof of exposure.

    Published Checked

Cite this record

For factual claims, cite the primary sources above; cite KEVWire for its compilation, dates, and classifications.

APA

KEVWire. (2026, October 23). virtualenv: Bash prompt values can change meaning under older compatibility modes (CVE-2026-113723). https://kevwire.com/record/CVE-2026-113723

MLA

"virtualenv: Bash prompt values can change meaning under older compatibility modes (CVE-2026-113723)." KEVWire, 23 Oct. 2026, kevwire.com/record/CVE-2026-113723.

Chicago

KEVWire. "virtualenv: Bash prompt values can change meaning under older compatibility modes (CVE-2026-113723)." Last modified October 23, 2026. https://kevwire.com/record/CVE-2026-113723.

Evidence summary (plain text)

virtualenv: Bash prompt values can change meaning under older compatibility modes (Oct 23, 2026).
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.

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.
CVSS 7.1 (version 4.0; evidence as of Oct 23, 2026; https://github.com/advisories/GHSA-6w3r-xr62-4xcp).
EPSS 0.2% for the following 30 days, scored Oct 26, 2026 (https://api.first.org/data/v1/epss?cve=CVE-2026-113723&date=2026-10-26).
Sources:
GitHub-reviewed advisory GHSA-6w3r-xr62-4xcp: https://github.com/advisories/GHSA-6w3r-xr62-4xcp
GitHub public advisory API page: https://api.github.com/advisories?type=reviewed&per_page=100&sort=updated&direction=desc
NVD CVE-2026-113723: https://nvd.nist.gov/vuln/detail/CVE-2026-113723
NVD CVE API 2.0: https://services.nvd.nist.gov/rest/json/cves/2.0?pubStartDate=2026-10-12T13:35:55.142Z&pubEndDate=2026-10-26T13:35:55.142Z&resultsPerPage=500&startIndex=6000
FIRST measured EPSS score: https://api.first.org/data/v1/epss?cve=CVE-2026-113723&date=2026-10-26
Record ID: CVE-2026-113723.
Record origin: Ingested record.
AI evidence: Not assessed.
Known exploitation: Not assessed.
Zero-day status: Not assessed. KEV membership alone does not establish zero-day status.
About this data

This record was ingested from a data source. Retrieved: Oct 27, 2026, 01:40 UTC. Ingestion is not an independent editorial investigation.

A CISA KEV listing documents known exploitation, not necessarily a zero-day; absence from the catalog does not prove a vulnerability has never been exploited.

Technology tags indicate possible relevance, not verified exposure. Confirm the affected product, version, and configuration against your own inventory; KEVWire does not scan your systems.

A personal reading checklist on this device, not verified remediation.

Record JSON

Your account

Email alerts

Email alerts are not available yet. To follow your stack today, use its RSS feed, which honors your filters, or connect an AI agent through the API.

Suggest an improvement

Ideas, missing sources, corrections, and bugs are all welcome. No account needed. Suggestions are reviewed by a person before anything changes.

Record details

Record detail