GHSA-c947-3pg5-gm8q

Suggest an improvement
Source
https://github.com/advisories/GHSA-c947-3pg5-gm8q
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-c947-3pg5-gm8q/GHSA-c947-3pg5-gm8q.json
JSON Data
https://api.osv.dev/v1/vulns/GHSA-c947-3pg5-gm8q
Aliases
Downstream
Published
2026-10-21T16:39:58Z
Modified
2026-10-21T17:00:06Z
Severity
  • 7.8 (High) CVSS_V3 - CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H CVSS Calculator
Summary
virtualenv activate.fish runs commands from a path or prompt with a backslash before a quote
Details

Impact

FishActivator defines no quote(), so it inherits ViaTemplateActivator.quote, which returns shlex.quote(string). That function follows POSIX sh rules, where a backslash inside single quotes stays a literal character. fish reads \' inside single quotes as an escaped quote and \\ as an escaped backslash. A value with a backslash before a quote therefore ends the literal somewhere other than where shlex.quote put the end, and fish expands the command substitution that follows.

The environment path reaches set -gx VIRTUAL_ENV, and --prompt or VIRTUALENV_PROMPT reaches set -gx VIRTUAL_ENV_PROMPT. For --prompt "x\'\$(touch PWNED)'\'", the generated activate.fish contains:

set -gx VIRTUAL_ENV_PROMPT 'x\'"'"'$(touch PWNED)'"'"'\'"'"''

source bin/activate.fish runs touch PWNED, and fish prints no error. The same payload as a directory name runs through VIRTUAL_ENV. --prompt . takes the current directory's name, so running virtualenv inside a directory someone else named is enough. Without the backslash the payload runs nothing, and under bash it runs nothing either.

virtualenv generates activate.fish by default. An attacker needs to influence the environment path or prompt: a CI job or wrapper tool that passes a branch, project or job name through, or a directory in a cloned repository or unpacked archive.

The bug affects every release up to 21.14.1 that ships activate.fish. The GHSA-p58f-9548-mpm2 fix in 21.7.13 moved the placeholders outside their quotes but kept shlex.quote.

Patches

Fixed in 21.14.2. activate.fish now escapes backslashes and single quotes the way fish reads them, so the example above runs nothing and shows the prompt as given. Fix: https://github.com/pypa/virtualenv/commit/3bddeaf8d02c3ee7f576503efb082f8f494cfcab

Workarounds

Do not create an environment whose path or prompt contains a backslash, and inspect activate.fish before you source one you did not create.

Credits

Kevin Stubbings (@Kwstubbs) of GitHub Security Lab reported this issue.

Database specific
{
    "cwe_ids":  [
        "CWE-116",
        "CWE-78"
    ],
    "github_reviewed":  true,
    "github_reviewed_at":  "2026-10-21T16:39:58Z",
    "nvd_published_at":  "2026-10-20T22:19:30Z",
    "severity":  "HIGH"
}
References

Affected packages

PyPI / virtualenv

Package

Name
virtualenv
View open source insights on deps.dev
Purl
pkg:pypi/virtualenv

Affected ranges

Type
ECOSYSTEM
Events
Introduced
0 Unknown introduced version / All previous versions are affected
Fixed
21.14.2

Affected versions

0.*
0.8
0.8.1
0.8.2
0.8.3
0.8.4
0.9
0.9.1
0.9.2
1.*
1.0
1.1
1.2
1.3
1.3.1
1.3.2
1.3.3
1.3.4
1.4rc1
1.4
1.4.1
1.4.2
1.4.3
1.4.4
1.4.5
1.4.6
1.4.7
1.4.8
1.4.9
1.5
1.5.1
1.5.2
1.6
1.6.1
1.6.2
1.6.3
1.6.4
1.7
1.7.1
1.7.1.1
1.7.1.2
1.7.2
1.8
1.8.1
1.8.2
1.8.3
1.8.4
1.9
1.9.1
1.10
1.10.1
1.11
1.11.1
1.11.2
1.11.3
1.11.4
1.11.5
1.11.6
12.*
12.0
12.0.1
12.0.2
12.0.4
12.0.5
12.0.6
12.0.7
12.1.0
12.1.1
13.*
13.0.0
13.0.1
13.0.2
13.0.3
13.1.0
13.1.1
13.1.2
14.*
14.0.0
14.0.1
14.0.2
14.0.3
14.0.4
14.0.5
14.0.6
15.*
15.0.0
15.0.1
15.0.2
15.0.3
15.1.0
15.2.0
16.*
16.0.0
16.1.0
16.2.0
16.3.0
16.3.1.dev0
16.4.0
16.4.1
16.4.3
16.4.4.dev0
16.5.0
16.6.0
16.6.1
16.6.2
16.7.0
16.7.1
16.7.2
16.7.3
16.7.4
16.7.5
16.7.6
16.7.7
16.7.8
16.7.9
16.7.10
16.7.11
16.7.12
20.*
20.0.0b1
20.0.0b2
20.0.0
20.0.1
20.0.2
20.0.3
20.0.4
20.0.5
20.0.6
20.0.7
20.0.8
20.0.9
20.0.10
20.0.11
20.0.12
20.0.13
20.0.14
20.0.15
20.0.16
20.0.17
20.0.18
20.0.19
20.0.20
20.0.21
20.0.22
20.0.23
20.0.24
20.0.25
20.0.26
20.0.27
20.0.28
20.0.29
20.0.30
20.0.31
20.0.32
20.0.33
20.0.34
20.0.35
20.1.0
20.2.0
20.2.1
20.2.2
20.3.0
20.3.1
20.4.0
20.4.1
20.4.2
20.4.3
20.4.4
20.4.5
20.4.6
20.4.7
20.5.0
20.6.0
20.7.0
20.7.1
20.7.2
20.8.0
20.8.1
20.9.0
20.10.0
20.11.0
20.11.1
20.11.2
20.12.0
20.12.1
20.13.0
20.13.1
20.13.2
20.13.3
20.13.4
20.14.0
20.14.1
20.15.0
20.15.1
20.16.0
20.16.1
20.16.2
20.16.3
20.16.4
20.16.5
20.16.6
20.16.7
20.17.0
20.17.1
20.18.0
20.19.0
20.20.0
20.21.0
20.21.1
20.22.0
20.23.0
20.23.1
20.24.0
20.24.1
20.24.2
20.24.3
20.24.4
20.24.5
20.24.6
20.24.7
20.25.0
20.25.1
20.25.2
20.25.3
20.26.0
20.26.1
20.26.2
20.26.3
20.26.4
20.26.5
20.26.6
20.27.0
20.27.1
20.28.0
20.28.1
20.29.0
20.29.1
20.29.2
20.29.3
20.30.0
20.31.0
20.31.1
20.31.2
20.32.0
20.33.0
20.33.1
20.34.0
20.35.0
20.35.1
20.35.2
20.35.3
20.35.4
20.36.0
20.36.1
20.38.0
20.39.0
20.39.1
21.*
21.0.0
21.1.0
21.2.0
21.2.1
21.2.2
21.2.3
21.2.4
21.3.0
21.3.1
21.3.2
21.3.3
21.4.0
21.4.1
21.4.2
21.4.3
21.5.0
21.5.1
21.5.2
21.6.0
21.6.1
21.7.0
21.7.1
21.7.2
21.7.3
21.7.4
21.7.5
21.7.6
21.7.7
21.7.8
21.7.9
21.7.10
21.7.11
21.7.12
21.7.13
21.7.14
21.7.15
21.7.16
21.8.1
21.9.0
21.9.1
21.10.0
21.11.0
21.11.1
21.12.0
21.12.1
21.13.0
21.14.0
21.14.1

Database specific

last_known_affected_version_range
"<= 21.14.1"
source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-c947-3pg5-gm8q/GHSA-c947-3pg5-gm8q.json"