馃寪 US-Proxy
class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
Skip to content

馃悰 fix(activation): escape the bash prompt for both PS1 passes - #3390

Merged
gaborbernat merged 2 commits into
pypa:mainfrom
gaborbernat:ps1-escape
Oct 12, 2026
Merged

gaborbernat merged 2 commits into
pypa:mainfrom
gaborbernat:ps1-escape

Conversation

@gaborbernat

Copy link
Copy Markdown
Contributor

bash handles PS1 in two passes each time it draws the prompt: it first decodes backslash prompt escapes, turning \\ into \ and \$ into $ (or # for root), and then expands the result. The bash activate script escaped the environment name for the expansion pass only (#3326), so a backslash in the name undoes that escaping. 馃攼 A name such as a\$(touch PWNED), from the directory, --prompt or VIRTUALENV_PROMPT, runs the command each time bash draws the prompt. For root, \$ decodes to #, so the same name renders wrong but runs nothing.

Under bash, activate now escapes backslashes, dollar signs and backticks a second time, so both passes leave the name literal. zsh does no decode pass, so it keeps the single escaping added in 5b91536. The prompt tests gain cases for a backslash before $(...) and before backticks, and for names with a backslash before $, before a backtick, doubled, and trailing; they render through bash 5.2 and zsh 5.9 and pass as root and as an unprivileged user.

Every release up to 21.14.6 is affected, and earlier releases before 21.13.0 do not escape the name at all.

bash decodes its backslash prompt escapes in PS1 before it expands the
result, turning \\ into \ and \$ into $ (or # for root). The activate
script escaped the environment name for the expansion pass only, so a
backslash in the name undid the escaping, and a name such as
a\$(touch PWNED) ran the command each time the prompt was drawn.

Escape the name a second time under bash so both passes leave it
literal. zsh does no decode pass, so it keeps the single escaping.
@gaborbernat gaborbernat added bug security Fixes a vulnerability or hardens the supply chain, CI or release labels Oct 12, 2026
@gaborbernat
gaborbernat merged commit c3104e0 into pypa:main Oct 12, 2026
6 checks passed
gaborbernat added a commit that referenced this pull request Oct 12, 2026
#3390 escapes the bash prompt twice, once for bash's prompt-escape
decode and once for its expansion. `test_bash` renders the prompt with
`${PS1@P}` on bash 4.4+, but macOS ships bash 3.2, where it falls back
to a `sed` that strips one layer of escapes. 馃И The rendered prompt then
kept `\$` and `` \` `` and `test_bash` failed on every macOS job, as on
[#3391](https://github.com/pypa/virtualenv/actions/runs/38189937681/job/114620308443).

The fallback now runs the same `sed` expression twice. On bash 5.3 its
output matches `${PS1@P}` for the tester's environment name and the
names from the #3390 regression cases.
@gaborbernat
gaborbernat deleted the ps1-escape branch October 15, 2026 23:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug security Fixes a vulnerability or hardens the supply chain, CI or release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant