From 5b692c5b30bba4d7adcd34ec2e71184f4b69661f Mon Sep 17 00:00:00 2001 From: Afonso Oliveira Date: Mon, 7 Sep 2026 14:31:07 +0100 Subject: [PATCH] Preserve user PATH across updater relaunches --- bin/omarchy-update | 9 ++-- test/shell.d/update-user-path-test.sh | 67 +++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 test/shell.d/update-user-path-test.sh diff --git a/bin/omarchy-update b/bin/omarchy-update index 68582cd0..9a809351 100755 --- a/bin/omarchy-update +++ b/bin/omarchy-update @@ -14,7 +14,10 @@ source "${BASH_SOURCE[0]%/*}/omarchy-security-functions" || exit 126 omarchy_security_require_privileged_bash_startup || exit 126 set -e omarchy_security_sanitize_bash_environment "$0" "$@" -user_path=$PATH +# Logging and lock acquisition re-exec this command with a sanitized PATH. +# Preserve the caller's path only for the later unprivileged hook/mise phases. +user_path=${OMARCHY_UPDATE_USER_PATH:-$PATH} +unset OMARCHY_UPDATE_USER_PATH omarchy_security_revoke_sudo_timestamp || exit 1 omarchy_security_install_sudo_cleanup_traps omarchy_security_enable_no_update_sudo @@ -35,11 +38,11 @@ cleanup_update() { if [[ -z ${OMARCHY_UPDATE_LOGGED:-} ]]; then script_command=$(printf '%q ' "$0" "$@") - exec env OMARCHY_UPDATE_LOGGED=1 script -qefc "$script_command" "/tmp/omarchy-update.log" + exec env OMARCHY_UPDATE_LOGGED=1 OMARCHY_UPDATE_USER_PATH="$user_path" script -qefc "$script_command" "/tmp/omarchy-update.log" fi if ! omarchy-update-lock held; then - exec omarchy-update-lock run "$0" "$@" + exec env OMARCHY_UPDATE_USER_PATH="$user_path" omarchy-update-lock run "$0" "$@" fi trap 'echo ""; echo -e "\033[0;31mSomething went wrong during the update!\n\nPlease review the output above carefully, correct the error, and retry the update.\n\nIf you need assistance, get help from the community at https://omarchy.org/discord\033[0m"' ERR diff --git a/test/shell.d/update-user-path-test.sh b/test/shell.d/update-user-path-test.sh new file mode 100644 index 00000000..f76f0faf --- /dev/null +++ b/test/shell.d/update-user-path-test.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +set -euo pipefail + +source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh" +source "$SHELL_TEST_DIR/fixtures/sudo-boundary-test.sh" +copy_boundary_file bin/omarchy-update + +# Model the two exec boundaries without a host update log or a real lock. +# Both child processes inherit the environment exactly as script/lock would. +cat >"$SUDO_TEST_ROOT/bin/script" <<'STUB' +#!/bin/bash +printf 'logged-reexec\n' >>"$SUDO_TEST_LOG" +[[ $1 == "-qefc" ]] || exit 90 +exec /usr/bin/bash -p -c "$2" +STUB +rm "$SUDO_TEST_ROOT/bin/omarchy-update-lock" +cat >"$SUDO_TEST_ROOT/bin/omarchy-update-lock" <<'STUB' +#!/bin/bash +case "$1" in + held) [[ ${SUDO_TEST_LOCKED:-0} == "1" ]] ;; + run) + shift + printf 'locked-reexec\n' >>"$SUDO_TEST_LOG" + export SUDO_TEST_LOCKED=1 + exec "$@" + ;; +esac +STUB +mkdir "$boundary_tmp/user commands" +cat >"$boundary_tmp/user commands/update-user-tool" <<'STUB' +#!/bin/bash +printf 'user-tool:%s\n' "$1" >>"$SUDO_TEST_LOG" +STUB +chmod +x "$SUDO_TEST_ROOT/bin/script" "$SUDO_TEST_ROOT/bin/omarchy-update-lock" "$boundary_tmp/user commands/update-user-tool" + +for step in omarchy-hook omarchy-update-mise; do + rm "$SUDO_TEST_ROOT/bin/$step" + cat >"$SUDO_TEST_ROOT/bin/$step" <<'STUB' +#!/bin/bash +[[ ! -e $SUDO_TEST_CACHE ]] || exit 91 +[[ $(command -v sudo) == "$OMARCHY_PATH/default/omarchy/sudo-no-update/sudo" ]] || exit 92 +update-user-tool "${0##*/}" +STUB + chmod +x "$SUDO_TEST_ROOT/bin/$step" +done + +for entry in fresh logged locked; do + reset_boundary + unset OMARCHY_UPDATE_LOGGED OMARCHY_UPDATE_USER_PATH SUDO_TEST_LOCKED + case "$entry" in + logged) export OMARCHY_UPDATE_LOGGED=1 ;; + locked) export OMARCHY_UPDATE_LOGGED=1 SUDO_TEST_LOCKED=1 ;; + esac + PATH="$boundary_tmp/user commands:$PATH" "$SUDO_TEST_ROOT/bin/omarchy-update" -y >"$boundary_tmp/output" 2>&1 || + fail "$entry update lost the original user PATH" "$(<"$boundary_tmp/output")" + grep -q '^user-tool:omarchy-hook$' "$SUDO_TEST_LOG" || fail "$entry hook could not run a user-installed tool" + grep -q '^user-tool:omarchy-update-mise$' "$SUDO_TEST_LOG" || fail "$entry mise could not run a user-installed tool" + if [[ $entry == "fresh" ]]; then + grep -q '^logged-reexec$' "$SUDO_TEST_LOG" || fail "fresh update did not exercise the logging exec" + fi + if [[ $entry != "locked" ]]; then + grep -q '^locked-reexec$' "$SUDO_TEST_LOG" || fail "$entry update did not exercise the lock exec" + fi + assert_boundary_cold "$entry update" + pass "$entry update preserves the original user PATH through logging and locking with no-update sudo first" +done