From 41f3279cb0746059222f8fed8342a21361bf1294 Mon Sep 17 00:00:00 2001 From: MickLesk <47820557+MickLesk@users.noreply.github.com> Date: Wed, 11 Nov 2026 12:27:41 +0100 Subject: [PATCH] Drop the SUDO_ variables an update through sudo carries pnpm 12 refuses global commands while SUDO_USER is set, which failed the Immich update for anyone running sudo update (VE #18607). Nothing reads these variables, and apart from them root via sudo looks exactly like a root login. --- .github/workflows/verify-split-files.yml | 5 +++++ core/build.func | 3 +++ tests/sudo-env.sh | 28 ++++++++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 tests/sudo-env.sh diff --git a/.github/workflows/verify-split-files.yml b/.github/workflows/verify-split-files.yml index 2eb2431..85a3153 100644 --- a/.github/workflows/verify-split-files.yml +++ b/.github/workflows/verify-split-files.yml @@ -30,6 +30,7 @@ on: - "tests/uv-required-version.sh" - "tests/docker-lxcfs.sh" - "tests/java-memory.sh" + - "tests/sudo-env.sh" - "tests/deb822-local-keyring.sh" - "tests/gpu-pci-class.sh" - "tests/nvidia-version-pin.sh" @@ -90,6 +91,7 @@ on: - "tests/uv-required-version.sh" - "tests/docker-lxcfs.sh" - "tests/java-memory.sh" + - "tests/sudo-env.sh" - "tests/deb822-local-keyring.sh" - "tests/gpu-pci-class.sh" - "tests/nvidia-version-pin.sh" @@ -174,6 +176,9 @@ jobs: - name: Java memory drop-in tests run: bash tests/java-memory.sh + - name: sudo environment tests + run: bash tests/sudo-env.sh + - name: deb822 local keyring tests run: bash tests/deb822-local-keyring.sh diff --git a/core/build.func b/core/build.func index 458a4bd..d44b830 100644 --- a/core/build.func +++ b/core/build.func @@ -107,6 +107,9 @@ COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-$_CS_DEFAULT_URL}" COMMUNITY_SCRIPTS_CORE_URL="${COMMUNITY_SCRIPTS_CORE_URL:-$_CS_CORE_DEFAULT_URL}" export COMMUNITY_SCRIPTS_URL COMMUNITY_SCRIPTS_CORE_URL +# Left by sudo; pnpm 12 refuses global commands while SUDO_USER is set. +unset SUDO_USER SUDO_UID SUDO_GID SUDO_HOME SUDO_COMMAND + # ── Resolution ──────────────────────────────────────────────────────────────── # Local file for a virtual path, or non-zero when it must be fetched remotely. # Every branch is -f guarded: an unguarded assignment used to shadow the diff --git a/tests/sudo-env.sh b/tests/sudo-env.sh new file mode 100644 index 0000000..a2e2a23 --- /dev/null +++ b/tests/sudo-env.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +set -euo pipefail + +CORE_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)" +BUILD="$CORE_DIR/core/build.func" +passed=0 failed=0 + +check() { + if [[ "$3" == "$2" ]]; then + echo "PASS $1" + passed=$((passed + 1)) + else + echo "FAIL $1: expected <$2>, got <$3>" >&2 + failed=$((failed + 1)) + fi +} + +line="$(grep -m1 '^unset SUDO_USER' "$BUILD" || true)" +left="$(SUDO_USER=bob SUDO_UID=1000 SUDO_GID=1000 SUDO_HOME=/home/bob SUDO_COMMAND=update \ + bash -c "${line:-:}; env | grep '^SUDO_' | cut -d= -f1 | xargs || true")" +check "build.func drops every SUDO_ variable" "" "$left" + +unset_at="$(grep -n -m1 '^unset SUDO_USER' "$BUILD" | cut -d: -f1 || true)" +probes_at="$(grep -n -m1 '^_cs_start_host_probes$' "$BUILD" | cut -d: -f1)" +check "before the first child process starts" yes "$([[ -n "$unset_at" && "$unset_at" -lt "$probes_at" ]] && echo yes || echo no)" + +printf '%s passed, %s failed\n' "$passed" "$failed" +((failed == 0))