@@ -209,9 +209,7 @@ __git_ps1_show_upstream ()
209
209
if [[ -n " $count " && -n " $name " ]]; then
210
210
__git_ps1_upstream_name=$( git rev-parse \
211
211
--abbrev-ref " $upstream " 2> /dev/null)
212
- if [ $pcmode = yes ]; then
213
- # see the comments around the
214
- # __git_ps1_branch_name variable below
212
+ if [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then
215
213
p=" $p \$ {__git_ps1_upstream_name}"
216
214
else
217
215
p=" $p ${__git_ps1_upstream_name} "
@@ -308,6 +306,43 @@ __git_ps1 ()
308
306
;;
309
307
esac
310
308
309
+ # ps1_expanded: This variable is set to 'yes' if the shell
310
+ # subjects the value of PS1 to parameter expansion:
311
+ #
312
+ # * bash does unless the promptvars option is disabled
313
+ # * zsh does not unless the PROMPT_SUBST option is set
314
+ # * POSIX shells always do
315
+ #
316
+ # If the shell would expand the contents of PS1 when drawing
317
+ # the prompt, a raw ref name must not be included in PS1.
318
+ # This protects the user from arbitrary code execution via
319
+ # specially crafted ref names. For example, a ref named
320
+ # 'refs/heads/$(IFS=_;cmd=sudo_rm_-rf_/;$cmd)' might cause the
321
+ # shell to execute 'sudo rm -rf /' when the prompt is drawn.
322
+ #
323
+ # Instead, the ref name should be placed in a separate global
324
+ # variable (in the __git_ps1_* namespace to avoid colliding
325
+ # with the user's environment) and that variable should be
326
+ # referenced from PS1. For example:
327
+ #
328
+ # __git_ps1_foo=$(do_something_to_get_ref_name)
329
+ # PS1="...stuff...\${__git_ps1_foo}...stuff..."
330
+ #
331
+ # If the shell does not expand the contents of PS1, the raw
332
+ # ref name must be included in PS1.
333
+ #
334
+ # The value of this variable is only relevant when in pcmode.
335
+ #
336
+ # Assume that the shell follows the POSIX specification and
337
+ # expands PS1 unless determined otherwise. (This is more
338
+ # likely to be correct if the user has a non-bash, non-zsh
339
+ # shell and safer than the alternative if the assumption is
340
+ # incorrect.)
341
+ #
342
+ local ps1_expanded=yes
343
+ [ -z " $ZSH_VERSION " ] || [[ -o PROMPT_SUBST ]] || ps1_expanded=no
344
+ [ -z " $BASH_VERSION " ] || shopt -q promptvars || ps1_expanded=no
345
+
311
346
local repo_info rev_parse_exit_code
312
347
repo_info=" $( git rev-parse --git-dir --is-inside-git-dir \
313
348
--is-bare-repository --is-inside-work-tree \
@@ -457,21 +492,8 @@ __git_ps1 ()
457
492
fi
458
493
459
494
b=${b## refs/ heads/ }
460
- if [ $pcmode = yes ]; then
461
- # In pcmode (and only pcmode) the contents of
462
- # $gitstring are subject to expansion by the shell.
463
- # Avoid putting the raw ref name in the prompt to
464
- # protect the user from arbitrary code execution via
465
- # specially crafted ref names (e.g., a ref named
466
- # '$(IFS=_;cmd=sudo_rm_-rf_/;$cmd)' would execute
467
- # 'sudo rm -rf /' when the prompt is drawn). Instead,
468
- # put the ref name in a new global variable (in the
469
- # __git_ps1_* namespace to avoid colliding with the
470
- # user's environment) and reference that variable from
471
- # PS1.
495
+ if [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then
472
496
__git_ps1_branch_name=$b
473
- # note that the $ is escaped -- the variable will be
474
- # expanded later (when it's time to draw the prompt)
475
497
b=" \$ {__git_ps1_branch_name}"
476
498
fi
477
499
0 commit comments