Skip to content

Commit

Permalink
Handle volatile characters in prompts with promptsubst set
Browse files Browse the repository at this point in the history
We don't set that option, but users may do it in .zshrc.local or similar.

The issue is that performing expansions on a prompt string is an exploitable
vulnerability, if you do not contol every part the prompt string is made up of.

This is what is demonstrated by

  https://github.com/njhartwell/pw3nage

Per default, the code strips [$`] from a final prompt string, so you can't
really take advantage of prompt subst, even though you have it set. If the
prompt_subst option is not set, the code does not kick in at all.

If you want more control over which parts of the prompt are stripped, so you
can take control of prompt_subst, you can do that as well.  Here's an example
that only strips the data returned from vcs_info:

  zstyle ':prompt:grml:*:items:vcs' strip-sensitive-characters on
  zstyle ':prompt:grml:*:setup' strip-sensitive-characters off

Now you can take advantage of prompt_subst in privately defined tokens (even
though I'd use a token that calls a function callback instead of inserting a
string that relies on prompt_subst — but that's just me).

Reported-by: Joerg Jaspert <joerg@debian.org>
  • Loading branch information
ft committed Mar 25, 2017
1 parent 2210c9b commit 38a1b61
Showing 1 changed file with 32 additions and 11 deletions.
43 changes: 32 additions & 11 deletions etc/zsh/zshrc
Original file line number Diff line number Diff line change
Expand Up @@ -2255,22 +2255,24 @@ grml_theme_add_token: Token `%s'\'' exists! Giving up!\n\n' $name
fi
}

function grml_typeset_and_wrap () {
function grml_wrap_reply () {
emulate -L zsh
local target="$1"
local new="$2"
local left="$3"
local right="$4"

if (( ${+parameters[$new]} )); then
typeset -g "${target}=${(P)target}${left}${(P)new}${right}"
REPLY="${left}${(P)new}${right}"
else
REPLY=''
fi
}

function grml_prompt_addto () {
emulate -L zsh
local target="$1"
local lr it apre apost new v
local lr it apre apost new v REPLY
local -a items
shift

Expand All @@ -2284,21 +2286,21 @@ function grml_prompt_addto () {
|| apost=${grml_prompt_post_default[$it]}
zstyle -s ":prompt:${grmltheme}:${lr}:items:$it" token new \
|| new=${grml_prompt_token_default[$it]}
typeset -g "${target}=${(P)target}${apre}"
if (( ${+grml_prompt_token_function[$it]} )); then
${grml_prompt_token_function[$it]} $it
typeset -g "${target}=${(P)target}${REPLY}"
else
case $it in
battery)
grml_typeset_and_wrap $target $new '' ''
grml_wrap_reply $target $new '' ''
;;
change-root)
grml_typeset_and_wrap $target $new '(' ')'
grml_wrap_reply $target $new '(' ')'
;;
grml-chroot)
if [[ -n ${(P)new} ]]; then
typeset -g "${target}=${(P)target}(CHROOT)"
REPLY="$CHROOT"
else
REPLY=''
fi
;;
vcs)
Expand All @@ -2308,14 +2310,33 @@ function grml_prompt_addto () {
vcscalled=1
fi
if (( ${+parameters[$v]} )) && [[ -n "${(P)v}" ]]; then
typeset -g "${target}=${(P)target}${(P)v}"
REPLY="${(P)v}"
else
REPLY=''
fi
;;
*) typeset -g "${target}=${(P)target}${new}" ;;
*) REPLY="$new" ;;
esac
fi
typeset -g "${target}=${(P)target}${apost}"
# Strip volatile characters per item. This is off by default. See the
# global stripping code a few lines below for details.
if [[ -o prompt_subst ]] && zstyle -t ":prompt:${grmltheme}:${lr}:items:$it" \
strip-sensitive-characters
then
REPLY="${REPLY//[$\`]/}"
fi
typeset -g "${target}=${(P)target}${apre}${REPLY}${apost}"
done

# Per default, strip volatile characters (in the prompt_subst case)
# globally. If the option is off, the style has no effect. For more
# control, this can be turned off and stripping can be configured on a
# per-item basis (see above).
if [[ -o prompt_subst ]] && zstyle -T ":prompt:${grmltheme}:${lr}:setup" \
strip-sensitive-characters
then
typeset -g "${target}=${${(P)target}//[$\`]/}"
fi
}

function prompt_grml_precmd () {
Expand Down

0 comments on commit 38a1b61

Please sign in to comment.