From 0237810720c86f0e4b2083a5fc9b453c878c7675 Mon Sep 17 00:00:00 2001 From: Gogs Date: Fri, 7 Aug 2026 22:24:44 +0800 Subject: [PATCH 1/4] fix(barbuk): strip control characters from prompt segment output The python_venv segment falls back to reading pyproject.toml's requires-python field with no character restrictions, and every segment's output was concatenated into PS1 unfiltered. A crafted pyproject.toml could inject terminal escape sequences into the prompt simply by cd-ing into the directory. Strips control characters from each segment's output in __prompt-command, the single point all segments already pass through, before it's appended to PS1. --- themes/barbuk/barbuk.theme.bash | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/themes/barbuk/barbuk.theme.bash b/themes/barbuk/barbuk.theme.bash index cedb56902d..62eb5e6287 100644 --- a/themes/barbuk/barbuk.theme.bash +++ b/themes/barbuk/barbuk.theme.bash @@ -312,6 +312,12 @@ function __prompt-command() { for segment in $BARBUK_PROMPT; do local info info="$(__"${segment}"_prompt)" + # Some segments (e.g. python_venv) can read values from files in the + # current directory (pyproject.toml, etc), which have no character + # restrictions, unlike a git ref name. Strip control characters + # before concatenating into PS1 so a crafted file can't inject + # terminal escape sequences into the prompt. + info="${info//[$'\x01'-$'\x1f'$'\x7f']/}" [[ -n "${info}" ]] && PS1+="${info}" done From 496e52ec973beadb80bf4bceb97f176bd4c164f5 Mon Sep 17 00:00:00 2001 From: Gogs Date: Sat, 8 Aug 2026 15:34:07 +0800 Subject: [PATCH 2/4] Revert "fix(barbuk): strip control characters from prompt segment output" This reverts commit 0237810720c86f0e4b2083a5fc9b453c878c7675. --- themes/barbuk/barbuk.theme.bash | 6 ------ 1 file changed, 6 deletions(-) diff --git a/themes/barbuk/barbuk.theme.bash b/themes/barbuk/barbuk.theme.bash index 62eb5e6287..cedb56902d 100644 --- a/themes/barbuk/barbuk.theme.bash +++ b/themes/barbuk/barbuk.theme.bash @@ -312,12 +312,6 @@ function __prompt-command() { for segment in $BARBUK_PROMPT; do local info info="$(__"${segment}"_prompt)" - # Some segments (e.g. python_venv) can read values from files in the - # current directory (pyproject.toml, etc), which have no character - # restrictions, unlike a git ref name. Strip control characters - # before concatenating into PS1 so a crafted file can't inject - # terminal escape sequences into the prompt. - info="${info//[$'\x01'-$'\x1f'$'\x7f']/}" [[ -n "${info}" ]] && PS1+="${info}" done From 7b7718c7e2a7f906e9bfcb988d547bfe0015b9e7 Mon Sep 17 00:00:00 2001 From: Gogs Date: Sat, 8 Aug 2026 15:35:44 +0800 Subject: [PATCH 3/4] fix(barbuk): sanitize requires-python at extraction instead of every segment The previous fix stripped control characters from every segment's rendered output in __prompt-command, which also stripped legitimate ANSI color codes (e.g. the git segment's branch/status coloring), breaking prompt coloring for every user, not just the vulnerable one. It also only handled raw control bytes, not the same escape sequence written as literal backslash-letter text (e.g. "\e]0;...\a"), which some shells/echo modes can still expand. Sanitize at the actual source instead: strip anything outside printable ASCII, plus literal backslash-letter escape sequences, directly in the awk extraction of pyproject.toml's requires-python field, the one value that's genuinely untrusted. Every other segment's output, including its own legitimate color codes, is left untouched. Thanks @BarbUk for catching both issues. --- themes/barbuk/barbuk.theme.bash | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/themes/barbuk/barbuk.theme.bash b/themes/barbuk/barbuk.theme.bash index cedb56902d..4fe8f86548 100644 --- a/themes/barbuk/barbuk.theme.bash +++ b/themes/barbuk/barbuk.theme.bash @@ -194,7 +194,12 @@ function __python_venv_prompt() { elif [[ -n "${VIRTUAL_ENV_PROMPT:-}" ]]; then python_info="${VIRTUAL_ENV_PROMPT}" elif [[ -f pyproject.toml ]]; then - python_info=$(awk -F'"' '/^requires-python/ {print $2}' pyproject.toml) + # pyproject.toml has no character restrictions on this field, unlike a + # git ref name. Strip anything outside printable ASCII (raw control + # characters, e.g. terminal escape sequences) as well as literal + # backslash-letter escape sequences written as text (e.g. "\e]...\a"), + # which some shells/echo modes can still expand. + python_info=$(awk -F'"' '/^requires-python/ {gsub(/[^\40-\176]|\\[a-zA-Z]/, "", $2); print $2}' pyproject.toml) [[ -z "${python_info}" ]] && python_info="py" fi From 404bba0725abd6809e298199dc9a8555a1efb142 Mon Sep 17 00:00:00 2001 From: Gogs Date: Sun, 9 Aug 2026 01:14:14 +0800 Subject: [PATCH 4/4] fix(barbuk): apply BarbUk's suggested fix, control-class strip + drop echo -e git_prompt_info used 'echo -e' to expand its own color codes, which were stored as literal backslash-escape text (e.g. lib/colors.bash's bold_red) rather than real bytes. Applying the blanket control- character strip in __prompt-command without first removing that -e flag broke coloring, since by the time the strip ran, echo -e had already turned the git segment's own colors into real bytes indistinguishable from a malicious payload. Dropping -e means git_prompt_info's own escape codes are no longer expanded from literal text at echo time (removing the injection surface that flag represented for any future untrusted input reaching this function), and re-adds the blanket [[:cntrl:]] strip at __prompt-command, this time safely, since no segment's construction path relies on echo -e turning literal text into real bytes anymore. Verified live: git branch coloring intact in a raw pipe-pane capture (same bytes as before this change), and the original PoC's injected control bytes still stripped from the python_venv segment. --- themes/barbuk/barbuk.theme.bash | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/themes/barbuk/barbuk.theme.bash b/themes/barbuk/barbuk.theme.bash index 4fe8f86548..b3f2827c00 100644 --- a/themes/barbuk/barbuk.theme.bash +++ b/themes/barbuk/barbuk.theme.bash @@ -106,7 +106,7 @@ function __git-upstream-remote-logo_prompt() { function git_prompt_info() { git_prompt_vars - echo -e "on $SCM_GIT_CHAR_ICON_BRANCH $SCM_PREFIX$SCM_BRANCH$SCM_STATE$SCM_GIT_AHEAD$SCM_GIT_BEHIND$SCM_GIT_STASH$SCM_SUFFIX " + echo "on $SCM_GIT_CHAR_ICON_BRANCH $SCM_PREFIX$SCM_BRANCH$SCM_STATE$SCM_GIT_AHEAD$SCM_GIT_BEHIND$SCM_GIT_STASH$SCM_SUFFIX " } function __exit_prompt() { @@ -317,6 +317,7 @@ function __prompt-command() { for segment in $BARBUK_PROMPT; do local info info="$(__"${segment}"_prompt)" + info="${info//[[:cntrl:]]/}" [[ -n "${info}" ]] && PS1+="${info}" done