CVE-2026-113718
virtualenv: Xonsh activation literals depend on the script decoding codec
virtualenv is a tool for creating isolated virtual python environments. Prior to 21.14.9, POSIX xonsh activation quote() uses repr() to write printable non-ASCII prompt or destination data into UTF-8 activate.xsh, while xonsh can read that script using $XONSH_ENCODING. Under a legacy multibyte codec such as GBK or Big5, a UTF-8 trail byte can consume the backslash before an adjacent quote, allowing the literal to close and attacker-influenced statements to execute when the user sources the generated script. This issue is fixed in version 21.14.9.
Attack profile
How easy it is to exploit
- Attack vector
- Local
- Complexity
- High
- Privileges needed
- None
- User interaction
- Active
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
7.1
virtualenv: Xonsh activation literals depend on the script decoding codec
virtualenv is a tool for creating isolated virtual python environments. Prior to 21.14.9, POSIX xonsh activation quote() uses repr() to write printable non-ASCII prompt or destination data into UTF-8 activate.xsh, while xonsh can read that script using $XONSH_ENCODING. Under a legacy multibyte codec such as GBK or Big5, a UTF-8 trail byte can consume the backslash before an adjacent quote, allowing the literal to close and attacker-influenced statements to execute when the user sources the generated script. This issue is fixed in version 21.14.9.
- Record
CVE-2026-113718- CVSS 4.0
- 7.1 High
CVSS:4.0/AV:L/AC:H/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-94
- Updated
- 2026-11-02
EUVDEUVD-2026-105299
7.1
virtualenv is a tool for creating isolated virtual python environments. Prior to 21.14.9, POSIX xonsh activation quote() uses repr() to write printable non-ASCII prompt or destination data into UTF-8 activate.xsh, while xonsh can read that script using $XONSH_ENCODING. Under a legacy multibyte codec such as GBK or Big5, a UTF-8 trail byte can consume the backslash before an adjacent quote, allowing the literal to close and attacker-influenced statements to execute when the user sources the generated script. This issue is fixed in version 21.14.9.
- Record
EUVD-2026-105299- CVSS 4.0
- 7.1 High
CVSS:4.0/AV:L/AC:H/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-394h-qwmc-48pf
7.1
virtualenv: Xonsh activation literals depend on the script decoding codec
Summary
Caller-supplied prompt text can become executable syntax in the xonsh activation script. An attacker must influence the value passed to virtualenv, and a user must subsequently activate the environment.
Affected area
Xonsh reads a UTF-8 activation script using a legacy multibyte encoding such as GBK. Printable non-ASCII bytes can change how the reader recognizes an adjacent quote. The report concerns POSIX activation. It does not establish exposure through unrelated activators.
Attacker-controlled input
The attacker controls prompt or destination data passed as a virtualenv argument. The user later sources the generated activation script.
Affected code
The relevant 21.14.8 source is in xonsh quote(), UTF-8 template writer.
Mechanism
The generator writes activate.xsh as UTF-8. Its quote() used repr(), which leaves printable non-ASCII characters
in the file and backslash-escapes an embedded quote. Xonsh's source reads the file using $XONSH_ENCODING. With GBK
or Big5, the UTF-8 bytes of 中 end in 0xad, which pairs with the following 0x5c backslash as one decoded character.
The backslash no longer escapes the quote. A prompt containing both quote kinds can then close its Python string literal
and supply statements that run during activation. With UTF-8 source decoding, the same value stays inside the literal.
Reproduction and evidence
The original scanner finding, ANT-2026-PAUVP7YL, demonstrated this byte-level failure in activate_this.py: a hostile
prompt loaded through exec(open(file).read(), ...) under GBK created a marker, while UTF-8 and runpy.run_path
controls did not. The xonsh path in this advisory was identified in the subsequent maintainer-provided review.
PR #3432 shows the xonsh source-decoding chain and changes quote() to
ascii(), which writes non-ASCII characters as escapes. Its regression test encodes the generated literal as ASCII,
decodes it as GBK, and checks that ast.literal_eval returns the original prompt.
The attack needs control of the prompt or destination value, an affected xonsh source encoding, and later sourcing of
the generated file. The original activate_this.py reproducer does not itself prove xonsh execution; that result is
attributed to the separate review. Existing activate.xsh files must be regenerated after the fix.
Attack sequence
sequenceDiagram
participant A as Prompt supplier
participant V as virtualenv quote()
participant F as activate.xsh bytes
participant X as xonsh source
A->>V: 中 plus escaped quote and statements
V->>F: repr writes UTF-8 中 followed by backslash
alt XONSH_ENCODING is UTF-8
F->>X: backslash remains an escape
X-->>A: prompt remains data
else XONSH_ENCODING is GBK or Big5
F->>X: decoder consumes backslash as trail byte
X->>X: quote closes and statements run
end
Note over V,X: ascii() emits only ASCII bytes and preserves the literal
Reproducer files
The following files are from the scanner report for ANT-2026-PAUVP7YL. They were tested against commit a857a7823c73
in the scanner image. The repro entrypoint expects companion files under /tmp/repro.d; cases that change user IDs
need a disposable root-capable container. The last output line is BUG when the reported behavior occurs. These files
are included as evidence and were not rerun for this advisory update.
repro
#!/usr/bin/env python3
import os
import subprocess
import sys
from pathlib import Path
from shutil import rmtree
work = Path("/tmp/activate-this-gbk")
rmtree(work, ignore_errors=True)
work.mkdir()
env_dir = work / "venv"…
- Record
GHSA-394h-qwmc-48pf- CVSS 4.0
- 7.1 High
CVSS:4.0/AV:L/AC:H/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-94
- Updated
- 2026-11-02
NVD
7.1
virtualenv is a tool for creating isolated virtual python environments. Prior to 21.14.9, POSIX xonsh activation quote() uses repr() to write printable non-ASCII prompt or destination data into UTF-8 activate.xsh, while xonsh can read that script using $XONSH_ENCODING. Under a legacy multibyte codec such as GBK or Big5, a UTF-8 trail byte can consume the backslash before an adjacent quote, allowing the literal to close and attacker-influenced statements to execute when the user sources the generated script. This issue is fixed in version 21.14.9.
- Record
CVE-2026-113718- CVSS 4.0
- 7.1 High
CVSS:4.0/AV:L/AC:H/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - Weakness
- CWE-94
- Updated
- 2026-11-02
OSV
7.1
virtualenv: Xonsh activation literals depend on the script decoding codec
virtualenv is a tool for creating isolated virtual python environments. Prior to 21.14.9, POSIX xonsh activation quote() uses repr() to write printable non-ASCII prompt or destination data into UTF-8 activate.xsh, while xonsh can read that script using $XONSH_ENCODING. Under a legacy multibyte codec such as GBK or Big5, a UTF-8 trail byte can consume the backslash before an adjacent quote, allowing the literal to close and attacker-influenced statements to execute when the user sources the generated script. This issue is fixed in version 21.14.9.
- Record
CVE-2026-113718- CVSS 4.0
- 7.1 High
CVSS:4.0/AV:L/AC:H/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-94
- Updated
- 2026-11-02
OSVDEBIAN-CVE-2026-113718
7.1
virtualenv is a tool for creating isolated virtual python environments. Prior to 21.14.9, POSIX xonsh activation quote() uses repr() to write printable non-ASCII prompt or destination data into UTF-8 activate.xsh, while xonsh can read that script using $XONSH_ENCODING. Under a legacy multibyte codec such as GBK or Big5, a UTF-8 trail byte can consume the backslash before an adjacent quote, allowing the literal to close and attacker-influenced statements to execute when the user sources the generated script. This issue is fixed in version 21.14.9.
- Record
DEBIAN-CVE-2026-113718- CVSS 4.0
- 7.1 High
CVSS:4.0/AV:L/AC:H/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - Updated
- 2026-11-02
Show 6 moreShow less
OSVGHSA-394h-qwmc-48pf
7.1
virtualenv: Xonsh activation literals depend on the script decoding codec
Summary
Caller-supplied prompt text can become executable syntax in the xonsh activation script. An attacker must influence the value passed to virtualenv, and a user must subsequently activate the environment.
Affected area
Xonsh reads a UTF-8 activation script using a legacy multibyte encoding such as GBK. Printable non-ASCII bytes can change how the reader recognizes an adjacent quote. The report concerns POSIX activation. It does not establish exposure through unrelated activators.
Attacker-controlled input
The attacker controls prompt or destination data passed as a virtualenv argument. The user later sources the generated activation script.
Affected code
The relevant 21.14.8 source is in xonsh quote(), UTF-8 template writer.
Mechanism
The generator writes activate.xsh as UTF-8. Its quote() used repr(), which leaves printable non-ASCII characters
in the file and backslash-escapes an embedded quote. Xonsh's source reads the file using $XONSH_ENCODING. With GBK
or Big5, the UTF-8 bytes of 中 end in 0xad, which pairs with the following 0x5c backslash as one decoded character.
The backslash no longer escapes the quote. A prompt containing both quote kinds can then close its Python string literal
and supply statements that run during activation. With UTF-8 source decoding, the same value stays inside the literal.
Reproduction and evidence
The original scanner finding, ANT-2026-PAUVP7YL, demonstrated this byte-level failure in activate_this.py: a hostile
prompt loaded through exec(open(file).read(), ...) under GBK created a marker, while UTF-8 and runpy.run_path
controls did not. The xonsh path in this advisory was identified in the subsequent maintainer-provided review.
PR #3432 shows the xonsh source-decoding chain and changes quote() to
ascii(), which writes non-ASCII characters as escapes. Its regression test encodes the generated literal as ASCII,
decodes it as GBK, and checks that ast.literal_eval returns the original prompt.
The attack needs control of the prompt or destination value, an affected xonsh source encoding, and later sourcing of
the generated file. The original activate_this.py reproducer does not itself prove xonsh execution; that result is
attributed to the separate review. Existing activate.xsh files must be regenerated after the fix.
Attack sequence
sequenceDiagram
participant A as Prompt supplier
participant V as virtualenv quote()
participant F as activate.xsh bytes
participant X as xonsh source
A->>V: 中 plus escaped quote and statements
V->>F: repr writes UTF-8 中 followed by backslash
alt XONSH_ENCODING is UTF-8
F->>X: backslash remains an escape
X-->>A: prompt remains data
else XONSH_ENCODING is GBK or Big5
F->>X: decoder consumes backslash as trail byte
X->>X: quote closes and statements run
end
Note over V,X: ascii() emits only ASCII bytes and preserves the literal
Reproducer files
The following files are from the scanner report for ANT-2026-PAUVP7YL. They were tested against commit a857a7823c73
in the scanner image. The repro entrypoint expects companion files under /tmp/repro.d; cases that change user IDs
need a disposable root-capable container. The last output line is BUG when the reported behavior occurs. These files
are included as evidence and were not rerun for this advisory update.
repro
#!/usr/bin/env python3
import os
import subprocess
import sys
from pathlib import Path
from shutil import rmtree
work = Path("/tmp/activate-this-gbk")
rmtree(work, ignore_errors=True)
work.mkdir()
env_dir = work / "venv"…
- Record
GHSA-394h-qwmc-48pf- CVSS 4.0
- 7.1 High
CVSS:4.0/AV:L/AC:H/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-94
- Updated
- 2026-11-02
OSVUBUNTU-CVE-2026-113718
7.1
virtualenv is a tool for creating isolated virtual python environments. Prior to 21.14.9, POSIX xonsh activation quote() uses repr() to write printable non-ASCII prompt or destination data into UTF-8 activate.xsh, while xonsh can read that script using $XONSH_ENCODING. Under a legacy multibyte codec such as GBK or Big5, a UTF-8 trail byte can consume the backslash before an adjacent quote, allowing the literal to close and attacker-influenced statements to execute when the user sources the generated script. This issue is fixed in version 21.14.9.
- Record
UBUNTU-CVE-2026-113718- CVSS 4.0
- 7.1 High
CVSS:4.0/AV:L/AC:H/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Updated
- 2026-11-02
OSVAZL-112589 No score
CVE-2026-113718 affecting package python-virtualenv 20.36.1-9
virtualenv is a tool for creating isolated virtual python environments. Prior to 21.14.9, POSIX xonsh activation quote() uses repr() to write printable non-ASCII prompt or destination data into UTF-8 activate.xsh, while xonsh can read that script using $XONSH_ENCODING. Under a legacy multibyte codec such as GBK or Big5, a UTF-8 trail byte can consume the backslash before an adjacent quote, allowing the literal to close and attacker-influenced statements to execute when the user sources the generated script. This issue is fixed in version 21.14.9.
- Record
AZL-112589- Updated
- 2026-11-03
OSVBIT-virtualenv-2026-113718 No score
virtualenv: Xonsh activation literals depend on the script decoding codec
virtualenv is a tool for creating isolated virtual python environments. Prior to 21.14.9, POSIX xonsh activation quote() uses repr() to write printable non-ASCII prompt or destination data into UTF-8 activate.xsh, while xonsh can read that script using $XONSH_ENCODING. Under a legacy multibyte codec such as GBK or Big5, a UTF-8 trail byte can consume the backslash before an adjacent quote, allowing the literal to close and attacker-influenced statements to execute when the user sources the generated script. This issue is fixed in version 21.14.9.
- Record
BIT-virtualenv-2026-113718- Updated
- 2026-11-02
OSVopenSUSE-SU-2026:12372-1 No score
python313-virtualenv-21.15.1-1.1 on GA media
These are all security issues fixed in the python313-virtualenv-21.15.1-1.1 package on the GA media of openSUSE Tumbleweed.
- Record
openSUSE-SU-2026:12372-1- Updated
- 2026-11-02
OSVROOT-APP-PYPI-CVE-2026-113718 No score
CVE-2026-113718 in virtualenv - Patched by Root
Root has patched CVE-2026-113718 in the virtualenv package for Root:PyPI. Multiple fixed versions available.
- Record
ROOT-APP-PYPI-CVE-2026-113718- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
virtualenvPyPI |
before 21.14.9 | 21.14.9 |
python-virtualenvAzure Linux:3 |
through 20.36.1-9 | None known |
virtualenvBitnami |
before 21.14.9 | 21.14.9 |
python-virtualenvDebian:12 |
All versions, plus listed versions 20.17.1+ds-120.19.0+ds-120.21.0+ds-120.23.0+ds-120.23.0+ds-2 Show 28 moreShow less20.24.1+ds-120.24.6+ds-120.24.6+ds-220.25.0+ds-120.25.0+ds-220.25.1+ds-120.26.1+ds-120.26.2+ds-120.26.6+ds-120.27.0+ds-120.28.0+ds-120.29.1+ds-120.29.3+ds-120.30.0+ds-120.30.0+ds-220.30.0+ds-320.31.2+ds-120.33.1+ds-120.34.0+ds-120.35.3+ds-120.35.4+ds-120.36.1+ds-120.38.0+ds-121.2.0+ds-121.2.4+ds-121.3.1+ds-121.4.1+ds-121.5.1+ds-1 |
None known |
python-virtualenvDebian:13 |
All versions, plus listed versions 20.31.2+ds-120.31.2+ds-1+deb13u120.33.1+ds-120.34.0+ds-120.35.3+ds-1 Show 8 moreShow less20.35.4+ds-120.36.1+ds-120.38.0+ds-121.2.0+ds-121.2.4+ds-121.3.1+ds-121.4.1+ds-121.5.1+ds-1 |
None known |
python-virtualenvDebian:14 |
All versions, plus listed versions 20.31.2+ds-120.33.1+ds-120.34.0+ds-120.35.3+ds-120.35.4+ds-1 Show 7 moreShow less20.36.1+ds-120.38.0+ds-121.2.0+ds-121.2.4+ds-121.3.1+ds-121.4.1+ds-121.5.1+ds-1 |
None known |
virtualenvPyPI |
before 21.14.9, plus listed versions 0.80.8.10.8.20.8.30.8.4 Show 45 moreShow less0.90.9.10.9.21.01.11.101.10.11.111.11.11.11.21.11.31.11.41.11.51.11.61.21.31.3.11.3.21.3.31.3.41.41.4.11.4.21.4.31.4.41.4.51.4.61.4.71.4.81.4.91.4rc11.51.5.11.5.21.61.6.11.6.21.6.31.6.41.71.7.11.7.1.11.7.1.21.7.21.8 |
21.14.9 |
virtualenvRoot:PyPI |
before 21.12.1+aikido.2 | 21.12.1+aikido.221.9.0+aikido.321.7.5+aikido.521.7.1+aikido.421.12.1+aikido.321.3.2+aikido.4 |
python-virtualenvUbuntu:14.04:LTS |
All versions, plus listed versions 1.10.1-11.11-11.11-21.11.4-11.11.4-1ubuntu1 |
None known |
python-virtualenvUbuntu:16.04:LTS |
All versions, plus listed versions 1.11.6+ds-114.0.5+ds-114.0.5+ds-214.0.5+ds-415.0.0+ds-1 Show 6 moreShow less15.0.0+ds-215.0.1+ds-115.0.1+ds-215.0.1+ds-315.0.1+ds-3ubuntu115.0.1+ds-3ubuntu1.1 |
None known |
Show 7 moreShow less
| Package | Affected | Fixed |
|---|---|---|
python-virtualenvUbuntu:18.04:LTS |
All versions, plus listed versions 15.1.0+ds-115.1.0+ds-1.1 |
None known |
python-virtualenvUbuntu:Pro:20.04:LTS |
All versions, plus listed versions 15.1.0+ds-215.1.0+ds-2build115.1.0+ds-2ubuntu120.0.13-120.0.17-120.0.17-1ubuntu0.320.0.17-1ubuntu0.420.0.17-1ubuntu0.4+esm1 |
None known |
python-virtualenvUbuntu:Pro:22.04:LTS |
All versions, plus listed versions 20.4.6+ds-220.10.0+ds-120.12.1+ds-120.13.0+ds-120.13.0+ds-220.13.0+ds-2ubuntu0.1~esm1 |
None known |
python-virtualenvUbuntu:Pro:24.04:LTS |
All versions, plus listed versions 20.24.1+ds-120.24.6+ds-120.24.6+ds-220.25.0+ds-120.25.0+ds-220.25.0+ds-2ubuntu0.1~esm1 |
None known |
python-virtualenvUbuntu:26.10 |
All versions, plus listed versions 20.36.1+ds-121.4.1+ds-121.5.1+ds-1 |
None known |
python-virtualenvUbuntu:26.04:LTS |
All versions, plus listed versions 20.31.2+ds-120.35.3+ds-120.35.4+ds-120.36.1+ds-1 |
None known |
python-virtualenvopenSUSE:Tumbleweed From an advisory covering 9 CVEs |
before 21.15.1-1.1 | 21.15.1-1.1 |
History
| Recorded | Changed | Sources |
|---|---|---|
| affected, facts | ||
| affected, aliases | OSV | |
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-113718 is a high vulnerability (CVSS 7.1) in Pypa Virtualenv, published October 20, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.24%, the 15th percentile. Fixed in virtualenv 21.14.9.
References
github.com/pypa/virtualenv/security/advisories/GHSA-394h-qwmc-48pf
github.com/pypa/virtualenv/pull/3432
github.com/pypa/virtualenv/commit/e5fc2e6e189a877ff559af288919e3525d13e5e0
github.com/pypa/virtualenv/releases/tag/21.14.9
nvd.nist.gov/vuln/detail/CVE-2026-113718
github.com/advisories/GHSA-394h-qwmc-48pf
Show 14 moreShow less
github.com/CVEProject/cvelistV5/tree/main/cves/2026/113xxx/CVE-2026-113718.json
security-tracker.debian.org/tracker/CVE-2026-113718
github.com/pypa/virtualenv
ubuntu.com/security/CVE-2026-113718
cve.org/CVERecord?id=CVE-2026-113718
suse.com/security/cve/CVE-2026-113714
suse.com/security/cve/CVE-2026-113716
suse.com/security/cve/CVE-2026-113718
suse.com/security/cve/CVE-2026-113720
suse.com/security/cve/CVE-2026-113722
suse.com/security/cve/CVE-2026-113724
suse.com/security/cve/CVE-2026-113726
suse.com/security/cve/CVE-2026-113732
suse.com/security/cve/CVE-2026-115586
Left out here: 254 versions and the rest of 2 source descriptions. The JSON record has them.