Skip to content

chore(deps): update dependency virtualenv to v21 [security] - #59

Open
renovate-coveo[bot] wants to merge 1 commit into
mainfrom
renovate/pypi-virtualenv-vulnerability
Open

renovate-coveo[bot] wants to merge 1 commit into
mainfrom
renovate/pypi-virtualenv-vulnerability

Conversation

@renovate-coveo

@renovate-coveo renovate-coveo Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Note

This PR body was truncated due to platform limits.

This PR contains the following updates:

Package Change Age Adoption Passing Confidence
virtualenv (changelog) >=20.25,<21 → >=21.14,<22 age adoption passing confidence

virtualenv: Downloaded seed wheels (pip/setuptools) are not integrity-checked before use

CVE-2026-102930 / GHSA-94p9-xgh2-xp45

More information

Details

download_wheel() runs pip download and hands the result straight to the seeder, with nothing checking the bytes it gets back. The embedded pip and setuptools wheels carry a BUNDLE_SHA256 that virtualenv checks on every load, but a wheel fetched over the network for the periodic-update feature or the --download flag had no equivalent verification.

A compromised index, a stale mirror, or a MITM'd download (when TLS is intercepted, e.g. via a misconfigured or malicious CA) could substitute a different wheel under the same distribution/version/filename, and virtualenv would cache and seed it into every environment created afterward with no warning.

Fixed by computing the downloaded wheel's sha256 and comparing it against the digest PyPI's public JSON API reports for that exact release, independent of which index actually served the file. The check is skipped, not treated as failure, when a custom index (PIP_INDEX_URL, PIP_EXTRA_INDEX_URL, PIP_INDEX) is configured, since a private index can legitimately serve a different, intentionally rebuilt wheel. Fix: https://github.com/pypa/virtualenv/pull/3251

Severity

  • CVSS Score: 7.7 / 10 (High)
  • Vector String: CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


virtualenv writes prompt values into pyvenv.cfg without sanitizing line boundaries, allowing configuration injection

CVE-2026-102938 / GHSA-9h9j-4vrj-gf7g

More information

Details

Summary

pyvenv.cfg is a line-based format with no escape syntax. PyEnvCfg.write() wrote values verbatim, while PyEnvCfg._read_values() parses the file with str.splitlines(). A value containing a line boundary therefore became additional configuration lines, and because reading is last-wins, the injected keys replaced any key written earlier in the file.

Impact

The prompt value is the reachable input: it is set by --prompt, by the VIRTUALENV_PROMPT environment variable, or from the config file, and write() emits prompt before home. A crafted prompt can therefore set home in the generated pyvenv.cfg:

$ virtualenv --prompt $'x"\nhome = /attacker/path\nprompt = "z' venv
$ grep '^home' venv/pyvenv.cfg
home = /attacker/path

home is what tooling reads to locate the base interpreter, so a consumer that trusts it can be pointed elsewhere. implementation, version_info, version, executable, command and virtualenv are also written before prompt and can be replaced the same way.

This requires the prompt to come from somewhere other than the person running the command, for example a CI job templating a branch name into it, tooling deriving an environment name from user-supplied data, or an inherited VIRTUALENV_PROMPT. Where the operator supplies the prompt directly they already control the command line, and the effect is corruption rather than privilege gain: the value is truncated at the boundary and read back with a dangling quote.

Details

The boundary set is the one str.splitlines() recognizes, which is wider than \n: \r, \v, \f, the file, group and record separators, U+0085, U+2028 and U+2029 were all written through unchanged and all split the line when read back.

Patches

PyEnvCfg.write() now collapses those boundaries to spaces as it serializes each line, so it cannot emit a structurally invalid file regardless of what a caller places in content.

Workarounds

Do not pass externally influenced data as the virtualenv prompt. Strip line boundaries from any value before using it as --prompt or VIRTUALENV_PROMPT.

Severity

  • CVSS Score: 5.8 / 10 (Medium)
  • Vector String: CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:P/VC:L/VI:H/VA:L/SC:N/SI:N/SA:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


virtualenv: Command injection via --prompt in activate.bat (batch activator)

CVE-2026-102937 / GHSA-x78j-v8h9-3j2q

More information

Details

BatchActivator.quote() returned its input unchanged, the only activator with no escaping at all. --prompt, the VIRTUALENV_PROMPT environment variable, and the config file all set the prompt, and activate.bat writes it straight into @set "VAR=value". A prompt containing a double quote closes that string early, and whatever follows runs as live cmd.exe syntax:

$ virtualenv --prompt 'x" & calc & "' venv
$ venv\Scripts\activate.bat

