From a02a881cc75b95aeeecaf24db39c47c7e3e8d24e Mon Sep 17 00:00:00 2001 From: marcelsafin <179933638+marcelsafin@users.noreply.github.com> Date: Sat, 11 Jul 2026 18:45:24 +0200 Subject: [PATCH] fix(uninstaller): harden home path resolution Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tools/uninstall.sh | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/tools/uninstall.sh b/tools/uninstall.sh index 1dc290eda..cad793121 100644 --- a/tools/uninstall.sh +++ b/tools/uninstall.sh @@ -2,28 +2,39 @@ # Make sure important variables exist if not already defined # -# $USER is defined by login(1) which is not always executed (e.g. containers) -# POSIX: https://pubs.opengroup.org/onlinepubs/009695299/utilities/id.html -USER=${USER:-$(id -u -n)} # $HOME is defined at the time of login, but it could be unset. If it is unset, # a tilde by itself (~) will not be expanded to the current user's home directory. # POSIX: https://pubs.opengroup.org/onlinepubs/009696899/basedefs/xbd_chap08.html#tag_08_03 -HOME="${HOME:-$(getent passwd "$USER" 2>/dev/null | cut -d: -f6)}" -# macOS does not have getent; use dscl to query the directory service -HOME="${HOME:-$(dscl . -read "/Users/$USER" NFSHomeDirectory 2>/dev/null | awk '{print $2}')}" -# Last resort: tilde expansion via eval (POSIX, but carries injection risk) -HOME="${HOME:-$(eval "echo ~$USER" 2>/dev/null)}" - -if [ -z "$HOME" ]; then - echo >&2 "Error: could not determine HOME directory" - exit 1 +current_uid=$(id -u 2>/dev/null) +current_user=$(id -u -n 2>/dev/null) +HOME=${HOME:-} +if [ -z "$HOME" ] && [ -n "$current_uid" ] && command -v getent >/dev/null 2>&1; then + HOME=$(getent passwd "$current_uid" 2>/dev/null | cut -d: -f6) +fi +# macOS does not have getent; use dscl to query the directory service. +if [ -z "$HOME" ] && [ -n "$current_user" ] && command -v dscl >/dev/null 2>&1; then + HOME=$(dscl . -read "/Users/$current_user" NFSHomeDirectory 2>/dev/null | awk '{print $2}') +fi +if [ -z "$HOME" ] && [ -n "$current_uid" ] && [ -r /etc/passwd ]; then + HOME=$(awk -F: -v uid="$current_uid" '$3 == uid { print $6; exit }' /etc/passwd) fi +HOME=${HOME%"${HOME##*[!/]}"} +case "$HOME" in + ""|/) echo >&2 "Error: could not determine HOME directory"; exit 1 ;; + /*) ;; + *) echo >&2 "Error: could not determine HOME directory"; exit 1 ;; +esac + zdot="${ZDOTDIR:-$HOME}" +zdot=${zdot%"${zdot##*[!/]}"} +case "${zdot:-/}" in + /|.|..) echo >&2 "Error: refusing unsafe ZDOTDIR '$zdot'"; exit 1 ;; +esac # Default OMZ directory (matches tools/install.sh logic) -if [ -n "$ZDOTDIR" ] && [ "$ZDOTDIR" != "$HOME" ]; then - OMZ_DIR="${ZSH:-$ZDOTDIR/ohmyzsh}" +if [ -n "$ZDOTDIR" ] && [ "$zdot" != "$HOME" ]; then + OMZ_DIR="${ZSH:-$zdot/ohmyzsh}" else OMZ_DIR="${ZSH:-$HOME/.oh-my-zsh}" fi