From 0ae1694830b6bd9511042fe1b89a0062d8c083cb Mon Sep 17 00:00:00 2001 From: Omarchybot Date: Tue, 25 Aug 2026 22:30:09 +0200 Subject: [PATCH] Constrain the tzupdate sudoers rule to a single timezone argument (#8194) The wildcard granted passwordless root for timedatectl set-timezone plus any trailing arguments, so -H/--host and -M/--machine reached the SSH and machine transports as root. Systemd 261 guards argv injection into ssh, but -H still drives root's SSH client at an attacker-chosen host, and the transport resolves its helper through PATH; only Defaults secure_path stands between that and a planted ssh running as root. Match the argument with an anchored POSIX ERE that admits exactly one timezone token (no whitespace, no leading-dash segment, no traversal component), so no second argument and no option can ever match. The sole caller, omarchy-menu-timezone, passes one list-timezones value and is unaffected. Co-authored-by: Claude Opus 4.8 Co-authored-by: Codex XHigh --- etc/sudoers.d/omarchy-tzupdate | 2 +- test/shell.d/timezone-test.sh | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/etc/sudoers.d/omarchy-tzupdate b/etc/sudoers.d/omarchy-tzupdate index d35adb82..98b30771 100644 --- a/etc/sudoers.d/omarchy-tzupdate +++ b/etc/sudoers.d/omarchy-tzupdate @@ -1 +1 @@ -%wheel ALL=(root) NOPASSWD: /usr/bin/timedatectl set-timezone * +%wheel ALL=(root) NOPASSWD: /usr/bin/timedatectl ^set-timezone [A-Za-z0-9_+][A-Za-z0-9_+.-]*(/[A-Za-z0-9_+][A-Za-z0-9_+.-]*)*$ diff --git a/test/shell.d/timezone-test.sh b/test/shell.d/timezone-test.sh index c1880a14..dc4a0263 100644 --- a/test/shell.d/timezone-test.sh +++ b/test/shell.d/timezone-test.sh @@ -7,9 +7,12 @@ source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh" timezone_menu="$ROOT/bin/omarchy-menu-timezone" sudoers_file="$ROOT/etc/sudoers.d/omarchy-tzupdate" -grep -F '%wheel ALL=(root) NOPASSWD: /usr/bin/timedatectl set-timezone *' "$sudoers_file" >/dev/null || +grep -F '%wheel ALL=(root) NOPASSWD: /usr/bin/timedatectl ^set-timezone [A-Za-z0-9_+][A-Za-z0-9_+.-]*(/[A-Za-z0-9_+][A-Za-z0-9_+.-]*)*$' "$sudoers_file" >/dev/null || fail "timezone sudoers rule allows passwordless timedatectl timezone changes" +! grep -F 'set-timezone *' "$sudoers_file" >/dev/null || + fail "timezone sudoers rule uses a bare wildcard that admits extra arguments like -H and -M" + ! grep -F 'tzupdate' "$sudoers_file" >/dev/null || fail "timezone sudoers rule does not grant passwordless tzupdate"