runs calc the moment someone activates the environment. Confirmed on a real Windows runner. Anyone who templates a prompt from untrusted input (a CI job using a branch name, a wrapper script deriving an environment name from user input) hands an attacker code execution in the shell of anyone who activates the resulting venv on Windows.

Fixed in 21.7.12 by escaping the characters cmd.exe treats as live syntax inside this construct. Fix: https://github.com/pypa/virtualenv/pull/3250

Severity

  • CVSS Score: 7.3 / 10 (High)
  • Vector String: CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


virtualenv bash and fish activation scripts execute commands embedded in paths

CVE-2026-102925 / GHSA-p58f-9548-mpm2

More information

Details

Impact

The generated activate (bash/zsh) and activate.fish scripts interpolate a shlex.quote-ed value into a position that quotes it a second time. The extra quotes terminate the quoted run early and leave part of the value parsed as shell code, so a path containing shell metacharacters runs commands when a user sources the activation script.

activate is affected through the virtual environment's own path, on the branch that reports a relocated environment:

echo "Virtual environment directory __VIRTUAL_ENV__ does not exist!" >&2

For a destination named x'$(id)'y, shlex.quote emits 'x'"'"'$(id)'"'"'y'. The inner " closes the enclosing double quote and $(id) is left unquoted. Backtick and ; payloads reach the same result. This branch runs whenever the recorded path is absent, which is the normal case for a virtual environment copied or distributed to another machine.

activate.fish is affected through the interpreter's Tcl/Tk library paths:

set -gx TCL_LIBRARY '__TCL_LIBRARY__'

shlex.quote already returns '/tcl/(cmd)/lib', so the rendered line is ''/tcl/(cmd)/lib''. fish concatenates the adjacent quoted runs and expands the (cmd) left between them. The same doubling also splits a path containing a space into two list elements, corrupting TCL_LIBRARY and TK_LIBRARY.

This is the same defect class as GHSA-x78j-v8h9-3j2q, which covered activate.bat.

Patches

Fixed in 21.7.13 by moving the placeholders outside the surrounding quotes, so each value keeps only the quoting shlex.quote applied. Fix: https://github.com/pypa/virtualenv/pull/3252

Workarounds

Avoid creating or distributing virtual environments whose path contains ', `, $, ;, ( or ), and inspect the generated activation script before sourcing one you did not create.

Severity

  • CVSS Score: 7.8 / 10 (High)
  • Vector String: CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Release Notes

pypa/virtualenv (virtualenv)

v21.14.13

Compare Source

