Files
omarchycn/test/shell.d/timezone-test.sh
T
0ad64a59df Fix command injection in theme install, drop tzupdate NOPASSWD (#6694)
* Fix theme install code execution and drop tzupdate NOPASSWD

VULN-01 (C, D, E): a malicious theme can execute arbitrary code
during install through three injection sinks:

  C: colors.toml values reach a sed script unsanitized.
     GNU sed's `e` flag runs the pattern space as a shell command.

  D: vscode.json `.name` is interpolated into a sed replacement
     string without escaping sed metacharacters.

  E: keyboard.rgb content is interpolated into a python3 -c
     argument without validation.

Fix C by validating keys and values in omarchy-theme-color's parser
with a character allowlist. Byte-identical output for all 22 shipped
themes.

Fix D by escaping backslash, ampersand, and slash in the theme name
before sed interpolation.

Fix E by gating on ^[0-9A-Fa-f]{6}$ before interpolation, in both
the Framework 16 and ASUS ROG keyboard scripts.

VULN-02: the tzupdate sudoers grant has no argument constraint.
tzupdate -l lets any wheel user write a root-owned symlink to any
path. Drop it; nothing has invoked tzupdate since omarchy-cmd-tzupdate
was removed. Keep timedatectl set-timezone.

* Harden keyboard and vscode theme scripts

keyboard-f16: pass hex as sys.argv instead of interpolating into
python3 -c. The hex validation gate stays as the primary defense;
argv separation is defense-in-depth per OWASP guidance.

vscode: replace sed interpolation of theme name with jq, which
handles arbitrary strings safely via --arg. Validate extension IDs
against ^[a-zA-Z0-9._-]+$ before passing to --install-extension.

* Keep VS Code settings edits JSONC-safe

settings.json is JSONC, so routing the write through jq dropped theme sync
entirely for anyone with a comment or trailing comma in the file, including
the `{ "workbench.colorTheme": "",\n}` shape Omarchy itself creates. Edit in
place again and close the injection by validating the theme label instead.

Scope the extension-id guard to the install so a malformed id no longer skips
the colorTheme write, and treat a missing descriptor field as empty rather
than the literal string "null".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Widen the accepted colors.toml value charset

The sanitizer dropped gradient angles, decimals, underscored palette
references, and paths, which vanish from --raw/--all and leave a raw
{{ placeholder }} in the generated config. Allow the punctuation real
palettes use, keep out everything sed treats as special, and say so on
stderr rather than dropping a key silently.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: David Heinemeier Hansson <david@hey.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 12:31:52 +02:00

38 lines
1.6 KiB
Bash

#!/bin/bash
set -euo pipefail
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 ||
fail "timezone sudoers rule allows passwordless timedatectl timezone changes"
! grep -F 'tzupdate' "$sudoers_file" >/dev/null ||
fail "timezone sudoers rule does not grant passwordless tzupdate"
grep -F 'sudo timedatectl set-timezone "$timezone"' "$timezone_menu" >/dev/null ||
fail "timezone menu uses the passwordless sudoers timedatectl rule"
! grep -F 'pkexec timedatectl set-timezone "$timezone"' "$timezone_menu" >/dev/null ||
fail "timezone menu does not wrap timedatectl in pkexec"
! grep -F 'pkexec /usr/bin/timedatectl set-timezone "$timezone"' "$timezone_menu" >/dev/null ||
fail "timezone menu does not wrap timedatectl in pkexec"
! grep -F 'sudo /usr/bin/timedatectl set-timezone "$timezone"' "$timezone_menu" >/dev/null ||
fail "timezone menu lets sudo resolve timedatectl from its secure path"
! grep -Fx 'timedatectl set-timezone "$timezone"' "$timezone_menu" >/dev/null ||
fail "timezone menu does not use bare timedatectl, which triggers polkit"
grep -F 'omarchy-shell -q omarchy.clock refresh' "$timezone_menu" >/dev/null ||
fail "timezone menu refreshes the namespaced clock IPC target"
! grep -F 'omarchy-shell -q Clock refresh' "$timezone_menu" >/dev/null ||
fail "timezone menu no longer refreshes the retired Clock IPC target"
pass "timezone menu refreshes clock after timezone changes"