pypi / virtualenv
virtualenv
What changed in virtualenv 20 to 21, from its official release notes, upgrade guides and advisories. Sources checked 2026-10-29.
1 breaking24 security9 fixes and other
See which of these apply to your code, ranked, in your agent:
npx @unstale/cli initvirtualenv 2133 changes
Breaking changes 1
The standalone zipapp bundles dependencies for Python 3.15 and no longer bundles Python 3.8, which is outside the supported range.
Security 23
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.
Create the
.venvredirect and wheelRECORDexclusively to prevent a planted link from redirecting writes; on POSIX, replace a read-only.venvredirect that points at a virtualenv.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)
virtualenv: Temporary app-data can leave dangling seed package links
virtualenv: Bash prompt values can change meaning under older compatibility modes
virtualenv: Builtin creation follows linked environment directories
virtualenv: Deletion recovery can change a symlink target's mode
virtualenv: Downloaded wheel selection and caching precede verification
virtualenv: Generated files can follow existing destination links
virtualenv: Generated POSIX console launchers interpret destination paths as shell syntax
virtualenv: Pip seeding with download omits wheel digest verification
virtualenv: Seed replacement does not contain metadata deletion paths
virtualenv: Seeded files retain permissions from an older cache
virtualenv: Venv configuration readback can reinterpret path boundaries
virtualenv: Xonsh activation literals depend on the script decoding codec
virtualenv bash activate runs commands from an environment name with a backslash before $
virtualenv activate runs commands from the environment name in zsh with PROMPT_SUBST
virtualenv activate.fish runs commands from a path or prompt with a backslash before a quote
virtualenv activation scripts run code from a path that contains a placeholder name
virtualenv bash and fish activation scripts execute commands embedded in paths
virtualenv: Command injection via --prompt in activate.bat (batch activator)
virtualenv: Downloaded seed wheels (pip/setuptools) are not integrity-checked before use
virtualenv writes prompt values into pyvenv.cfg without sanitizing line boundaries, allowing configuration injection
Fixes and other changes 9
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.
Count -p once rather than once per internal parsing pass.
Count -q once rather than once per internal parsing pass.
When symlink seeding is enabled on a host that cannot create symlinks, copy the seed packages instead of failing.
Copy the content of a symlinked directory when copying a tree into an environment, instead of dropping it.
Count --try-first-with once rather than once per internal parsing pass.
Count -v once rather than once per internal parsing pass, so Session.verbosity reflects the supplied option.
When symlink seeding is enabled on a host that cannot create symlinks, copy the seed packages instead of failing.
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.
virtualenv 201 changes
Security 1
virtualenv Has TOCTOU Vulnerabilities in Directory Creation