Bugfixes - 21.14.13

  • Stop bash running commands from --prompt or an environment name containing $(...), backticks or a backslash
    after shopt -s promptvars, set -o posix, or in a child shell that inherits an exported PS1
    (GHSA-cx6f-vjhg-g3cc); reported by rozzkml. zsh now draws the prompt from psvar[9], which is never parsed
    as shell syntax.

    Write the .venv redirect and the wheel RECORD with exclusive create, so a link planted after the existence
    check cannot redirect the write. On POSIX, a read-only .venv redirect that points at a virtualenv is replaced.
    (#​3466)

PyPI release

Full Changelog: pypa/virtualenv@21.14.12...21.14.13

v21.14.12

Compare Source

Bugfixes - 21.14.12

  • Upgrade embedded wheels:

    • setuptools to 84.2.1 from 84.0.0
    • pip to 26.2.2 from 26.2.1 (#​3452)

Improved Documentation - 21.14.12

  • Require a pull request news fragment and a matching changelog section before publishing. (#​3445)

PyPI release

Full Changelog: pypa/virtualenv@21.14.11...21.14.12

v21.14.11

Compare Source

Bugfixes - 21.14.11

  • Search all directories supplied by repeated --extra-search-dir options instead of keeping only the last group.
    (#​3440)
  • On Windows, the app data is now migrated into the nested cache directory instead of the migration failing with a
    warning on every run. (#​3441)

PyPI release

Full Changelog: pypa/virtualenv@21.14.10...21.14.11

v21.14.10

Compare Source

Bugfixes - 21.14.10

  • Always copy seed packages when app-data is temporary, including when symlink seeding is enabled through an environment
    variable or configuration file. Seeded packages remain available after temporary cache cleanup. (#​3437)

PyPI release

Full Changelog: pypa/virtualenv@21.14.9...21.14.10

v21.14.9

Compare Source

Bugfixes - 21.14.9

  • Parse VIRTUALENV_PERIODIC_UPDATE_INSECURE as a boolean, so 0, false, no and off keep certificate
    verification enabled. (#​3398)

  • Reject destinations whose resolved path contains the platform's PATH separator, including separators inherited from
    the working directory or a directory symlink. (#​3399)

  • Preserve an existing pyvenv.cfg when a prompt or configuration value cannot be encoded as UTF-8, instead of
    leaving the file empty after a failed environment creation. The file now ends its lines with LF on every platform.

    Debug logs show each configuration line as a Python string literal, so control characters are visible. (#​3400)

  • Skip writing a .venv redirect when the environment name contains a line boundary. The environment is still
    created, and any existing redirect remains unchanged. (#​3401)

  • Preserve non-ASCII values in activate_this.py when applications read the script with a legacy text encoding before
    executing it. (#​3402)

  • Reject malformed seed versions and requirements ending in archive suffixes before starting pip, with an error
    identifying the invalid value instead of a misleading download or local-file error. (#​3403)

  • Allow a literal percent sign as a csh prompt and preserve carets in tcsh prompt display instead of interpreting them
    as control-character notation.

    Separate csh history and prompt escapes from preceding non-ASCII text in legacy locales. (#​3404)

  • Report an error when an existing pyvenv.cfg is not a regular file, instead of trying to read or write directories,
    pipes, or devices as configuration files. (#​3405)

  • Preserve percent-containing paths during batch reactivation and show dollar signs literally in command prompts. Skip
    batch scripts for paths containing line boundaries, and remove stale batch scripts for unsupported paths even when
    only other activators are selected. (#​3406)

  • Compile shared seed-cache bytecode without loading site customizations from the destination environment or importing
    modules from the current working directory. (#​3407)

  • Keep the bundled seed version when a cached periodic update is older, and stop recording downloads below the bundled
    version during update checks. (#​3408)

  • Stop activating a moved environment, leaving PATH unchanged, when the shell is not bash, the script is evaluated
    or read from standard input, a path tool fails, the sourced file is not the environment's own activation script, or
    the new location has no pyvenv.cfg, instead of continuing with an incorrect environment path. (#​3409)

  • Reject built-in options with missing values before creating the application-data directory or starting interpreter
    discovery, instead of reporting the argument error after those operations. (#​3410)

  • Keep unset-variable bookkeeping out of exported xonsh variables, so child shells do not restore an internal sentinel
    as PYTHONHOME. Skip xonsh activation for destination names that its PATH handling would expand to a different
    path.

    Restore unset Tcl/Tk library variables when switching between environments in one xonsh session.

    Preserve non-ASCII paths and prompts when xonsh reads activation scripts with a legacy encoding. (#​3411)

  • Skip default shell activators with a warning when a POSIX path encoding is incompatible with their UTF-8 scripts.
    Explicitly requested incompatible shell activators still report an error. Environments created with --activators=
    or --activators=python remain supported in legacy locales. Undecodable parent paths are now caught before any
    shell activation script is written. (#​3412)

  • Keep apostrophes and backslashes in fish activation values separate from preceding non-ASCII characters, so fish 3
    legacy locale decoders cannot consume their escapes as part of a multibyte character. (#​3413)

  • Preserve backslashes and apostrophes in csh activation values when tcsh's backslash_quote option is enabled.
    Assign prompt text before conditional branches so skipped prompt branches do not reinterpret its quoting.

    Display literal backslashes once in bsd-csh prompts. Keep disabled prompts unchanged when generated values contain
    quotes. (#​3414)

  • Preserve backslashes in POSIX environment directory names during PowerShell activation, including configuration lookup
    and the default prompt. Resolve relative, home-relative, PSDrive-qualified and filesystem provider-qualified
    -VenvDir arguments to absolute paths, and stop activation when that resolution fails. (#​3415)

  • Keep helper processes for pip, symlink-seed compilation, stdlib venv creation, and periodic wheel updates from
    importing modules through Python's implicit current-directory entry. Pip helpers retain the selected bootstrap wheel
    on their import path.

    Preserve Python environment-variable overrides for delegated stdlib venv creation while removing the implicit
    working-directory import entry.

    Retain explicit Python configuration when compiling symlink seed images, and report compilation failures.
    (#​3416)

  • Preserve spaces, quotes, and backslashes in interpreter paths when pip console scripts need a POSIX shell launcher.
    Paths containing tabs also use the shell launcher so the kernel does not split the interpreter name.

    Apply the same launcher quoting after pip seeding and refresh the installed file records. Later independent pip
    installs or upgrades can overwrite these launchers; recreate affected environments after upgrading virtualenv.
    (#​3417)

  • Leave PS1 unchanged when sourcing the POSIX activation script in a shell other than bash or zsh, whose prompt
    escaping rules virtualenv handles; VIRTUAL_ENV_PROMPT stays available to custom prompts in other shells.

    In bash, keep the prompt literal under older compatibility levels, with promptvars disabled and in posix mode, and
    avoid nounset errors after VIRTUAL_ENV_PROMPT is unset. (#​3418)

  • Remove Python's implicit working-directory import entry before handling python -m virtualenv commands, reducing
    accidental module shadowing during environment creation. Explicit import paths keep their existing order.

    Keep the working-directory entry when virtualenv itself is installed there, and preserve explicit paths under Python
    safe-path mode. (#​3419)

  • Start periodic wheel updates with the same virtualenv installation or zipapp that scheduled them, even when the host
    interpreter has another virtualenv version installed or no installed copy.

    Keep standard-library precedence and explicit Python configuration in update processes, and drop only the implicit
    working-directory import entry before importing anything. (#​3420)

  • Create new default app-data directories with owner-only access where supported. For existing POSIX defaults owned by
    the current user, remove group and other write access, preserving group write on setgid shared caches. Keep
    permissions on directories owned by another user and on explicit app-data paths. Warn and use temporary app-data if
    changing an owned default cache's permissions fails. (#​3421)

  • Reject --clear when the normalized destination is a symlink or Windows reparse point, including paths containing
    ... Pass the target directory explicitly to clear it. Creating an environment through a symlink without
    --clear remains supported. (#​3422)

  • Detach seed-package and launcher symlinks before running the pip seeder. Reseeding an environment created with
    --symlink-app-data no longer rewrites its shared wheel image. Unrelated launcher symlinks remain in place.

    Preserve case in console entry-point names and use the last value for duplicate entries when regenerating launchers.

    Remove linked metadata from previous seed versions when reseeding with pip so package listings report the installed
    version. (#​3423)

  • Replace line-boundary characters in csh prompt text with spaces so activation remains valid.

    When a filesystem path contains a newline, skip csh activation and remove any stale csh activation scripts. Keep
    filesystem paths unchanged, including other control characters, and omit skipped activators from the creation summary.
    (#​3424)

  • Apply the current umask when copying interpreter and seed-package files instead of inheriting cached permission bits.
    Executable sources remain executable within the permissions allowed by that umask. Copied files no longer grant group
    or world write access, even with a permissive umask. Source modes are not preserved: data files start from 0644 and
    executable files from 0755 before applying the umask. (#​3425)

  • Reject destinations containing line boundaries when using the stdlib venv creator, before it writes
    pyvenv.cfg. Other creators retain their existing destination support. Write the final configuration from the
    selected interpreter and virtualenv options instead of merging stdlib's intermediate configuration. GraalPy launcher
    settings are derived from the selected interpreter. (#​3426)

  • Preserve file permissions when deletion fails on POSIX. On Windows, clear read-only attributes through a handle that
    opens the entry itself and prevents replacement, preserving other attributes and rejecting reparse points.
    (#​3427)

  • Limit seed-package cleanup to entries inside the environment. Ignore metadata entries that name the environment
    itself, a directory holding the metadata (a blank top_level.txt line names site-packages), or resolve outside
    the environment, with a warning. Launcher entries inside the environment remain supported. (#​3428)

  • Replace pre-existing directory symlinks and Windows junctions in the environment's executable and library paths before
    creating files. Links within those paths are replaced even when they point inside the environment. Log replaced links
    and junctions, and reject a non-directory encountered while creating their replacements. (#​3429)

  • Verify downloads in a private staging directory before adding them to the reusable wheel cache. Select the downloaded
    archive from that directory instead of pip's output. The pip seeder now uses the same download verification path and
    installs pinned versions from a temporary directory containing only the selected wheels, without another index lookup.
    Seeded packages retain version pins in pip freeze output. (#​3430)

  • Replace existing symbolic and hard links when writing environment configuration, activation scripts, import hooks, and
    seed launchers. Create generated text files exclusively so a replacement link cannot redirect the final file open.
    Before recreating an environment with the stdlib venv creator, replace executable-directory symlinks and Windows
    junctions with real directories. Remove symbolic and hard links inside that directory before creating interpreter
    files, including when switching from symlinks to copies. (#​3431)

  • Write xonsh prompt and path literals as ASCII escapes in every generated activation script. This preserves their
    values when xonsh reads the script with a legacy encoding such as GBK or Big5. Regenerate existing scripts to apply
    the fix. (#​3432)

  • Keep existing redirects whose target has a non-regular configuration file, and allow --clear to recreate
    environments with such configuration paths. (#​3433)

  • Reject invalid and archive-like seed versions while parsing options for both seeders, before creating an environment
    or looking up wheels, with an error naming the invalid value. Apply the same validation to versions obtained from
    wheel filenames. (#​3434)

  • Skip writing .venv redirects for environment names with leading or trailing whitespace, which redirect readers may
    strip. (#​3435)

Improved Documentation - 21.14.9

  • Document the accepted boolean values and environment-only scope of VIRTUALENV_PERIODIC_UPDATE_INSECURE.
    (#​3436)

PyPI release

Full Changelog: pypa/virtualenv@21.14.8...21.14.9

v21.14.8

Compare Source

Bugfixes - 21.14.8

  • Activate PowerShell environments whose path contains square brackets, and read the environment's own pyvenv.cfg
    instead of whichever file the path matches as a wildcard pattern - by repzakske. (#​3396)

PyPI release

Full Changelog: pypa/virtualenv@21.14.7...21.14.8

v21.14.7

Compare Source

Bugfixes - 21.14.7

  • Escape the environment name in the bash activator for both of bash's PS1 passes, so a name or --prompt value
    with a backslash before $(...) or backticks no longer runs as a command each time bash draws the prompt - by
    gaborbernat. (#​3390)

PyPI release

Full Changelog: pypa/virtualenv@21.14.6...21.14.7

v21.14.6

Compare Source

Bugfixes - 21.14.6

  • Fall back to the bundled seed wheel with periodic update on (the default) when the embed update log holds JSON of the
    wrong shape, instead of downloading the wheel or, offline, failing to create the environment - by darrenhuai.
    (#​3383)

PyPI release

Full Changelog: pypa/virtualenv@21.14.5...21.14.6

v21.14.5

Compare Source

Bugfixes - 21.14.5

  • Fall back to the bundled seed wheel and remove the embed update log when the log in the app data folder holds JSON of
    the wrong shape, instead of failing to create the environment - by pasmud. (#​3376)

PyPI release

Full Changelog: pypa/virtualenv@21.14.4...21.14.5

v21.14.4

Compare Source

Bugfixes - 21.14.4

  • Fix activate running commands from a virtual environment name or --prompt that holds $(...), backticks or
    ${...} when zsh has PROMPT_SUBST set, and show a % in the name as typed under zsh (GHSA-5vjq-rrrf-7h2q <https://github.com/pypa/virtualenv/security/advisories/GHSA-5vjq-rrrf-7h2q>_); reported by kemrec.
    (#​3373)

PyPI release

Full Changelog: pypa/virtualenv@21.14.3...21.14.4

v21.14.3

Compare Source

Bugfixes - 21.14.3

  • Honor ~= and every clause of a seed wheel's Requires-Python when picking a wheel for the target Python, and
    skip a wheel whose Requires-Python is not a valid specifier instead of failing - by pasmud.
    (#​3369)

PyPI release

Full Changelog: pypa/virtualenv@21.14.2...21.14.3

v21.14.2

Compare Source

Bugfixes - 21.14.2

  • Fix pyvenv.cfg getting an absolute path in python-version, include-system-site-packages and the other keys
    that hold no path when the working directory has an entry named like the value, such as 3.14 for virtualenv 3.14 or true with --system-site-packages - by darrenhuai. (#​3366)
  • Fix activation scripts running code from a virtual environment path whose parent directory carries a placeholder name
    such as __VIRTUAL_NAME__ (GHSA-8rjx-v5ww-45pp <https://github.com/pypa/virtualenv/security/advisories/GHSA-8rjx-v5ww-45pp>), and activate.fish running
    commands from a path or --prompt that holds a backslash before a single quote (GHSA-c947-3pg5-gm8q <https://github.com/pypa/virtualenv/security/advisories/GHSA-c947-3pg5-gm8q>
    ); both reported by Kwstubbs of
    GitHub Security Lab. (#​3367)

PyPI release

Full Changelog: pypa/virtualenv@21.14.1...21.14.2

v21.14.1

Compare Source

No significant changes.

PyPI release

Full Changelog: pypa/virtualenv@21.14.0...21.14.1

v21.14.0

Compare Source

Features - 21.14.0

  • Record the SPDX license id in the wheel and zipapp SBOMs for bundled packages that declare their license by name or
    classifier, such as distlib and python-discovery, so license scanners can match them. (#​3339)
  • Add the Tidelift and thanks.dev funding links to the PyPI project URLs, next to GitHub Sponsors - by
    gaborbernat. (#​3340)

Bugfixes - 21.14.0

  • Build the release sdist, wheel and zipapp with the build backend and SBOM tools that
    tasks/release-requirements.txt pins by version and SHA-256, so a rebuild of the tag uses the same versions.
    (#​3337)
  • Use PEP 440 version ordering when selecting seed wheels, so pinned pre-releases, post-releases and local versions
    resolve to the requested wheel. (#​3361)

Improved Documentation - 21.14.0

  • Apply the licensing policy to what the wheel and zipapp ship, checked against their SBOMs, and name
    ALLOWED_LICENSES in tasks/license_policy.py as the list of accepted licenses. (#​3339)
  • Document what a maintainer checks when reviewing a pull request and what the main ruleset requires before a merge
  • Document how the project selects, obtains and tracks its dependencies, and which dependency findings block a merge or
    a release - by gaborbernat. (#​3342)
  • Document which static analysis findings block a merge or a release, and how maintainers suppress a finding - by
    gaborbernat. (#​3343)
  • Document which secrets the project stores, who can read them and when maintainers rotate them - by
    gaborbernat. (#​3344)
  • Update the roadmap: 832 support shipped, and 838 waits on the PEP - by gaborbernat.
    (#​3345)

PyPI release

Full Changelog: pypa/virtualenv@21.13.0...21.14.0

v21.13.0

Compare Source

Features - 21.13.0

  • Add Changelog and Funding links to the PyPI project metadata, and replace the 2020-202x placeholder in
    LICENSE with 2020-present so the copyright field of the wheel SBOM reads as a real range - by
    gaborbernat. (#​3334)

Bugfixes - 21.13.0

  • Escape the curly single quotes U+2018-U+201B in the PowerShell activator's quote so a virtual environment
    prompt, name or Tcl/Tk library path containing them can no longer close the string literal and run commands - by
    gaborbernat. (#​3325)
  • Stop the bash activator from re-expanding the prompt inside PS1, so a virtual environment name or --prompt
    value containing $(...), backticks or backslashes no longer runs as a command each time bash draws the prompt - by
    gaborbernat. (#​3326)

Improved Documentation - 21.13.0

  • Correct the documented changelog fragment types and example to match the enforced towncrier categories.
    (#​3323)
  • List the Unlicense and the SPDX BSD variants in the runtime dependency licensing policy, matching the filelock
    releases virtualenv installs on Python 3.9, and describe the dependency review check that enforces the policy.
    (#​3329)
  • Show how to check a release with gh release verify and gh release verify-asset, and how to rebuild the zipapp
    byte for byte with the build tool versions its SBOMs list. Drop the claims that the zipapp build does not pin the
    distributions it bundles and that wheels differ between build machines - by gaborbernat. (#​3330)

PyPI release

Full Changelog: pypa/virtualenv@21.12.1...21.13.0

v21.12.1

Compare Source

Bugfixes - 21.12.1

  • Limit the 832 .venv redirect to folders holding a pyproject.toml and no .venv yet, so virtualenv foo in a scratch folder, and tools such as tox or nox building environments through virtualenv, no longer claim a
    folder's default environment - by gaborbernat.

    • --venv-redirect writes the redirect in any folder and replaces an earlier virtualenv redirect.
    • A flag on the command line overrides the environment variable and the config file in either direction.
      (#​3316)

PyPI release

Full Changelog: pypa/virtualenv@21.12.0...21.12.1

v21.12.0

Compare Source

Features - 21.12.0

  • Write the PEP 838 <https://peps.python.org/pep-0838/>_ python-version key into pyvenv.cfg, holding the
    target interpreter's feature release. The new reference/files page covers it alongside every other file a
    created environment holds - by konstin. (#​3193)

  • Point a .venv redirect file in the parent folder at the created environment, per PEP 832 <https://peps.python.org/pep-0832/>_, so editors and type checkers can find it - by gaborbernat.

    • virtualenv leaves a .venv folder alone, and a redirect pointing at an environment it did not create.
    • Pass --no-venv-redirect to opt out.
    • The feature is provisional while PEP 832 is a draft: a minor or patch release may change it in backward incompatible
      ways to follow the PEP. (#​3204)

PyPI release

Full Changelog: pypa/virtualenv@21.11.1...21.12.0

v21.11.1

Compare Source

Bugfixes - 21.11.1

  • Include the pre-commit configuration and the zipapp lock file in the source distribution, so downstream packagers can
    run the test suite from it. (#​3314)

PyPI release

Full Changelog: pypa/virtualenv@21.11.0...21.11.1

v21.11.0

Compare Source

Features - 21.11.0

  • Attach the CycloneDX SBOM and an SPDX 2.3 rendering of it (virtualenv.cdx.json, virtualenv.spdx.json) to each
    GitHub release, and attest the SPDX document against the sdist and wheel. (#​3299)
  • Describe the zipapp in its own CycloneDX SBOM, which lists virtualenv, the embedded pip and setuptools wheels, and
    each bundled dependency with the Python versions that load it, down to a SHA-256 per file. The SBOM sits at the root
    of virtualenv.pyz, ships as the virtualenv.pyz.cdx.json release asset, and GitHub attests it against the
    zipapp. (#​3310)

Bugfixes - 21.11.0

  • Refuse a seed wheel downloaded from the default index when virtualenv cannot get its sha256 from PyPI after three
    retries, instead of seeding it unverified. Seeding falls back to the bundled wheel unless a specific version was
    requested. (#​3302)
  • Build the zipapp from the dependency wheels that pylock.zipapp.toml pins by URL and sha256, so a release bundles
    only files matching the committed hashes. (#​3306)
  • Leave the build machine out of the wheel and zipapp SBOMs, so the wheel rebuilds byte for byte on any operating system
    and architecture given the same source, SOURCE_DATE_EPOCH, Python patch version and build backend versions. Zipapp
    entries now carry the SOURCE_DATE_EPOCH timestamp and fixed permissions instead of the build time. (#​3311)

Improved Documentation - 21.11.0

  • Document the backup maintainer and the two-factor authentication and access review expectations for maintainers.
    (#​3290)
  • Link the Carl Meyer talk on the home page over HTTPS - by gaborbernat. (#​3300)
  • Add a roadmap to the development guide listing what the project plans to do, and not do, through September 2027 - by
    gaborbernat. (#​3304)
  • Document what a release publishes and how to verify each file, covering the PyPI attestations, the zipapp and its
    provenance, the CycloneDX and SPDX SBOMs of the wheel, the zipapp SBOM, and rebuilding the sdist from its tag.
    (#​3305)

PyPI release

Full Changelog: pypa/virtualenv@21.10.0...21.11.0

v21.10.0

Compare Source

Features - 21.10.0

  • Include versioned identities for packages vendored inside seed wheels in the embedded SBOM. (#​3281)
  • Allow filelock 4.x on Python 3.10+ by relaxing the upper bound from <4 to <5 - by r3wretrhy.
    (#​3285)

Bugfixes - 21.10.0

  • Skip Windows batch activation scripts when environment or Tcl/Tk paths contain ^ or !, since quoting changes
    those paths. Other activation scripts remain available. (#​3280)

PyPI release

Full Changelog: pypa/virtualenv@21.9.1...21.10.0

v21.9.1

Compare Source

Bugfixes - 21.9.1

  • Correct SBOM CSV parsing and unresolved dependency relationships, and omit CI run identifiers from reproducible
    builds. (#​3278)

PyPI release

Full Changelog: pypa/virtualenv@21.9.0...21.9.1

v21.9.0

Compare Source

Features - 21.9.0

  • The embedded SBOM now describes the root component's license, copyright, maintainers and project links, each bundled
    wheel from its own metadata, the declared runtime dependencies, and the full build environment (interpreter, OS and
    every distribution in the isolated build environment with the dependency graph between them), plus the GitHub Actions
    run when built there. (#​3270)

Bugfixes - 21.9.0

  • Add metadata.timestamp (derived from SOURCE_DATE_EPOCH for reproducibility) and metadata.tools naming the
    generator to the embedded SBOM, and validate both fields in the packaging checks that already run on every pull
    request. (#​3269)
  • Fix the embedded SBOM not conforming to the CycloneDX 1.6 schema (an invalid vendor key on the generator tool
    entry) and validate it against the schema in CI. (#​3270)

PyPI release

Full Changelog: pypa/virtualenv@21.8.1...21.9.0

v21.8.1

Compare Source

Bugfixes - 21.8.1

  • Make the embedded SBOM's serialNumber a deterministic UUID derived from the package name, version and bundled
    wheel hashes, so the same source tree produces a byte-identical SBOM, and validate the SBOM's structure as part of the
    packaging checks that already run on every pull request. (#​3268)

PyPI release

Full Changelog: pypa/virtualenv@21.7.16...21.8.1

v21.7.16

Compare Source

Bugfixes - 21.7.16

  • Fix activate.csh rendering the venv's prompt text wrong when it contains ! (csh and tcsh both expand it) or
    % (tcsh only, since plain csh has no % prompt escape at all). (#​3263)

PyPI release

Full Changelog: pypa/virtualenv@21.7.15...21.7.16

v21.7.15

Compare Source

Bugfixes - 21.7.15

  • Restore an empty PATH on deactivate in the bash and fish activators, and stop bash leaving the prompt in
    PS1 when it was unset before activation. (#​3259)
  • Fix activate.csh failing to restore PATH and other saved variables on deactivate when PATH was already
    empty. (#​3260)

PyPI release

Full Changelog: pypa/virtualenv@21.7.14...21.7.15

v21.7.14

Compare Source

Bugfixes - 21.7.14

  • Fix activate.csh failing with Event not found when the virtual environment path contains !.
    (#​3256)

PyPI release

Full Changelog: pypa/virtualenv@21.7.13...21.7.14

v21.7.13

Compare Source

Bugfixes - 21.7.13

  • Fix activate and activate.fish running commands embedded in the virtual environment path or in the
    interpreter's Tcl/Tk library paths. (#​3252)

PyPI release

Full Changelog: pypa/virtualenv@21.7.12...21.7.13

v21.7.12

Compare Source

Bugfixes - 21.7.12

  • Fix activate.bat running arbitrary commands from a crafted --prompt, VIRTUALENV_PROMPT, or config file
    value. (#​3250)
  • Verify a downloaded seed wheel's sha256 against PyPI before seeding it into a virtual environment, skipped when a
    custom pip index is configured. (#​3251)

PyPI release

Full Changelog: pypa/virtualenv@21.7.11...21.7.12

v21.7.11

Compare Source

Bugfixes - 21.7.11

  • Running activate.bat again before deactivate no longer makes deactivate leave the environment's
    PKG_CONFIG_PATH, TCL_LIBRARY and TK_LIBRARY behind, or lose values the user had set before the first
    activation - by darrenhuai. (#​3245)
  • Write pyvenv.cfg values on a single line, so a prompt carrying a line boundary can no longer inject configuration.
    --prompt, the VIRTUALENV_PROMPT environment variable and the config file all set the prompt, and
    pyvenv.cfg has no escape syntax, so a newline, a carriage return, or any other boundary str.splitlines
    recognizes, such as U+2028, started a new configuration line. Reading the file back picked up those lines as keys,
    and since the last value for a key wins, they replaced anything written earlier, including home. (#​3247)

Improved Documentation - 21.7.11

  • Document the policy for AI-assisted contributions and the licensing rules for dependencies. (#​3239)

Misc - 21.7.11

[PyPI release](https://pypi.org/project/virtualenv/

[!IMPORTANT]
✂ PR body was truncated to here.


Configuration

📅 Schedule: (in timezone America/Toronto)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • "after 9:00am and before 12:00pm on tuesday, wednesday, thursday"

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Mend Renovate CLI.

@renovate-coveo
renovate-coveo Bot requested a review from a team as a code owner October 7, 2026 10:20
@renovate-coveo
renovate-coveo Bot force-pushed the renovate/pypi-virtualenv-vulnerability branch from 03f13de to 02ab691 Compare October 8, 2026 14:59
@renovate-coveo renovate-coveo Bot changed the title chore(deps): update dependency virtualenv to v21 [security] chore(deps): update dependency virtualenv to v21 [security] - autoclosed Oct 20, 2026
@renovate-coveo renovate-coveo Bot closed this Oct 20, 2026
@renovate-coveo
renovate-coveo Bot deleted the renovate/pypi-virtualenv-vulnerability branch October 20, 2026 14:59
@renovate-coveo renovate-coveo Bot changed the title chore(deps): update dependency virtualenv to v21 [security] - autoclosed chore(deps): update dependency virtualenv to v21 [security] Oct 20, 2026
@renovate-coveo renovate-coveo Bot reopened this Oct 20, 2026
@renovate-coveo
renovate-coveo Bot force-pushed the renovate/pypi-virtualenv-vulnerability branch 4 times, most recently from 4c53582 to 289efd8 Compare October 21, 2026 08:24
@renovate-coveo renovate-coveo Bot changed the title chore(deps): update dependency virtualenv to v21 [security] chore(deps): update dependency virtualenv to v21 [security] - autoclosed Oct 22, 2026
@renovate-coveo renovate-coveo Bot closed this Oct 22, 2026
@renovate-coveo renovate-coveo Bot changed the title chore(deps): update dependency virtualenv to v21 [security] - autoclosed chore(deps): update dependency virtualenv to v21 [security] Oct 22, 2026
@renovate-coveo renovate-coveo Bot reopened this Oct 22, 2026
@renovate-coveo
renovate-coveo Bot force-pushed the renovate/pypi-virtualenv-vulnerability branch from 289efd8 to 75325bb Compare October 22, 2026 17:20
@renovate-coveo
renovate-coveo Bot force-pushed the renovate/pypi-virtualenv-vulnerability branch from 75325bb to c36f24c Compare October 22, 2026 20:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants