fix(installer): prevent command injection via `$USER` in install.sh (#13960)
HOME="${HOME:-$(eval echo ~"$USER")}" expands any shell metacharacters in
$USER when HOME is unset (CWE-78), e.g. USER='x"; <command>; "'. Validate the
username against a safe character set before running the eval and fall back
to $PWD for unsafe values. Also quote $USER in the getent call to avoid word
splitting.
Co-authored-by: Carlo Sala <carlosalag@protonmail.com>
Diff
1diff --git a/tools/install.sh b/tools/install.sh
2index 0af9fada1995f89f100de09e829c7970d103bd09..83ff0cab051670daaa27713d8f2203555c45bf68 100755
3--- a/tools/install.sh
4+++ b/tools/install.sh
5@@ -49,9 +49,31 @@ USER=${USER:-$(id -u -n)}
6 # $HOME is defined at the time of login, but it could be unset. If it is unset,
7 # a tilde by itself (~) will not be expanded to the current user's home directory.
8 # POSIX: https://pubs.opengroup.org/onlinepubs/009696899/basedefs/xbd_chap08.html#tag_08_03
9-HOME="${HOME:-$(getent passwd $USER 2>/dev/null | cut -d: -f6)}"
10-# macOS does not have getent, but this works even if $HOME is unset
11-HOME="${HOME:-$(eval echo ~"$USER")}"
12+if [ -z "$HOME" ]; then
13+ HOME=$(getent passwd "$USER" 2>/dev/null | cut -d: -f6)
14+
15+ # macOS does not have getent; fall back to tilde expansion, but only if
16+ # $USER is a safe username. The eval below would otherwise expand any shell
17+ # metacharacters in $USER and allow command injection (CWE-78).
18+ case "$USER" in
19+ *[![:alnum:]_.-]*|'')
20+ ;;
21+ *)
22+ resolved_home=$(eval echo ~"$USER")
23+ # Unknown users are not expanded and produce a literal "~username".
24+ [ "$resolved_home" = "~$USER" ] || HOME=$resolved_home
25+ ;;
26+ esac
27+
28+ case "$HOME" in
29+ /*) ;;
30+ *)
31+ echo "Error: unable to determine the current user's home directory." >&2
32+ echo "Set HOME explicitly and rerun the installer." >&2
33+ exit 1
34+ ;;
35+ esac
36+fi
373839 # Track if $ZSH was provided