Stop world-writable browser policy directories

Chromium managed policy is mandatory for every profile. World-writable
dirs let any local uid plant policy, including force-installed
extensions. Write goes through the omarchy-browser-policy group at 2775
so theme colour still works without other-write.
This commit is contained in:
acrogenesis
2026-08-25 12:04:02 -06:00
parent 9301092404
commit 95b791af16
14 changed files with 596 additions and 38 deletions
+13 -17
View File
@@ -6,9 +6,12 @@
set -e set -e
setup_policy_directory() { source "$OMARCHY_PATH/install/helpers/browser-policy.sh"
sudo mkdir -p "$1"
sudo chmod a+rw "$1" setup_chromium_policy_directory() {
browser_policy_setup_group
browser_policy_grant_user "${USER:-$(id -un)}"
browser_policy_setup_dir "$1"
} }
announce_browser_installed() { announce_browser_installed() {
@@ -23,13 +26,6 @@ copy_chromium_flags() {
omarchy-install-chromium-ytdlp omarchy-install-chromium-ytdlp
} }
setup_firefox_preferences() {
local distribution_dir="$1"
setup_policy_directory "$distribution_dir"
sudo cp -f "$OMARCHY_PATH/default/firefox/policies.json" "$distribution_dir/policies.json"
}
setup_firefox_wayland() { setup_firefox_wayland() {
mkdir -p ~/.config/environment.d mkdir -p ~/.config/environment.d
echo "MOZ_ENABLE_WAYLAND=1" > ~/.config/environment.d/omarchy-firefox-wayland.conf echo "MOZ_ENABLE_WAYLAND=1" > ~/.config/environment.d/omarchy-firefox-wayland.conf
@@ -40,7 +36,7 @@ chromium)
echo "Installing Chromium..." echo "Installing Chromium..."
omarchy-pkg-add chromium omarchy-pkg-add chromium
setup_policy_directory /etc/chromium/policies/managed setup_chromium_policy_directory /etc/chromium/policies/managed
copy_chromium_flags ~/.config/chromium-flags.conf copy_chromium_flags ~/.config/chromium-flags.conf
omarchy-theme-set-browser omarchy-theme-set-browser
announce_browser_installed "Chromium" announce_browser_installed "Chromium"
@@ -49,7 +45,7 @@ chrome)
echo "Installing Chrome..." echo "Installing Chrome..."
omarchy-pkg-aur-add google-chrome || exit 1 omarchy-pkg-aur-add google-chrome || exit 1
setup_policy_directory /etc/opt/chrome/policies/managed setup_chromium_policy_directory /etc/opt/chrome/policies/managed
copy_chromium_flags ~/.config/chrome-flags.conf copy_chromium_flags ~/.config/chrome-flags.conf
omarchy-theme-set-browser omarchy-theme-set-browser
announce_browser_installed "Chrome" announce_browser_installed "Chrome"
@@ -58,7 +54,7 @@ edge)
echo "Installing Edge..." echo "Installing Edge..."
omarchy-pkg-aur-add microsoft-edge-stable-bin || exit 1 omarchy-pkg-aur-add microsoft-edge-stable-bin || exit 1
setup_policy_directory /etc/opt/edge/policies/managed setup_chromium_policy_directory /etc/opt/edge/policies/managed
copy_chromium_flags ~/.config/microsoft-edge-stable-flags.conf copy_chromium_flags ~/.config/microsoft-edge-stable-flags.conf
omarchy-theme-set-browser omarchy-theme-set-browser
announce_browser_installed "Edge" announce_browser_installed "Edge"
@@ -67,7 +63,7 @@ brave)
echo "Installing Brave..." echo "Installing Brave..."
omarchy-pkg-aur-add brave-bin || exit 1 omarchy-pkg-aur-add brave-bin || exit 1
setup_policy_directory /etc/brave/policies/managed setup_chromium_policy_directory /etc/brave/policies/managed
copy_chromium_flags ~/.config/brave-flags.conf copy_chromium_flags ~/.config/brave-flags.conf
omarchy-theme-set-browser omarchy-theme-set-browser
announce_browser_installed "Brave" announce_browser_installed "Brave"
@@ -76,7 +72,7 @@ brave-origin)
echo "Installing Brave Origin..." echo "Installing Brave Origin..."
omarchy-pkg-aur-add brave-origin-bin || exit 1 omarchy-pkg-aur-add brave-origin-bin || exit 1
setup_policy_directory /etc/brave/policies/managed setup_chromium_policy_directory /etc/brave/policies/managed
copy_chromium_flags ~/.config/brave-origin-flags.conf copy_chromium_flags ~/.config/brave-origin-flags.conf
omarchy-theme-set-browser omarchy-theme-set-browser
announce_browser_installed "Brave Origin" announce_browser_installed "Brave Origin"
@@ -85,7 +81,7 @@ firefox)
echo "Installing Firefox..." echo "Installing Firefox..."
omarchy-pkg-add firefox || exit 1 omarchy-pkg-add firefox || exit 1
setup_firefox_preferences /usr/lib/firefox/distribution browser_policy_setup_firefox_distribution /usr/lib/firefox/distribution
setup_firefox_wayland setup_firefox_wayland
announce_browser_installed "Firefox" announce_browser_installed "Firefox"
;; ;;
@@ -93,7 +89,7 @@ zen)
echo "Installing Zen..." echo "Installing Zen..."
omarchy-pkg-aur-add zen-browser-bin || exit 1 omarchy-pkg-aur-add zen-browser-bin || exit 1
setup_firefox_preferences /opt/zen-browser/distribution browser_policy_setup_firefox_distribution /opt/zen-browser/distribution
setup_firefox_wayland setup_firefox_wayland
announce_browser_installed "Zen" announce_browser_installed "Zen"
;; ;;
+9
View File
@@ -742,6 +742,15 @@ create_user() {
# for specific commands), and a duplicate grant is harmless. # for specific commands), and a duplicate grant is harmless.
echo "%wheel ALL=(ALL:ALL) ALL" >/etc/sudoers.d/00-omarchy-wheel echo "%wheel ALL=(ALL:ALL) ALL" >/etc/sudoers.d/00-omarchy-wheel
chmod 440 /etc/sudoers.d/00-omarchy-wheel chmod 440 /etc/sudoers.d/00-omarchy-wheel
source "$OMARCHY_PATH/install/helpers/browser-policy.sh"
OMARCHY_INSTALL_USER=$username
OMARCHY_PROVISIONING_DIR=$PROVISIONING_DIR
browser_policy_setup_group
for dir in "${BROWSER_POLICY_MANAGED_DIRS[@]}"; do
[[ -d $dir ]] || continue
browser_policy_setup_dir "$dir"
done
} }
install_authorized_keys() { install_authorized_keys() {
+10 -8
View File
@@ -13,11 +13,10 @@ else
THEME_HEX_COLOR="#1c2027" THEME_HEX_COLOR="#1c2027"
fi fi
set_browser_policy() { source "$OMARCHY_PATH/install/helpers/browser-policy.sh"
local policy_dir="$1"
[[ -d $policy_dir ]] || return set_browser_policy() {
echo "{\"BrowserThemeColor\": \"$THEME_HEX_COLOR\", \"BrowserColorScheme\": \"device\"}" | tee "$policy_dir/color.json" >/dev/null browser_policy_write_color "$1" "$THEME_HEX_COLOR"
} }
refresh_running_browser() { refresh_running_browser() {
@@ -30,17 +29,20 @@ refresh_running_browser() {
fi fi
} }
set_browser_policy /etc/chromium/policies/managed failed=0
set_browser_policy /etc/chromium/policies/managed || failed=1
refresh_running_browser chromium chromium refresh_running_browser chromium chromium
set_browser_policy /etc/opt/chrome/policies/managed set_browser_policy /etc/opt/chrome/policies/managed || failed=1
refresh_running_browser chrome google-chrome-stable || refresh_running_browser chrome google-chrome refresh_running_browser chrome google-chrome-stable || refresh_running_browser chrome google-chrome
set_browser_policy /etc/opt/edge/policies/managed set_browser_policy /etc/opt/edge/policies/managed || failed=1
refresh_running_browser msedge microsoft-edge-stable refresh_running_browser msedge microsoft-edge-stable
set_browser_policy /etc/brave/policies/managed set_browser_policy /etc/brave/policies/managed || failed=1
refresh_running_browser brave brave refresh_running_browser brave brave
# Match on the binary path: the running process is named plain "brave", and a # Match on the binary path: the running process is named plain "brave", and a
# bare -f brave-origin pattern would also match the installer's own terminal. # bare -f brave-origin pattern would also match the installer's own terminal.
refresh_running_browser /opt/brave-origin-bin/ brave-origin -f refresh_running_browser /opt/brave-origin-bin/ brave-origin -f
exit "$failed"
+21 -1
View File
@@ -1312,7 +1312,22 @@ apply_system_transition() {
/usr/share/icons/Yaru/scalable/actions/go-next-symbolic.svg /usr/share/icons/Yaru/scalable/actions/go-next-symbolic.svg
as_root gtk-update-icon-cache /usr/share/icons/Yaru >/dev/null 2>&1 || true as_root gtk-update-icon-cache /usr/share/icons/Yaru >/dev/null 2>&1 || true
as_root install -d -m 0777 /etc/chromium/policies/managed local browser_policy_helper=/usr/share/omarchy/install/helpers/browser-policy.sh
if ! as_root test -f "$browser_policy_helper"; then
warn "$browser_policy_helper is unavailable; Chromium policy directories were not hardened."
else
as_root env OMARCHY_PATH=/usr/share/omarchy OMARCHY_INSTALL_USER="$target_user" \
bash -euo pipefail -c '
source "$OMARCHY_PATH/install/helpers/browser-policy.sh"
browser_policy_setup_group
browser_policy_setup_dir /etc/chromium/policies/managed
for dir in "${BROWSER_POLICY_MANAGED_DIRS[@]}"; do
[[ $dir == "/etc/chromium/policies/managed" ]] && continue
[[ -d $dir ]] || continue
browser_policy_setup_dir "$dir"
done
'
fi
as_root install -d -m 0755 /usr/lib/chromium as_root install -d -m 0755 /usr/lib/chromium
printf '%s\n' '{"browser":{"theme":{"color_scheme":0,"color_scheme2":0}}}' | \ printf '%s\n' '{"browser":{"theme":{"color_scheme":0,"color_scheme2":0}}}' | \
as_root tee /usr/lib/chromium/initial_preferences >/dev/null as_root tee /usr/lib/chromium/initial_preferences >/dev/null
@@ -2306,6 +2321,11 @@ refresh_current_theme_after_upgrade() {
# hooks because one of them runs `hyprctl reload`. Still poke terminal # hooks because one of them runs `hyprctl reload`. Still poke terminal
# emulators so the active upgrade terminal picks up generated theme files. # emulators so the active upgrade terminal picks up generated theme files.
run_as_user_omarchy omarchy-restart-terminal >/dev/null 2>&1 || true run_as_user_omarchy omarchy-restart-terminal >/dev/null 2>&1 || true
# apply_system_transition purged user-owned color.json. Headless theme-set
# skipped omarchy-theme-set-browser, so rewrite the colour here.
run_as_user_omarchy omarchy-theme-set-browser >/dev/null 2>&1 ||
warn "Could not apply browser theme colour. Run 'omarchy theme set \"$theme_name\"' after reboot if Chromium's theme looks stale."
} }
# Everything below mutates the system, so a non-zero exit from here on leaves a # Everything below mutates the system, so a non-zero exit from here on leaves a
+1
View File
@@ -1,4 +1,5 @@
run_logged "$OMARCHY_INSTALL/config/theme-system.sh" run_logged "$OMARCHY_INSTALL/config/theme-system.sh"
run_logged "$OMARCHY_INSTALL/config/browser-policy.sh"
run_logged "$OMARCHY_INSTALL/config/increase-lockout-limit.sh" run_logged "$OMARCHY_INSTALL/config/increase-lockout-limit.sh"
run_logged "$OMARCHY_INSTALL/config/lockscreen-pam.sh" run_logged "$OMARCHY_INSTALL/config/lockscreen-pam.sh"
run_logged "$OMARCHY_INSTALL/config/fix-powerprofilesctl-shebang.sh" run_logged "$OMARCHY_INSTALL/config/fix-powerprofilesctl-shebang.sh"
+3
View File
@@ -0,0 +1,3 @@
source "$OMARCHY_PATH/install/helpers/browser-policy.sh"
browser_policy_setup_group
browser_policy_setup_dir /etc/chromium/policies/managed
-4
View File
@@ -6,10 +6,6 @@ ln -snf /usr/share/icons/Adwaita/symbolic/actions/go-next-symbolic.svg \
/usr/share/icons/Yaru/scalable/actions/go-next-symbolic.svg /usr/share/icons/Yaru/scalable/actions/go-next-symbolic.svg
gtk-update-icon-cache /usr/share/icons/Yaru &>/dev/null || true gtk-update-icon-cache /usr/share/icons/Yaru &>/dev/null || true
# Chromium policy directory for theme
mkdir -p /etc/chromium/policies/managed
chmod a+rw /etc/chromium/policies/managed
# Default Chromium to follow system appearance ("device") instead of dark # Default Chromium to follow system appearance ("device") instead of dark
mkdir -p /usr/lib/chromium mkdir -p /usr/lib/chromium
echo '{"browser":{"theme":{"color_scheme":0,"color_scheme2":0}}}' > \ echo '{"browser":{"theme":{"color_scheme":0,"color_scheme2":0}}}' > \
+7
View File
@@ -0,0 +1,7 @@
as_root() {
if (( EUID == 0 )); then
"$@"
else
sudo "$@"
fi
}
+171
View File
@@ -0,0 +1,171 @@
# Chromium-family machine policy is mandatory for every profile. A dedicated
# group at 2775 lets every Omarchy user write color.json and every other uid
# read; other-write stays off. Setgid so new files inherit the group.
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/as-root.sh"
BROWSER_POLICY_GROUP=omarchy-browser-policy
BROWSER_POLICY_MANAGED_DIRS=(
/etc/chromium/policies/managed
/etc/opt/chrome/policies/managed
/etc/opt/edge/policies/managed
/etc/brave/policies/managed
)
BROWSER_POLICY_FIREFOX_DIRS=(
/usr/lib/firefox/distribution
/opt/zen-browser/distribution
)
browser_policy_setup_group() {
local provisioning_dir="${OMARCHY_PROVISIONING_DIR:-/var/lib/omarchy/provisioning}"
as_root groupadd --system --force "$BROWSER_POLICY_GROUP"
as_root mkdir -p "$provisioning_dir"
if ! grep -qxF "$BROWSER_POLICY_GROUP" "$provisioning_dir/groups" 2>/dev/null; then
printf '%s\n' "$BROWSER_POLICY_GROUP" | as_root tee -a "$provisioning_dir/groups" >/dev/null
fi
if [[ -n ${OMARCHY_INSTALL_USER:-} ]] && getent passwd "$OMARCHY_INSTALL_USER" >/dev/null; then
as_root usermod -aG "$BROWSER_POLICY_GROUP" "$OMARCHY_INSTALL_USER"
fi
}
browser_policy_grant_user() {
local user=${1:-}
if [[ -z $user || $user == "root" ]]; then
user=${SUDO_USER:-}
fi
[[ -n $user && $user != "root" ]] || return 0
getent passwd "$user" >/dev/null || return 0
as_root usermod -aG "$BROWSER_POLICY_GROUP" "$user"
}
browser_policy_purge_dir() {
local dir=$1
as_root find "$dir" -mindepth 1 -maxdepth 1 ! -user root -exec rm -rf -- {} +
}
browser_policy_dir_hardened() {
local dir=$1
[[ -d $dir ]] || return 1
[[ $(stat -c '%a' "$dir") == "2775" ]] || return 1
[[ $(stat -c '%U' "$dir") == "root" ]] || return 1
[[ $(stat -c '%G' "$dir") == $BROWSER_POLICY_GROUP ]] || return 1
}
browser_policy_setup_dir() {
local dir=$1
as_root install -d -m 2775 -o root -g "$BROWSER_POLICY_GROUP" "$dir"
browser_policy_purge_dir "$dir"
}
browser_policy_file_owner() {
local user
if [[ -n ${OMARCHY_INSTALL_USER:-} && $OMARCHY_INSTALL_USER != "root" ]]; then
printf '%s\n' "$OMARCHY_INSTALL_USER"
return
fi
if [[ -n ${SUDO_USER:-} && $SUDO_USER != "root" ]]; then
printf '%s\n' "$SUDO_USER"
return
fi
if [[ -n ${PKEXEC_UID:-} ]]; then
user=$(getent passwd "$PKEXEC_UID" | cut -d: -f1)
if [[ -n $user && $user != "root" ]]; then
printf '%s\n' "$user"
return
fi
fi
user=${USER:-$(id -un)}
if [[ $user != "root" ]]; then
printf '%s\n' "$user"
fi
}
# sudo when this process has a controlling terminal (fd 0 is /dev/null under
# `bash -lc cmd &`, but /dev/tty still works). pkexec when it does not.
browser_policy_elevate() {
if (( EUID == 0 )); then
"$@"
elif { exec 3</dev/tty; } 2>/dev/null; then
exec 3<&-
sudo "$@"
else
pkexec "$@"
fi
}
browser_policy_write_color() {
local policy_dir=$1
local hex=$2
local dest=$policy_dir/color.json
local payload
local tmp
local owner
[[ -d $policy_dir ]] || return 0
payload=$(printf '{"BrowserThemeColor": "%s", "BrowserColorScheme": "device"}\n' "$hex")
tmp=$(mktemp) || return 1
printf '%s' "$payload" >"$tmp"
# A planted symlink or directory must not be written through or into.
if [[ -L $dest || -d $dest ]]; then
if ! rm -rf -- "$dest" 2>/dev/null; then
if ! browser_policy_elevate rm -rf -- "$dest"; then
rm -f "$tmp"
echo "omarchy-theme-set-browser: cannot replace $dest (need group $BROWSER_POLICY_GROUP)" >&2
return 1
fi
fi
fi
if install -m 664 -T "$tmp" "$dest" 2>/dev/null; then
rm -f "$tmp"
return 0
fi
owner=$(browser_policy_file_owner)
[[ -n $owner ]] || owner=root
if browser_policy_elevate install -m 664 -o "$owner" -g "$BROWSER_POLICY_GROUP" -T "$tmp" "$dest"; then
rm -f "$tmp"
return 0
fi
rm -f "$tmp"
echo "omarchy-theme-set-browser: cannot write $dest (need group $BROWSER_POLICY_GROUP)" >&2
return 1
}
browser_policy_firefox_hardened() {
local dir=$1
[[ -d $dir ]] || return 1
[[ $(stat -c '%a' "$dir") == "755" ]] || return 1
[[ $(stat -c '%U' "$dir") == "root" ]] || return 1
[[ -f $dir/policies.json && ! -L $dir/policies.json ]] || return 1
}
browser_policy_install_firefox_policies() {
local distribution_dir=$1
local policies=${2:-$OMARCHY_PATH/default/firefox/policies.json}
as_root install -m 644 -o root -g root -T "$policies" "$distribution_dir/policies.json"
}
browser_policy_setup_firefox_distribution() {
local distribution_dir=$1
local policies=${2:-$OMARCHY_PATH/default/firefox/policies.json}
as_root install -d -m 0755 -o root -g root "$distribution_dir"
browser_policy_purge_dir "$distribution_dir"
browser_policy_install_firefox_policies "$distribution_dir" "$policies"
}
+24
View File
@@ -0,0 +1,24 @@
echo "Stop world-writable Chromium and Firefox policy directories"
source "$OMARCHY_PATH/install/helpers/browser-policy.sh"
browser_policy_setup_group
browser_policy_grant_user "${USER:-$(id -un)}"
repaired=0
for dir in "${BROWSER_POLICY_MANAGED_DIRS[@]}"; do
[[ -d $dir ]] || continue
browser_policy_dir_hardened "$dir" && continue
browser_policy_setup_dir "$dir"
repaired=1
done
if (( repaired )); then
omarchy-theme-set-browser
fi
for dir in "${BROWSER_POLICY_FIREFOX_DIRS[@]}"; do
[[ -d $dir ]] || continue
browser_policy_firefox_hardened "$dir" && continue
browser_policy_setup_firefox_distribution "$dir"
done
+244
View File
@@ -0,0 +1,244 @@
#!/bin/bash
set -euo pipefail
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
test_tmp=$(mktemp -d)
trap 'rm -rf "$test_tmp"' EXIT
mock_bin=$test_tmp/bin
mkdir -p "$mock_bin"
elev_log=$test_tmp/elev.log
cat >"$mock_bin/sudo" <<SH
#!/bin/bash
printf 'SUDO %s\\n' "\$*" >>"$elev_log"
[[ \${OMARCHY_TEST_SUDO_FAIL:-} == 1 ]] && exit 1
exit 0
SH
cat >"$mock_bin/pkexec" <<SH
#!/bin/bash
printf 'PKEXEC %s\\n' "\$*" >>"$elev_log"
[[ \${OMARCHY_TEST_SUDO_FAIL:-} == 1 ]] && exit 1
exit 0
SH
chmod +x "$mock_bin/sudo" "$mock_bin/pkexec"
export PATH="$mock_bin:$PATH"
: >"$elev_log"
export OMARCHY_PATH="$ROOT"
export OMARCHY_PROVISIONING_DIR="$test_tmp/provisioning"
source "$ROOT/install/helpers/browser-policy.sh"
# Temp dirs are user-owned; drop -o/-g so install(1) can run unprivileged.
unprivileged_as_root() {
if [[ $1 == "install" ]]; then
shift
local args=()
local skip=0
local arg
for arg in "$@"; do
if (( skip )); then
skip=0
continue
fi
case $arg in
-o|-g) skip=1 ;;
*) args+=("$arg") ;;
esac
done
command install "${args[@]}"
else
"$@"
fi
}
write_dir=$test_tmp/writable
mkdir -p "$write_dir"
browser_policy_write_color "$write_dir" "#aabbcc" ||
fail "theme colour writes into a writable policy directory"
grep -F '"BrowserThemeColor": "#aabbcc"' "$write_dir/color.json" >/dev/null ||
fail "theme colour writes BrowserThemeColor"
mode=$(stat -c '%a' "$write_dir/color.json")
[[ $mode == "664" ]] || fail "theme colour creates a group-writable policy file" "mode=$mode"
pass "theme colour writes a group-writable color.json"
if (( EUID == 0 )); then
pass "running as root; skipping the mktemp-failure check"
else
chmod u+w "$write_dir"
export TMPDIR=$test_tmp/missing-tmp
if browser_policy_write_color "$write_dir" "#dead00" 2>/dev/null; then
fail "theme colour fails when mktemp cannot create a file"
fi
unset TMPDIR
grep -F '"BrowserThemeColor": "#aabbcc"' "$write_dir/color.json" >/dev/null ||
fail "a failed mktemp leaves an existing color.json intact"
pass "a failed mktemp does not truncate color.json"
fi
printf 'original\n' >"$test_tmp/pwn"
rm -f "$write_dir/color.json"
ln -s "$test_tmp/pwn" "$write_dir/color.json"
browser_policy_write_color "$write_dir" "#aabbcc" ||
fail "theme colour replaces a planted color.json symlink"
[[ -f $write_dir/color.json && ! -L $write_dir/color.json ]] ||
fail "theme colour unlinks a planted color.json symlink instead of writing through it"
grep -Fxq 'original' "$test_tmp/pwn" || fail "theme colour leaves the symlink target unchanged"
pass "theme colour does not follow a planted color.json symlink"
plant_write=$test_tmp/plant-dir
mkdir -p "$plant_write/color.json/nested"
printf 'inside\n' >"$plant_write/color.json/nested/x"
browser_policy_write_color "$plant_write" "#aabbcc" ||
fail "theme colour replaces a planted color.json directory"
[[ -f $plant_write/color.json && ! -d $plant_write/color.json ]] ||
fail "theme colour does not write into a planted color.json directory"
pass "theme colour does not write into a planted color.json directory"
missing_dir=$test_tmp/missing
browser_policy_write_color "$missing_dir" "#aabbcc" ||
fail "theme colour skips a policy directory that does not exist"
[[ ! -e $missing_dir ]] || fail "theme colour does not create a missing policy directory"
pass "theme colour skips a missing policy directory"
if (( EUID == 0 )); then
pass "running as root; skipping elevation checks"
else
denied_dir=$test_tmp/denied
mkdir -p "$denied_dir"
chmod a-w "$denied_dir"
owner=${USER:-$(id -un)}
: >"$elev_log"
browser_policy_write_color "$denied_dir" "#aabbcc" ||
fail "elevated install reports success from pkexec"
grep -E "^PKEXEC install -m 664 -o $owner -g omarchy-browser-policy -T .+ $denied_dir/color.json$" "$elev_log" >/dev/null ||
fail "without a controlling tty, colour write elevates through pkexec as the owner" "$(cat "$elev_log")"
if grep -E '^SUDO ' "$elev_log" >/dev/null; then
fail "without a controlling tty, colour write does not call sudo" "$(cat "$elev_log")"
fi
pass "without a controlling tty, colour write elevates through pkexec"
: >"$elev_log"
export OMARCHY_TEST_SUDO_FAIL=1
if browser_policy_write_color "$denied_dir" "#aabbcc" 2>"$test_tmp/write.err"; then
fail "theme colour fails when the policy directory is not writable"
fi
unset OMARCHY_TEST_SUDO_FAIL
grep -F 'omarchy-browser-policy' "$test_tmp/write.err" >/dev/null ||
fail "theme colour names the group when the write is denied"
pass "theme colour reports a denied policy write"
if command -v script >/dev/null; then
: >"$elev_log"
cat >"$test_tmp/tty-write.sh" <<EOF
source "$ROOT/install/helpers/browser-policy.sh"
browser_policy_write_color "$denied_dir" "#aabbcc"
EOF
script -q -c "PATH='$mock_bin:$PATH' OMARCHY_PATH='$ROOT' bash '$test_tmp/tty-write.sh'" /dev/null >/dev/null
grep -E "^SUDO install -m 664 -o $owner -g omarchy-browser-policy -T .+ $denied_dir/color.json$" "$elev_log" >/dev/null ||
fail "with a controlling tty, colour write elevates through sudo" "$(cat "$elev_log")"
if grep -E '^PKEXEC ' "$elev_log" >/dev/null; then
fail "with a controlling tty, colour write does not call pkexec" "$(cat "$elev_log")"
fi
pass "with a controlling tty, colour write elevates through sudo"
else
pass "script(1) unavailable; skipping the controlling-tty elevation check"
fi
fi
planted_dir=$test_tmp/planted
mkdir -p "$planted_dir/evil"
printf 'evil\n' >"$planted_dir/evil/f"
printf 'old\n' >"$planted_dir/color.json"
as_root() { unprivileged_as_root "$@"; }
browser_policy_setup_dir "$planted_dir"
[[ ! -e $planted_dir/evil ]] || fail "policy setup drops a non-empty non-root subdirectory"
[[ ! -e $planted_dir/color.json ]] || fail "policy setup drops a non-root color.json"
[[ -d $planted_dir ]] || fail "policy setup leaves the managed directory in place"
pass "policy setup drops non-root files and non-empty subdirectories"
owned=$test_tmp/not-root
mkdir -p "$owned"
chmod 2775 "$owned"
BROWSER_POLICY_GROUP=$(id -gn)
if browser_policy_dir_hardened "$owned"; then
fail "a user-owned 2775 directory is not treated as hardened"
fi
BROWSER_POLICY_GROUP=omarchy-browser-policy
pass "a hardened directory must be root-owned"
dist=$test_tmp/distribution
mkdir -p "$dist"
printf 'original\n' >"$test_tmp/firefox-pwn"
ln -s "$test_tmp/firefox-pwn" "$dist/policies.json"
as_root() { unprivileged_as_root "$@"; }
browser_policy_install_firefox_policies "$dist" ||
fail "Firefox policy install replaces a planted policies.json symlink"
[[ -f $dist/policies.json && ! -L $dist/policies.json ]] ||
fail "Firefox policy install unlinks a planted policies.json symlink instead of writing through it"
grep -Fxq 'original' "$test_tmp/firefox-pwn" || fail "Firefox policy install leaves the symlink target unchanged"
grep -q '"policies"' "$dist/policies.json" || fail "Firefox policy install writes the stock policies"
pass "Firefox policy install does not follow a planted policies.json symlink"
dir_dist=$test_tmp/distribution-dir
mkdir -p "$dir_dist"
mkdir "$dir_dist/policies.json"
as_root() { unprivileged_as_root "$@"; }
if browser_policy_install_firefox_policies "$dir_dist" 2>/dev/null; then
fail "Firefox policy install refuses a planted policies.json directory"
fi
[[ -d $dir_dist/policies.json ]] || fail "Firefox policy install leaves a planted policies.json directory in place"
pass "Firefox policy install does not write into a planted policies.json directory"
grant_log=$test_tmp/usermod.calls
as_root() {
if [[ $1 == "usermod" ]]; then
printf '%s\n' "$*" >>"$grant_log"
return 0
fi
unprivileged_as_root "$@"
}
invoker=${USER:-$(id -un)}
: >"$grant_log"
SUDO_USER=$invoker
browser_policy_grant_user root
unset SUDO_USER
grep -qx -- "usermod -aG omarchy-browser-policy $invoker" "$grant_log" ||
fail "granting as root uses SUDO_USER" "$(cat "$grant_log")"
: >"$grant_log"
OMARCHY_INSTALL_USER=""
browser_policy_grant_user ""
[[ ! -s $grant_log ]] || fail "an empty grant does not usermod"
pass "sudo install browser grants the invoking user, not root"
grep -F 'exit "$failed"' "$ROOT/bin/omarchy-theme-set-browser" >/dev/null ||
fail "omarchy-theme-set-browser exits non-zero when a policy write fails"
pass "omarchy-theme-set-browser exits non-zero when a policy write fails"
policy_files=(
"$ROOT/bin/omarchy-install-browser"
"$ROOT/bin/omarchy-provision-owner"
"$ROOT/bin/omarchy-theme-set-browser"
"$ROOT/bin/omarchy-upgrade-to-quattro"
"$ROOT/install/config/theme-system.sh"
"$ROOT/install/config/browser-policy.sh"
"$ROOT/install/helpers/browser-policy.sh"
"$ROOT/migrations/1787515927.sh"
)
if grep -nE 'chmod a\+rwx\b|chmod a\+rw\b|chmod a\+w\b|chmod o\+w|chmod ugo\+w|chmod 2777\b|chmod 0777\b|chmod 777\b|install -d -m 0?[27]?777' "${policy_files[@]}" >/dev/null; then
fail "browser policy setup is not world-writable"
fi
pass "browser policy setup is not world-writable"
mapfile -t migrations < <(rg -l 'Stop world-writable Chromium and Firefox policy directories' "$ROOT/migrations")
(( ${#migrations[@]} == 1 )) || fail "exactly one migration locks existing policy directories" "${migrations[*]}"
grep -F 'browser_policy_dir_hardened' "${migrations[0]}" >/dev/null ||
fail "the policy-directory migration no-ops a machine already repaired"
grep -F 'browser_policy_grant_user' "${migrations[0]}" >/dev/null ||
fail "the policy-directory migration still grants the current user the group"
grep -F 'BROWSER_POLICY_FIREFOX_DIRS' "${migrations[0]}" >/dev/null ||
fail "the policy-directory migration covers Firefox and Zen"
grep -F '/opt/zen-browser/distribution' "$ROOT/install/helpers/browser-policy.sh" >/dev/null ||
fail "the shared helper names the Zen distribution directory"
pass "a migration locks existing policy directories"
+42 -5
View File
@@ -61,11 +61,13 @@ if [[ $installer == "omarchy-install-browser" && ${OMARCHY_TEST_REAL_BROWSER_INS
fi fi
case $installer in case $installer in
omarchy-pkg-add) omarchy-pkg-add|omarchy-pkg-aur-add)
package=$1 package=$1
printf 'pkg:%s\n' "$package" >>"$OMARCHY_TEST_INSTALL_LOG" printf 'pkg:%s\n' "$package" >>"$OMARCHY_TEST_INSTALL_LOG"
case $package in case $package in
chromium) command=chromium ;; chromium) command=chromium ;;
firefox) command=firefox ;;
zen-browser-bin) command=zen-browser ;;
cursor-bin) command=cursor ;; cursor-bin) command=cursor ;;
sublime-text-4) command=sublime_text ;; sublime-text-4) command=sublime_text ;;
vim) command=vim ;; vim) command=vim ;;
@@ -107,6 +109,7 @@ SH
for installer in \ for installer in \
omarchy-pkg-add \ omarchy-pkg-add \
omarchy-pkg-aur-add \
omarchy-install-browser \ omarchy-install-browser \
omarchy-install-terminal \ omarchy-install-terminal \
omarchy-install-editor-vscode \ omarchy-install-editor-vscode \
@@ -205,10 +208,14 @@ OMARCHY_TEST_REAL_BROWSER_INSTALL=true omarchy-default-browser --install chromiu
[[ $(omarchy-default-browser) == "chromium" ]] || fail "Chromium becomes the default after its full installer succeeds" [[ $(omarchy-default-browser) == "chromium" ]] || fail "Chromium becomes the default after its full installer succeeds"
cmp -s "$ROOT/config/chromium-flags.conf" "$test_home/.config/chromium-flags.conf" || cmp -s "$ROOT/config/chromium-flags.conf" "$test_home/.config/chromium-flags.conf" ||
fail "Chromium browser installer copies the default flags" fail "Chromium browser installer copies the default flags"
grep -Fxq 'sudo:mkdir -p /etc/chromium/policies/managed' "$setup_log" || grep -Fxq 'sudo:groupadd --system --force omarchy-browser-policy' "$setup_log" ||
fail "Chromium browser installer creates its policy directory" fail "Chromium browser installer creates the browser-policy group"
grep -Fxq 'sudo:chmod a+rw /etc/chromium/policies/managed' "$setup_log" || grep -Fxq 'sudo:install -d -m 2775 -o root -g omarchy-browser-policy /etc/chromium/policies/managed' "$setup_log" ||
fail "Chromium browser installer makes its policy directory writable" fail "Chromium browser installer creates a group-writable managed policy directory"
grep -Fxq 'sudo:find /etc/chromium/policies/managed -mindepth 1 -maxdepth 1 ! -user root -exec rm -rf -- {} +' "$setup_log" ||
fail "Chromium browser installer drops non-root files from its policy directory"
grep -Fxq "sudo:usermod -aG omarchy-browser-policy ${USER:-$(id -un)}" "$setup_log" ||
fail "Chromium browser installer grants the installing user the browser-policy group"
grep -Fxq 'omarchy-install-chromium-copy-url:' "$setup_log" || grep -Fxq 'omarchy-install-chromium-copy-url:' "$setup_log" ||
fail "Chromium browser installer registers the Copy URL host" fail "Chromium browser installer registers the Copy URL host"
grep -Fxq 'omarchy-install-chromium-ytdlp:' "$setup_log" || grep -Fxq 'omarchy-install-chromium-ytdlp:' "$setup_log" ||
@@ -217,6 +224,36 @@ grep -Fxq 'omarchy-theme-set-browser:' "$setup_log" ||
fail "Chromium browser installer applies the current theme" fail "Chromium browser installer applies the current theme"
pass "Chromium browser installer restores the complete Omarchy setup" pass "Chromium browser installer restores the complete Omarchy setup"
: >"$install_log"
: >"$setup_log"
rm -f "$installed_dir/firefox"
OMARCHY_TEST_REAL_BROWSER_INSTALL=true omarchy-default-browser --install firefox >/dev/null
[[ $(<"$install_log") == "pkg:firefox" ]] || fail "Firefox browser installer installs the package"
[[ $(omarchy-default-browser) == "firefox" ]] || fail "Firefox becomes the default after its full installer succeeds"
grep -Fxq 'sudo:install -d -m 0755 -o root -g root /usr/lib/firefox/distribution' "$setup_log" ||
fail "Firefox browser installer creates its distribution directory"
grep -Fxq 'sudo:find /usr/lib/firefox/distribution -mindepth 1 -maxdepth 1 ! -user root -exec rm -rf -- {} +' "$setup_log" ||
fail "Firefox browser installer drops non-root files from its distribution directory"
grep -Fxq "sudo:install -m 644 -o root -g root -T $ROOT/default/firefox/policies.json /usr/lib/firefox/distribution/policies.json" "$setup_log" ||
fail "Firefox browser installer copies policies.json without following a destination symlink"
[[ -e $installed_dir/firefox ]] || fail "Firefox browser installer marks firefox installed"
pass "Firefox browser installer restores the complete Omarchy setup"
: >"$install_log"
: >"$setup_log"
rm -f "$installed_dir/zen-browser"
OMARCHY_TEST_REAL_BROWSER_INSTALL=true omarchy-default-browser --install zen >/dev/null
[[ $(<"$install_log") == "pkg:zen-browser-bin" ]] || fail "Zen browser installer installs the package"
[[ $(omarchy-default-browser) == "zen" ]] || fail "Zen becomes the default after its full installer succeeds"
grep -Fxq 'sudo:install -d -m 0755 -o root -g root /opt/zen-browser/distribution' "$setup_log" ||
fail "Zen browser installer creates its distribution directory"
grep -Fxq 'sudo:find /opt/zen-browser/distribution -mindepth 1 -maxdepth 1 ! -user root -exec rm -rf -- {} +' "$setup_log" ||
fail "Zen browser installer drops non-root files from its distribution directory"
grep -Fxq "sudo:install -m 644 -o root -g root -T $ROOT/default/firefox/policies.json /opt/zen-browser/distribution/policies.json" "$setup_log" ||
fail "Zen browser installer copies policies.json without following a destination symlink"
[[ -e $installed_dir/zen-browser ]] || fail "Zen browser installer marks zen-browser installed"
pass "Zen browser installer restores the complete Omarchy setup"
omarchy-default-browser zen omarchy-default-browser zen
rm -f "$installed_dir/chromium" rm -f "$installed_dir/chromium"
if OMARCHY_TEST_REAL_BROWSER_INSTALL=true OMARCHY_TEST_INSTALL_FAIL=true \ if OMARCHY_TEST_REAL_BROWSER_INSTALL=true OMARCHY_TEST_INSTALL_FAIL=true \
+34 -3
View File
@@ -27,16 +27,40 @@ cat >"$TMPDIR/bin/usermod" <<STUB
#!/bin/bash #!/bin/bash
echo "\$@" >>"$TMPDIR/usermod.calls" echo "\$@" >>"$TMPDIR/usermod.calls"
STUB STUB
chmod +x "$TMPDIR/bin/getent" "$TMPDIR/bin/usermod" cat >"$TMPDIR/bin/groupadd" <<STUB
#!/bin/bash
echo "\$@" >>"$TMPDIR/groupadd.calls"
STUB
cat >"$TMPDIR/bin/install" <<STUB
#!/bin/bash
echo "\$@" >>"$TMPDIR/install.calls"
STUB
cat >"$TMPDIR/bin/find" <<STUB
#!/bin/bash
echo "\$@" >>"$TMPDIR/find.calls"
STUB
cat >"$TMPDIR/bin/sudo" <<STUB
#!/bin/bash
echo "\$@" >>"$TMPDIR/sudo.calls"
exec "\$@"
STUB
chmod +x "$TMPDIR/bin"/{getent,usermod,groupadd,install,find,sudo}
export PATH="$TMPDIR/bin:$PATH" export PATH="$TMPDIR/bin:$PATH"
export OMARCHY_PATH="$ROOT"
# No install user (deferred-provisioning install): input recorded, usermod not called. # No install user (deferred-provisioning install): groups recorded, usermod not called.
OMARCHY_INSTALL_USER="" bash -eE "$ROOT/install/config/docker.sh" OMARCHY_INSTALL_USER="" bash -eE "$ROOT/install/config/docker.sh"
OMARCHY_INSTALL_USER="" bash -eE "$ROOT/install/hardware/input-group.sh" OMARCHY_INSTALL_USER="" bash -eE "$ROOT/install/hardware/input-group.sh"
OMARCHY_INSTALL_USER="" bash -eE "$ROOT/install/config/browser-policy.sh"
[[ -f $OMARCHY_PROVISIONING_DIR/groups ]] || fail "groups file written without an install user" [[ -f $OMARCHY_PROVISIONING_DIR/groups ]] || fail "groups file written without an install user"
grep -qxF input "$OMARCHY_PROVISIONING_DIR/groups" || fail "input group recorded" grep -qxF input "$OMARCHY_PROVISIONING_DIR/groups" || fail "input group recorded"
grep -qxF omarchy-browser-policy "$OMARCHY_PROVISIONING_DIR/groups" || fail "browser-policy group recorded"
[[ ! -f $TMPDIR/usermod.calls ]] || fail "usermod not called without an install user" [[ ! -f $TMPDIR/usermod.calls ]] || fail "usermod not called without an install user"
grep -F -- '--system --force omarchy-browser-policy' "$TMPDIR/groupadd.calls" >/dev/null ||
fail "browser-policy group is created as a system group"
grep -F -- '-d -m 2775 -o root -g omarchy-browser-policy /etc/chromium/policies/managed' "$TMPDIR/install.calls" >/dev/null ||
fail "browser-policy directory is created group-writable"
pass "deferred provisioning records groups without calling usermod" pass "deferred provisioning records groups without calling usermod"
# The docker group is root-equivalent and must never be granted automatically. # The docker group is root-equivalent and must never be granted automatically.
@@ -45,17 +69,24 @@ pass "docker group is not recorded at install"
# Missing user (defensive): no usermod either. # Missing user (defensive): no usermod either.
OMARCHY_INSTALL_USER=ghost bash -eE "$ROOT/install/hardware/input-group.sh" OMARCHY_INSTALL_USER=ghost bash -eE "$ROOT/install/hardware/input-group.sh"
OMARCHY_INSTALL_USER=ghost bash -eE "$ROOT/install/config/browser-policy.sh"
[[ ! -f $TMPDIR/usermod.calls ]] || fail "usermod not called for a missing user" [[ ! -f $TMPDIR/usermod.calls ]] || fail "usermod not called for a missing user"
pass "missing install user defers group grants" pass "missing install user defers group grants"
# Re-running never duplicates entries. # Re-running never duplicates entries.
OMARCHY_INSTALL_USER="" bash -eE "$ROOT/install/hardware/input-group.sh" OMARCHY_INSTALL_USER="" bash -eE "$ROOT/install/hardware/input-group.sh"
[[ $(grep -cxF input "$OMARCHY_PROVISIONING_DIR/groups") == 1 ]] || fail "input group recorded once" [[ $(grep -cxF input "$OMARCHY_PROVISIONING_DIR/groups") == 1 ]] || fail "input group recorded once"
OMARCHY_INSTALL_USER="" bash -eE "$ROOT/install/config/browser-policy.sh"
[[ $(grep -cxF omarchy-browser-policy "$OMARCHY_PROVISIONING_DIR/groups") == 1 ]] ||
fail "browser-policy group recorded once"
pass "group recording is idempotent" pass "group recording is idempotent"
# Existing user: usermod applies the recorded groups, and docker is never among them. # Existing user: usermod applies the recorded groups, and docker is never among them.
OMARCHY_INSTALL_USER=existing bash -eE "$ROOT/install/config/docker.sh" OMARCHY_INSTALL_USER=existing bash -eE "$ROOT/install/config/docker.sh"
OMARCHY_INSTALL_USER=existing bash -eE "$ROOT/install/hardware/input-group.sh" OMARCHY_INSTALL_USER=existing bash -eE "$ROOT/install/hardware/input-group.sh"
OMARCHY_INSTALL_USER=existing bash -eE "$ROOT/install/config/browser-policy.sh"
grep -qx -- "-aG input existing" "$TMPDIR/usermod.calls" || fail "usermod grants input to the install user" grep -qx -- "-aG input existing" "$TMPDIR/usermod.calls" || fail "usermod grants input to the install user"
grep -qx -- "-aG omarchy-browser-policy existing" "$TMPDIR/usermod.calls" ||
fail "usermod grants browser-policy to the install user"
! grep -q -- "docker" "$TMPDIR/usermod.calls" || fail "usermod must not grant docker to the install user" ! grep -q -- "docker" "$TMPDIR/usermod.calls" || fail "usermod must not grant docker to the install user"
pass "existing install user gets input but never docker" pass "existing install user gets input and browser-policy but never docker"
+17
View File
@@ -67,6 +67,23 @@ grep -F 'OMARCHY_INSTALL_USER="$target_user"' "$upgrade_to_quattro" >/dev/null
grep -F '"$apply_lock"' "$upgrade_to_quattro" >/dev/null grep -F '"$apply_lock"' "$upgrade_to_quattro" >/dev/null
pass "Omarchy 4 upgrade configures lock screen authentication for the target user" pass "Omarchy 4 upgrade configures lock screen authentication for the target user"
grep -F 'install/helpers/browser-policy.sh' "$upgrade_to_quattro" >/dev/null ||
fail "Omarchy 4 upgrade uses the shared browser-policy helper"
grep -F 'as_root test -f "$browser_policy_helper"' "$upgrade_to_quattro" >/dev/null ||
fail "Omarchy 4 upgrade survives a packaged tree without the browser-policy helper"
grep -F 'browser_policy_setup_group' "$upgrade_to_quattro" >/dev/null ||
fail "Omarchy 4 upgrade creates the browser-policy group"
grep -F 'browser_policy_setup_dir /etc/chromium/policies/managed' "$upgrade_to_quattro" >/dev/null ||
fail "Omarchy 4 upgrade creates a group-writable Chromium policy directory"
grep -F 'BROWSER_POLICY_MANAGED_DIRS' "$upgrade_to_quattro" >/dev/null ||
fail "Omarchy 4 upgrade hardens every Chromium-family policy directory"
grep -F 'run_as_user_omarchy omarchy-theme-set-browser' "$upgrade_to_quattro" >/dev/null ||
fail "Omarchy 4 upgrade rewrites browser theme colour after a headless theme-set"
if grep -E 'install -d -m 0?[27]?777 /etc/.*/policies|chmod a\+rw' "$upgrade_to_quattro" >/dev/null; then
fail "Omarchy 4 upgrade does not create a world-writable Chromium policy directory"
fi
pass "Omarchy 4 upgrade locks the Chromium policy directory to the browser-policy group"
grep -F 'OMARCHY_UPGRADE_TO_QUATTRO_LIVE=1' "$upgrade_to_quattro" >/dev/null grep -F 'OMARCHY_UPGRADE_TO_QUATTRO_LIVE=1' "$upgrade_to_quattro" >/dev/null
grep -F 'systemd-networkd.service' "$upgrade_to_quattro" >/dev/null grep -F 'systemd-networkd.service' "$upgrade_to_quattro" >/dev/null
grep -F 'systemd-networkd.socket' "$upgrade_to_quattro" >/dev/null grep -F 'systemd-networkd.socket' "$upgrade_to_quattro" >/dev/null