# What changed in virtualenv

> 34 changes in virtualenv 20 to 21 from its official release notes, upgrade guides and advisories: 1 breaking, 24 security. Each one cited. Sources checked 2026-10-29. HTML: https://unstale.sh/pypi/virtualenv/

To see which of these apply to a repository, run `npx @unstale/cli init` in it.

## virtualenv 21

### Breaking changes

- The standalone zipapp bundles dependencies for Python 3.15 and no longer bundles Python 3.8, which is outside the supported range. (21.15.0) — [release notes](https://github.com/pypa/virtualenv/releases/tag/21.15.0)

### Security

- Prevent prompt or environment-name content from running as shell commands; zsh now draws the prompt from psvar[9], which is never parsed as shell syntax. (21.14.13) — [release notes](https://github.com/pypa/virtualenv/releases/tag/21.14.13)
- Create the `.venv` redirect and wheel `RECORD` exclusively to prevent a planted link from redirecting writes; on POSIX, replace a read-only `.venv` redirect that points at a virtualenv. (21.14.13) — [release notes](https://github.com/pypa/virtualenv/releases/tag/21.14.13)
- virtualenv: Bash activator leaves the --prompt value unescaped in PS1 when promptvars is off, so prompt expansion later executes it (regression in 21.14.9) (21.14.13) — [security advisory](https://github.com/advisories/GHSA-CX6F-VJHG-G3CC)
- virtualenv: Temporary app-data can leave dangling seed package links (21.14.10) — [security advisory](https://github.com/advisories/GHSA-4F8H-VR72-P32C)
- virtualenv: Bash prompt values can change meaning under older compatibility modes (21.14.9) — [security advisory](https://github.com/advisories/GHSA-6W3R-XR62-4XCP)
- virtualenv: Builtin creation follows linked environment directories (21.14.9) — [security advisory](https://github.com/advisories/GHSA-CW65-GX24-RC82)
- virtualenv: Deletion recovery can change a symlink target's mode (21.14.9) — [security advisory](https://github.com/advisories/GHSA-43MP-35Q3-X3FQ)
- virtualenv: Downloaded wheel selection and caching precede verification (21.14.9) — [security advisory](https://github.com/advisories/GHSA-494P-63J8-28P3)
- virtualenv: Generated files can follow existing destination links (21.14.9) — [security advisory](https://github.com/advisories/GHSA-558C-9HV2-4PRJ)
- virtualenv: Generated POSIX console launchers interpret destination paths as shell syntax (21.14.9) — [security advisory](https://github.com/advisories/GHSA-C978-59M8-C77V)
- virtualenv: Pip seeding with download omits wheel digest verification (21.14.9) — [security advisory](https://github.com/advisories/GHSA-CX28-75Q4-X26Q)
- virtualenv: Seed replacement does not contain metadata deletion paths (21.14.9) — [security advisory](https://github.com/advisories/GHSA-HHXQ-47XX-J5XX)
- virtualenv: Seeded files retain permissions from an older cache (21.14.9) — [security advisory](https://github.com/advisories/GHSA-FC2G-4W5P-6WHM)
- virtualenv: Venv configuration readback can reinterpret path boundaries (21.14.9) — [security advisory](https://github.com/advisories/GHSA-QMX5-4P3X-WVQF)
- virtualenv: Xonsh activation literals depend on the script decoding codec (21.14.9) — [security advisory](https://github.com/advisories/GHSA-394H-QWMC-48PF)
- virtualenv bash activate runs commands from an environment name with a backslash before $ (21.14.7) — [security advisory](https://github.com/advisories/GHSA-VXJ4-Q4G9-CRJ7)
- virtualenv activate runs commands from the environment name in zsh with PROMPT_SUBST (21.14.4) — [security advisory](https://github.com/advisories/GHSA-5VJQ-RRRF-7H2Q)
- virtualenv activate.fish runs commands from a path or prompt with a backslash before a quote (21.14.2) — [security advisory](https://github.com/advisories/GHSA-C947-3PG5-GM8Q)
- virtualenv activation scripts run code from a path that contains a placeholder name (21.14.2) — [security advisory](https://github.com/advisories/GHSA-8RJX-V5WW-45PP)
- virtualenv bash and fish activation scripts execute commands embedded in paths (21.7.13) — [security advisory](https://github.com/advisories/GHSA-P58F-9548-MPM2)
- virtualenv: Command injection via --prompt in activate.bat (batch activator) (21.7.12) — [security advisory](https://github.com/advisories/GHSA-X78J-V8H9-3J2Q)
- virtualenv: Downloaded seed wheels (pip/setuptools) are not integrity-checked before use (21.7.12) — [security advisory](https://github.com/advisories/GHSA-94P9-XGH2-XP45)
- virtualenv writes prompt values into pyvenv.cfg without sanitizing line boundaries, allowing configuration injection (21.7.11) — [security advisory](https://github.com/advisories/GHSA-9H9J-4VRJ-GF7G)

### Fixes and other changes

- Seeded console_scripts entries containing digits that do not end in a version keep their full names, preventing names such as python3-config from overwriting the environment's python executable. (21.15.1) — [release notes](https://github.com/pypa/virtualenv/releases/tag/21.15.1)
- Count -p once rather than once per internal parsing pass. (21.15.1) — [release notes](https://github.com/pypa/virtualenv/releases/tag/21.15.1)
- Count -q once rather than once per internal parsing pass. (21.15.1) — [release notes](https://github.com/pypa/virtualenv/releases/tag/21.15.1)
- When symlink seeding is enabled on a host that cannot create symlinks, copy the seed packages instead of failing. (21.15.1) — [release notes](https://github.com/pypa/virtualenv/releases/tag/21.15.1)
- Copy the content of a symlinked directory when copying a tree into an environment, instead of dropping it. (21.15.1) — [release notes](https://github.com/pypa/virtualenv/releases/tag/21.15.1)
- Count --try-first-with once rather than once per internal parsing pass. (21.15.1) — [release notes](https://github.com/pypa/virtualenv/releases/tag/21.15.1)
- Count -v once rather than once per internal parsing pass, so Session.verbosity reflects the supplied option. (21.15.1) — [release notes](https://github.com/pypa/virtualenv/releases/tag/21.15.1)
- When symlink seeding is enabled on a host that cannot create symlinks, copy the seed packages instead of failing. (21.15.1) — [release notes](https://github.com/pypa/virtualenv/releases/tag/21.15.1)
- Collect target interpreter debug information without PYTHONPATH and with the environment passed to cli_run, so reported sys.path no longer includes the caller's PYTHONPATH entries. (21.15.1) — [release notes](https://github.com/pypa/virtualenv/releases/tag/21.15.1)

## virtualenv 20

### Security

- virtualenv Has TOCTOU Vulnerabilities in Directory Creation (20.36.1) — [security advisory](https://github.com/advisories/GHSA-597G-3PHW-6986)
