d42209f2afa8ec3e6971e5b4695ff27f9d5670d2

Author
P1bub <js1626482@gmail.com>
Committer
GitHub <noreply@github.com>
Date

Message

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
37 
38 
39 # Track if $ZSH was provided