{"id":"CVE-2026-102938","aliases":["AZL-105672","BIT-virtualenv-2026-102938","CLSA-2026-1791452380","DEBIAN-CVE-2026-102938","EUVD-2026-89465","GHSA-9h9j-4vrj-gf7g","PYSEC-2026-4012","SUSE-SU-2026:24243-1","SUSE-SU-2026:4652-1","UBUNTU-CVE-2026-102938","openSUSE-SU-2026:11974-1","openSUSE-SU-2026:22100-1"],"status":"published","title":"virtualenv writes prompt values into pyvenv.cfg without sanitizing line boundaries, allowing configuration injection","description":"virtualenv is a tool for creating isolated virtual python environments. Prior to 21.7.11, PyEnvCfg.write() writes prompt values verbatim to the line-oriented pyvenv.cfg format while PyEnvCfg._read_values() parses the file with str.splitlines() and accepts the last value for duplicate keys. An attacker who influences --prompt, VIRTUALENV_PROMPT, or configuration input can insert a recognized line boundary and additional keys, including home, causing consumers to use an attacker-selected base interpreter or corrupted environment metadata. The security impact requires prompt input from outside the operator's trust boundary; directly supplied prompt content primarily corrupts the operator's own environment. This issue is fixed in version 21.7.11.","severity":{"version":"4.0","score":5.8,"vector":"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","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-12","score":0.00146,"percentile":0.03922,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-93"],"published":"2026-09-17T16:42:47Z","modified":"2026-11-07T14:15:22Z","fixes":[{"ecosystem":"PyPI","package":"virtualenv","fixed_in":["21.7.11"],"sources":["ghsa","osv"]},{"ecosystem":"Azure Linux:3","package":"python-virtualenv","fixed_in":["20.36.1-10"],"sources":["osv"]},{"ecosystem":"Bitnami","package":"virtualenv","fixed_in":["21.7.11"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"21.7.10"},{"fixed":"21.7.11"}]}]},{"source":"osv","ecosystem":"Azure Linux:3","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"20.36.1-10"}]}]},{"source":"osv","ecosystem":"Bitnami","package":"virtualenv","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"21.7.11"}]}]},{"source":"osv","ecosystem":"TuxCare:PyPI","package":"virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"20.39.1"},{"fixed":"20.39.1.post2+tuxcare"}]}],"versions":["20.39.1","20.39.1.post1+tuxcare"],"bundled":4},{"source":"osv","ecosystem":"Debian:12","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["20.17.1+ds-1","20.19.0+ds-1","20.21.0+ds-1","20.23.0+ds-1","20.23.0+ds-2","20.24.1+ds-1","20.24.6+ds-1","20.24.6+ds-2","20.25.0+ds-1","20.25.0+ds-2","20.25.1+ds-1","20.26.1+ds-1","20.26.2+ds-1","20.26.6+ds-1","20.27.0+ds-1","20.28.0+ds-1","20.29.1+ds-1","20.29.3+ds-1","20.30.0+ds-1","20.30.0+ds-2","20.30.0+ds-3","20.31.2+ds-1","20.33.1+ds-1","20.34.0+ds-1","20.35.3+ds-1","20.35.4+ds-1","20.36.1+ds-1","20.38.0+ds-1","21.2.0+ds-1","21.2.4+ds-1","21.3.1+ds-1","21.4.1+ds-1","21.5.1+ds-1"]},{"source":"osv","ecosystem":"Debian:13","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["20.31.2+ds-1","20.31.2+ds-1+deb13u1","20.33.1+ds-1","20.34.0+ds-1","20.35.3+ds-1","20.35.4+ds-1","20.36.1+ds-1","20.38.0+ds-1","21.2.0+ds-1","21.2.4+ds-1","21.3.1+ds-1","21.4.1+ds-1","21.5.1+ds-1"]},{"source":"osv","ecosystem":"Debian:14","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["20.31.2+ds-1","20.33.1+ds-1","20.34.0+ds-1","20.35.3+ds-1","20.35.4+ds-1","20.36.1+ds-1","20.38.0+ds-1","21.2.0+ds-1","21.2.4+ds-1","21.3.1+ds-1","21.4.1+ds-1","21.5.1+ds-1"]},{"source":"osv","ecosystem":"PyPI","package":"virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"21.7.11"}]}],"versions":["0.8","0.8.1","0.8.2","0.8.3","0.8.4","0.9","0.9.1","0.9.2","1.0","1.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","1.2","1.3","1.3.1","1.3.2","1.3.3","1.3.4","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.4rc1","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","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.0.0","13.0.1","13.0.2","13.0.3","13.1.0","13.1.1","13.1.2","14.0.0","14.0.1","14.0.2","14.0.3","14.0.4","14.0.5","14.0.6","15.0.0","15.0.1","15.0.2","15.0.3","15.1.0","15.2.0","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.10","16.7.11","16.7.12","16.7.2","16.7.3","16.7.4","16.7.5","16.7.6","16.7.7","16.7.8","16.7.9","20.0.0","20.0.0b1","20.0.0b2","20.0.1","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.2","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.3","20.0.30","20.0.31","20.0.32","20.0.33","20.0.34","20.0.35","20.0.4","20.0.5","20.0.6","20.0.7","20.0.8","20.0.9","20.1.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.2.0","20.2.1","20.2.2","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.3.0","20.3.1","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","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","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.10","21.7.2","21.7.3","21.7.4","21.7.5","21.7.6","21.7.7","21.7.8","21.7.9"]},{"source":"osv","ecosystem":"PyPI","package":"virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"21.7.11"}]}],"versions":["0.8","0.8.1","0.8.2","0.8.3","0.8.4","0.9","0.9.1","0.9.2","1.0","1.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","1.2","1.3","1.3.1","1.3.2","1.3.3","1.3.4","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.4rc1","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","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.0.0","13.0.1","13.0.2","13.0.3","13.1.0","13.1.1","13.1.2","14.0.0","14.0.1","14.0.2","14.0.3","14.0.4","14.0.5","14.0.6","15.0.0","15.0.1","15.0.2","15.0.3","15.1.0","15.2.0","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.10","16.7.11","16.7.12","16.7.2","16.7.3","16.7.4","16.7.5","16.7.6","16.7.7","16.7.8","16.7.9","20.0.0","20.0.0b1","20.0.0b2","20.0.1","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.2","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.3","20.0.30","20.0.31","20.0.32","20.0.33","20.0.34","20.0.35","20.0.4","20.0.5","20.0.6","20.0.7","20.0.8","20.0.9","20.1.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.2.0","20.2.1","20.2.2","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.3.0","20.3.1","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","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","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.10","21.7.2","21.7.3","21.7.4","21.7.5","21.7.6","21.7.7","21.7.8","21.7.9"]},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server 16.0","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"20.29.3-160000.4.1"}]}],"bundled":2},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server for SAP applications 16.0","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"20.29.3-160000.4.1"}]}],"bundled":2},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Module for Python 3 15 SP7","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"20.22.0-150400.9.12.1"}]}],"bundled":2},{"source":"osv","ecosystem":"SUSE:Linux Enterprise High Performance Computing 15 SP4-ESPOS","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"20.22.0-150400.9.12.1"}]}],"bundled":2},{"source":"osv","ecosystem":"SUSE:Linux Enterprise High Performance Computing 15 SP4-LTSS","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"20.22.0-150400.9.12.1"}]}],"bundled":2},{"source":"osv","ecosystem":"SUSE:Linux Enterprise High Performance Computing 15 SP5-ESPOS","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"20.22.0-150400.9.12.1"}]}],"bundled":2},{"source":"osv","ecosystem":"SUSE:Linux Enterprise High Performance Computing 15 SP5-LTSS","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"20.22.0-150400.9.12.1"}]}],"bundled":2},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server 15 SP4-LTSS","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"20.22.0-150400.9.12.1"}]}],"bundled":2},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server 15 SP5-LTSS","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"20.22.0-150400.9.12.1"}]}],"bundled":2},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server 15 SP6-LTSS","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"20.22.0-150400.9.12.1"}]}],"bundled":2},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server for SAP Applications 15 SP4","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"20.22.0-150400.9.12.1"}]}],"bundled":2},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server for SAP Applications 15 SP5","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"20.22.0-150400.9.12.1"}]}],"bundled":2},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server for SAP Applications 15 SP6","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"20.22.0-150400.9.12.1"}]}],"bundled":2},{"source":"osv","ecosystem":"Ubuntu:14.04:LTS","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.10.1-1","1.11-1","1.11-2","1.11.4-1","1.11.4-1ubuntu1"]},{"source":"osv","ecosystem":"Ubuntu:16.04:LTS","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.11.6+ds-1","14.0.5+ds-1","14.0.5+ds-2","14.0.5+ds-4","15.0.0+ds-1","15.0.0+ds-2","15.0.1+ds-1","15.0.1+ds-2","15.0.1+ds-3","15.0.1+ds-3ubuntu1","15.0.1+ds-3ubuntu1.1"]},{"source":"osv","ecosystem":"Ubuntu:18.04:LTS","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["15.1.0+ds-1","15.1.0+ds-1.1"]},{"source":"osv","ecosystem":"Ubuntu:Pro:20.04:LTS","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["15.1.0+ds-2","15.1.0+ds-2build1","15.1.0+ds-2ubuntu1","20.0.13-1","20.0.17-1","20.0.17-1ubuntu0.3","20.0.17-1ubuntu0.4","20.0.17-1ubuntu0.4+esm1"]},{"source":"osv","ecosystem":"Ubuntu:Pro:22.04:LTS","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["20.4.6+ds-2","20.10.0+ds-1","20.12.1+ds-1","20.13.0+ds-1","20.13.0+ds-2","20.13.0+ds-2ubuntu0.1~esm1"]},{"source":"osv","ecosystem":"Ubuntu:Pro:24.04:LTS","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["20.24.1+ds-1","20.24.6+ds-1","20.24.6+ds-2","20.25.0+ds-1","20.25.0+ds-2","20.25.0+ds-2ubuntu0.1~esm1"]},{"source":"osv","ecosystem":"Ubuntu:26.10","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["20.36.1+ds-1","21.4.1+ds-1","21.5.1+ds-1"]},{"source":"osv","ecosystem":"Ubuntu:26.04:LTS","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["20.31.2+ds-1","20.35.3+ds-1","20.35.4+ds-1","20.36.1+ds-1"]},{"source":"osv","ecosystem":"openSUSE:Tumbleweed","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"21.14.2-1.1"}]}],"bundled":4},{"source":"osv","ecosystem":"openSUSE:Leap 16.0","package":"python-virtualenv","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"20.29.3-160000.4.1"}]}],"bundled":2}],"products":[{"vendor":"pypa","product":"virtualenv"}],"references":[{"url":"https://github.com/pypa/virtualenv/security/advisories/GHSA-9h9j-4vrj-gf7g","tags":["x_refsource_CONFIRM","web","advisory","report"]},{"url":"https://github.com/pypa/virtualenv/pull/3247","tags":["x_refsource_MISC","web","fix","report"]},{"url":"https://github.com/pypa/virtualenv/commit/a30f995461043acb6cacbf3a890951563ccf7140","tags":["x_refsource_MISC","web","fix","report"]},{"url":"https://github.com/pypa/virtualenv/releases/tag/21.7.11","tags":["x_refsource_MISC","web","report"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-102938","tags":["web","advisory"]},{"url":"https://github.com/pypa/advisory-database/tree/main/vulns/virtualenv/PYSEC-2026-4012.yaml","tags":["web"]},{"url":"https://pypi.org/project/virtualenv","tags":["web","package"]},{"url":"https://github.com/advisories/GHSA-9h9j-4vrj-gf7g"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/102xxx/CVE-2026-102938.json","tags":["advisory"]},{"url":"https://security-tracker.debian.org/tracker/CVE-2026-102938","tags":["advisory"]},{"url":"https://github.com/pypa/virtualenv","tags":["package"]},{"url":"https://www.suse.com/support/update/announcement/2026/suse-su-202624243-1/","tags":["advisory"]},{"url":"https://bugzilla.suse.com/1283890","tags":["report"]},{"url":"https://bugzilla.suse.com/1283904","tags":["report"]},{"url":"https://www.suse.com/security/cve/CVE-2026-102930","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-102938","tags":["web"]},{"url":"https://www.suse.com/support/update/announcement/2026/suse-su-20264652-1/","tags":["advisory"]},{"url":"https://ubuntu.com/security/CVE-2026-102938","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-102938","tags":["report"]},{"url":"","tags":["advisory"]},{"url":"https://www.suse.com/security/cve/CVE-2024-9287","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-102925","tags":["web"]}],"sources":{"cve":[{"id":"CVE-2026-102938","title":"virtualenv writes prompt values into pyvenv.cfg without sanitizing line boundaries, allowing configuration injection","description":"virtualenv is a tool for creating isolated virtual python environments. Prior to 21.7.11, PyEnvCfg.write() writes prompt values verbatim to the line-oriented pyvenv.cfg format while PyEnvCfg._read_values() parses the file with str.splitlines() and accepts the last value for duplicate keys. An attacker who influences --prompt, VIRTUALENV_PROMPT, or configuration input can insert a recognized line boundary and additional keys, including home, causing consumers to use an attacker-selected base interpreter or corrupted environment metadata. The security impact requires prompt input from outside the operator's trust boundary; directly supplied prompt content primarily corrupts the operator's own environment. This issue is fixed in version 21.7.11.","status":"published","published":"2026-09-29T20:58:20.696Z","modified":"2026-09-30T19:53:20.817Z","cvss":[{"version":"4.0","score":5.8,"vector":"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","level":"medium","assessor":"cna"}],"cwes":["CWE-93"],"updated_at":"2026-11-02T13:38:54.394896Z"}],"euvd":[{"id":"EUVD-2026-89465","description":"virtualenv is a tool for creating isolated virtual python environments. Prior to 21.7.11, PyEnvCfg.write() writes prompt values verbatim to the line-oriented pyvenv.cfg format while PyEnvCfg._read_values() parses the file with str.splitlines() and accepts the last value for duplicate keys. An attacker who influences --prompt, VIRTUALENV_PROMPT, or configuration input can insert a recognized line boundary and additional keys, including home, causing consumers to use an attacker-selected base interpreter or corrupted environment metadata. The security impact requires prompt input from outside the operator's trust boundary; directly supplied prompt content primarily corrupts the operator's own environment. This issue is fixed in version 21.7.11.","status":"published","published":"2026-09-29T20:58:20Z","modified":"2026-09-30T19:53:20Z","cvss":[{"version":"4.0","score":5.8,"vector":"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","level":"medium"}],"updated_at":"2026-11-02T17:27:47.293232Z"}],"ghsa":[{"id":"GHSA-9h9j-4vrj-gf7g","title":"virtualenv writes prompt values into pyvenv.cfg without sanitizing line boundaries, allowing configuration injection","description":"### Summary\n\n`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.\n\n### Impact\n\nThe `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`:\n\n```console\n$ virtualenv --prompt $'x\"\\nhome = /attacker/path\\nprompt = \"z' venv\n$ grep '^home' venv/pyvenv.cfg\nhome = /attacker/path\n```\n\n`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.\n\nThis 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.\n\n### Details\n\nThe 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.\n\n### Patches\n\n`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`.\n\n### Workarounds\n\nDo not pass externally influenced data as the virtualenv prompt. Strip line boundaries from any value before using it as `--prompt` or `VIRTUALENV_PROMPT`.","status":"published","published":"2026-09-30T23:53:58Z","modified":"2026-09-30T23:53:59Z","cvss":[{"version":"4.0","score":5.8,"vector":"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","level":"medium"}],"cwes":["CWE-93"],"updated_at":"2026-11-02T14:41:23.783773Z"}],"nvd":[{"id":"CVE-2026-102938","description":"virtualenv is a tool for creating isolated virtual python environments. Prior to 21.7.11, PyEnvCfg.write() writes prompt values verbatim to the line-oriented pyvenv.cfg format while PyEnvCfg._read_values() parses the file with str.splitlines() and accepts the last value for duplicate keys. An attacker who influences --prompt, VIRTUALENV_PROMPT, or configuration input can insert a recognized line boundary and additional keys, including home, causing consumers to use an attacker-selected base interpreter or corrupted environment metadata. The security impact requires prompt input from outside the operator's trust boundary; directly supplied prompt content primarily corrupts the operator's own environment. This issue is fixed in version 21.7.11.","status":"published","published":"2026-09-29T21:17:19.047Z","modified":"2026-09-30T20:17:25.517Z","cvss":[{"version":"4.0","score":5.8,"vector":"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/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","level":"medium","assessor":"secondary"}],"cwes":["CWE-93"],"updated_at":"2026-11-02T14:12:52.759595Z"}],"osv":[{"id":"CVE-2026-102938","title":"virtualenv writes prompt values into pyvenv.cfg without sanitizing line boundaries, allowing configuration injection","description":"virtualenv is a tool for creating isolated virtual python environments. Prior to 21.7.11, PyEnvCfg.write() writes prompt values verbatim to the line-oriented pyvenv.cfg format while PyEnvCfg._read_values() parses the file with str.splitlines() and accepts the last value for duplicate keys. An attacker who influences --prompt, VIRTUALENV_PROMPT, or configuration input can insert a recognized line boundary and additional keys, including home, causing consumers to use an attacker-selected base interpreter or corrupted environment metadata. The security impact requires prompt input from outside the operator's trust boundary; directly supplied prompt content primarily corrupts the operator's own environment. This issue is fixed in version 21.7.11.","status":"published","published":"2026-09-29T20:58:20.696Z","modified":"2026-10-28T02:30:38.417504315Z","cvss":[{"version":"4.0","score":5.8,"vector":"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","level":"medium"}],"cwes":["CWE-93"],"updated_at":"2026-11-02T15:44:53.83521Z"},{"id":"DEBIAN-CVE-2026-102938","description":"virtualenv is a tool for creating isolated virtual python environments. Prior to 21.7.11, PyEnvCfg.write() writes prompt values verbatim to the line-oriented pyvenv.cfg format while PyEnvCfg._read_values() parses the file with str.splitlines() and accepts the last value for duplicate keys. An attacker who influences --prompt, VIRTUALENV_PROMPT, or configuration input can insert a recognized line boundary and additional keys, including home, causing consumers to use an attacker-selected base interpreter or corrupted environment metadata. The security impact requires prompt input from outside the operator's trust boundary; directly supplied prompt content primarily corrupts the operator's own environment. This issue is fixed in version 21.7.11.","status":"published","published":"2026-09-29T21:17:19.047Z","modified":"2026-10-01T08:47:26.318130936Z","cvss":[{"version":"4.0","score":5.8,"vector":"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/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","level":"medium"}],"updated_at":"2026-11-02T15:45:48.903138Z"},{"id":"GHSA-9h9j-4vrj-gf7g","title":"virtualenv writes prompt values into pyvenv.cfg without sanitizing line boundaries, allowing configuration injection","description":"### Summary\n\n`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.\n\n### Impact\n\nThe `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`:\n\n```console\n$ virtualenv --prompt $'x\"\\nhome = /attacker/path\\nprompt = \"z' venv\n$ grep '^home' venv/pyvenv.cfg\nhome = /attacker/path\n```\n\n`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.\n\nThis 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.\n\n### Details\n\nThe 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.\n\n### Patches\n\n`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`.\n\n### Workarounds\n\nDo not pass externally influenced data as the virtualenv prompt. Strip line boundaries from any value before using it as `--prompt` or `VIRTUALENV_PROMPT`.","status":"published","published":"2026-09-30T23:53:58Z","modified":"2026-10-06T15:25:56.172772842Z","cvss":[{"version":"4.0","score":5.8,"vector":"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","level":"medium"}],"cwes":["CWE-93"],"updated_at":"2026-11-02T15:46:43.875515Z"},{"id":"UBUNTU-CVE-2026-102938","description":"virtualenv is a tool for creating isolated virtual python environments. Prior to 21.7.11, PyEnvCfg.write() writes prompt values verbatim to the line-oriented pyvenv.cfg format while PyEnvCfg._read_values() parses the file with str.splitlines() and accepts the last value for duplicate keys. An attacker who influences --prompt, VIRTUALENV_PROMPT, or configuration input can insert a recognized line boundary and additional keys, including home, causing consumers to use an attacker-selected base interpreter or corrupted environment metadata. The security impact requires prompt input from outside the operator's trust boundary; directly supplied prompt content primarily corrupts the operator's own environment. This issue is fixed in version 21.7.11.","status":"published","published":"2026-09-29T21:17:00Z","modified":"2026-10-17T12:57:56.313633017Z","cvss":[{"version":"4.0","score":5.8,"vector":"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","level":"medium"}],"updated_at":"2026-11-02T16:55:58.519486Z"},{"id":"AZL-105672","title":"CVE-2026-102938 affecting package python-virtualenv for versions less than 20.36.1-10","description":"virtualenv is a tool for creating isolated virtual python environments. Prior to 21.7.11, PyEnvCfg.write() writes prompt values verbatim to the line-oriented pyvenv.cfg format while PyEnvCfg._read_values() parses the file with str.splitlines() and accepts the last value for duplicate keys. An attacker who influences --prompt, VIRTUALENV_PROMPT, or configuration input can insert a recognized line boundary and additional keys, including home, causing consumers to use an attacker-selected base interpreter or corrupted environment metadata. The security impact requires prompt input from outside the operator's trust boundary; directly supplied prompt content primarily corrupts the operator's own environment. This issue is fixed in version 21.7.11.","status":"published","published":"2026-09-29T21:17:19Z","modified":"2026-11-07T14:15:22.227281959Z","updated_at":"2026-11-07T14:48:25.680996Z"},{"id":"BIT-virtualenv-2026-102938","title":"virtualenv writes prompt values into pyvenv.cfg without sanitizing line boundaries, allowing configuration injection","description":"virtualenv is a tool for creating isolated virtual python environments. Prior to 21.7.11, PyEnvCfg.write() writes prompt values verbatim to the line-oriented pyvenv.cfg format while PyEnvCfg._read_values() parses the file with str.splitlines() and accepts the last value for duplicate keys. An attacker who influences --prompt, VIRTUALENV_PROMPT, or configuration input can insert a recognized line boundary and additional keys, including home, causing consumers to use an attacker-selected base interpreter or corrupted environment metadata. The security impact requires prompt input from outside the operator's trust boundary; directly supplied prompt content primarily corrupts the operator's own environment. This issue is fixed in version 21.7.11.","status":"published","published":"2026-10-06T11:57:39.681Z","modified":"2026-10-06T15:25:56.172772842Z","updated_at":"2026-11-02T15:28:36.104787Z"},{"id":"CLSA-2026-1791452380","title":"TuxCare security update for virtualenv (4 CVEs)","description":"TuxCare rebuilt virtualenv to address 4 CVEs. Fixed in 20.39.1.post2+tuxcare.","status":"published","published":"2026-10-08T09:39:40Z","modified":"2026-10-15T09:48:02.410568638Z","updated_at":"2026-11-02T15:43:49.016976Z"},{"id":"openSUSE-SU-2026:11974-1","title":"python313-virtualenv-21.14.2-1.1 on GA media","description":"These are all security issues fixed in the python313-virtualenv-21.14.2-1.1 package on the GA media of openSUSE Tumbleweed.","status":"published","published":"2026-10-02T00:00:00Z","modified":"2026-10-03T17:23:09.026072164Z","updated_at":"2026-11-02T16:58:40.245664Z"},{"id":"openSUSE-SU-2026:22100-1","title":"Security update for python-virtualenv","description":"This update for python-virtualenv fixes the following issues:\n\n- CVE-2026-102930: missing hash verification for network-fetched wheels can allow wheel tampering (bsc#1283904).\n- CVE-2026-102938: crafted prompt values with line boundaries can cause configuration key injection (bsc#1283890).\n","status":"published","published":"2026-10-14T13:25:46Z","modified":"2026-10-19T17:23:14.443447061Z","updated_at":"2026-11-02T16:58:42.426393Z"},{"id":"PYSEC-2026-4012","title":"virtualenv writes prompt values into pyvenv.cfg without sanitizing line boundaries, allowing configuration injection","description":"`pyvenv.cfg` is a line-based format with no escape syntax. `PyEnvCfg.write()`\nwrote values verbatim, while `PyEnvCfg._read_values()` parses the file with\n`str.splitlines()`. A value containing a line boundary therefore became\nadditional configuration lines, and because reading is last-wins, the injected\nkeys replaced any key written earlier in the file.\n\nThe `prompt` value is the reachable input: it is set by `--prompt`, by the\n`VIRTUALENV_PROMPT` environment variable, or from the config file, and\n`write()` emits `prompt` before `home`. A crafted prompt can therefore set\n`home` in the generated `pyvenv.cfg`. `home` is what tooling reads to locate\nthe base interpreter, so a consumer that trusts it can be pointed elsewhere.\n`implementation`, `version_info`, `version`, `executable`, `command` and\n`virtualenv` are also written before `prompt` and can be replaced the same\nway.\n\nThis requires the prompt to come from somewhere other than the person running\nthe command, for example a CI job templating a branch name into it, tooling\nderiving an environment name from user-supplied data, or an inherited\n`VIRTUALENV_PROMPT`.\n\nThe boundary set is the one `str.splitlines()` recognizes, which is wider than\n`\\n`: `\\r`, `\\v`, `\\f`, the file, group and record separators, `U+0085`,\n`U+2028` and `U+2029` were all written through unchanged and all split the\nline when read back.\n\nFixed in 21.7.11: `PyEnvCfg.write()` now collapses those boundaries to spaces\nas it serializes each line, so it cannot emit a structurally invalid file\nregardless of what a caller places in `content`.\n","status":"published","published":"2026-09-17T16:42:47Z","modified":"2026-10-06T15:25:56.172772842Z","updated_at":"2026-11-02T15:52:57.255153Z"},{"id":"SUSE-SU-2026:24243-1","title":"Security update for python-virtualenv","description":"This update for python-virtualenv fixes the following issues:\n\n- CVE-2026-102930: missing hash verification for network-fetched wheels can allow wheel tampering (bsc#1283904).\n- CVE-2026-102938: crafted prompt values with line boundaries can cause configuration key injection (bsc#1283890).\n","status":"published","published":"2026-10-14T13:25:46Z","modified":"2026-10-21T17:23:12.049967166Z","updated_at":"2026-11-02T15:54:04.519245Z"},{"id":"SUSE-SU-2026:4652-1","title":"Security update for python-virtualenv","description":"This update for python-virtualenv fixes the following issues:\n\n- CVE-2026-102930: missing hash verification for network-fetched wheels can allow wheel tampering (bsc#1283904).\n- CVE-2026-102938: crafted prompt values with line boundaries can cause configuration key injection (bsc#1283890).\n","status":"published","published":"2026-10-13T16:55:06Z","modified":"2026-10-14T17:30:07.604724527Z","updated_at":"2026-11-02T15:54:05.838224Z"}]}}
