Skip to content

Commit 7d58bb9

Browse files
authored
Merge pull request #7972 from acrogenesis/harden-browser-policy-dirs
Stop world-writable browser policy directories
2 parents 6dd9aa5 + bafc9a1 commit 7d58bb9

17 files changed

Lines changed: 968 additions & 49 deletions

bin/omarchy-install-browser

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66

77
set -e
88

9-
setup_policy_directory() {
10-
sudo mkdir -p "$1"
11-
sudo chmod a+rw "$1"
9+
source "$OMARCHY_PATH/install/helpers/browser-policy.sh"
10+
11+
setup_chromium_policy_directory() {
12+
browser_policy_setup_dir "$1"
1213
}
1314

1415
announce_browser_installed() {
@@ -23,13 +24,6 @@ copy_chromium_flags() {
2324
omarchy-install-chromium-ytdlp
2425
}
2526

26-
setup_firefox_preferences() {
27-
local distribution_dir="$1"
28-
29-
setup_policy_directory "$distribution_dir"
30-
sudo cp -f "$OMARCHY_PATH/default/firefox/policies.json" "$distribution_dir/policies.json"
31-
}
32-
3327
setup_firefox_wayland() {
3428
mkdir -p ~/.config/environment.d
3529
echo "MOZ_ENABLE_WAYLAND=1" > ~/.config/environment.d/omarchy-firefox-wayland.conf
@@ -40,7 +34,7 @@ chromium)
4034
echo "Installing Chromium..."
4135
omarchy-pkg-add chromium
4236

43-
setup_policy_directory /etc/chromium/policies/managed
37+
setup_chromium_policy_directory /etc/chromium/policies/managed
4438
copy_chromium_flags ~/.config/chromium-flags.conf
4539
omarchy-theme-set-browser
4640
announce_browser_installed "Chromium"
@@ -49,7 +43,7 @@ chrome)
4943
echo "Installing Chrome..."
5044
omarchy-pkg-aur-add google-chrome || exit 1
5145

52-
setup_policy_directory /etc/opt/chrome/policies/managed
46+
setup_chromium_policy_directory /etc/opt/chrome/policies/managed
5347
copy_chromium_flags ~/.config/chrome-flags.conf
5448
omarchy-theme-set-browser
5549
announce_browser_installed "Chrome"
@@ -58,7 +52,7 @@ edge)
5852
echo "Installing Edge..."
5953
omarchy-pkg-aur-add microsoft-edge-stable-bin || exit 1
6054

61-
setup_policy_directory /etc/opt/edge/policies/managed
55+
setup_chromium_policy_directory /etc/opt/edge/policies/managed
6256
copy_chromium_flags ~/.config/microsoft-edge-stable-flags.conf
6357
omarchy-theme-set-browser
6458
announce_browser_installed "Edge"
@@ -67,7 +61,7 @@ brave)
6761
echo "Installing Brave..."
6862
omarchy-pkg-aur-add brave-bin || exit 1
6963

70-
setup_policy_directory /etc/brave/policies/managed
64+
setup_chromium_policy_directory /etc/brave/policies/managed
7165
copy_chromium_flags ~/.config/brave-flags.conf
7266
omarchy-theme-set-browser
7367
announce_browser_installed "Brave"
@@ -76,7 +70,7 @@ brave-origin)
7670
echo "Installing Brave Origin..."
7771
omarchy-pkg-aur-add brave-origin-bin || exit 1
7872

79-
setup_policy_directory /etc/brave/policies/managed
73+
setup_chromium_policy_directory /etc/brave/policies/managed
8074
copy_chromium_flags ~/.config/brave-origin-flags.conf
8175
omarchy-theme-set-browser
8276
announce_browser_installed "Brave Origin"
@@ -85,15 +79,15 @@ firefox)
8579
echo "Installing Firefox..."
8680
omarchy-pkg-add firefox || exit 1
8781

88-
setup_firefox_preferences /usr/lib/firefox/distribution
82+
browser_policy_setup_firefox_distribution /usr/lib/firefox/distribution
8983
setup_firefox_wayland
9084
announce_browser_installed "Firefox"
9185
;;
9286
zen)
9387
echo "Installing Zen..."
9488
omarchy-pkg-aur-add zen-browser-bin || exit 1
9589

96-
setup_firefox_preferences /opt/zen-browser/distribution
90+
browser_policy_setup_firefox_distribution /opt/zen-browser/distribution
9791
setup_firefox_wayland
9892
announce_browser_installed "Zen"
9993
;;

bin/omarchy-provision-owner

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,12 @@ create_user() {
742742
# for specific commands), and a duplicate grant is harmless.
743743
echo "%wheel ALL=(ALL:ALL) ALL" >/etc/sudoers.d/00-omarchy-wheel
744744
chmod 440 /etc/sudoers.d/00-omarchy-wheel
745+
746+
source "$OMARCHY_PATH/install/helpers/browser-policy.sh"
747+
for dir in "${BROWSER_POLICY_MANAGED_DIRS[@]}"; do
748+
[[ -d $dir || -L $dir ]] || continue
749+
browser_policy_setup_dir "$dir"
750+
done
745751
}
746752

747753
install_authorized_keys() {

bin/omarchy-theme-set-browser

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,15 @@
33
# omarchy:summary=Apply the current theme color to Chromium, Chrome, Edge, and Brave
44
# omarchy:hidden=true
55

6+
source "$OMARCHY_PATH/install/helpers/browser-policy.sh"
7+
68
CHROMIUM_THEME=$HOME/.local/state/omarchy/current/theme/chromium.theme
9+
THEME_HEX_COLOR=$BROWSER_POLICY_DEFAULT_COLOR
710

811
if [[ -f $CHROMIUM_THEME ]]; then
9-
THEME_RGB_COLOR=$(<$CHROMIUM_THEME)
10-
THEME_HEX_COLOR=$(printf '#%02x%02x%02x' ${THEME_RGB_COLOR//,/ })
11-
else
12-
# Use a default, neutral grey if theme doesn't have a color
13-
THEME_HEX_COLOR="#1c2027"
12+
THEME_HEX_COLOR=$(browser_policy_theme_hex "$(<$CHROMIUM_THEME)")
1413
fi
1514

16-
set_browser_policy() {
17-
local policy_dir="$1"
18-
19-
[[ -d $policy_dir ]] || return
20-
echo "{\"BrowserThemeColor\": \"$THEME_HEX_COLOR\", \"BrowserColorScheme\": \"device\"}" | tee "$policy_dir/color.json" >/dev/null
21-
}
22-
2315
refresh_running_browser() {
2416
local process="$1"
2517
local command="$2"
@@ -30,17 +22,15 @@ refresh_running_browser() {
3022
fi
3123
}
3224

33-
set_browser_policy /etc/chromium/policies/managed
34-
refresh_running_browser chromium chromium
25+
failed=0
26+
omarchy-theme-set-browser-policy "${THEME_HEX_COLOR#\#}" || failed=1
3527

36-
set_browser_policy /etc/opt/chrome/policies/managed
28+
refresh_running_browser chromium chromium
3729
refresh_running_browser chrome google-chrome-stable || refresh_running_browser chrome google-chrome
38-
39-
set_browser_policy /etc/opt/edge/policies/managed
4030
refresh_running_browser msedge microsoft-edge-stable
41-
42-
set_browser_policy /etc/brave/policies/managed
4331
refresh_running_browser brave brave
4432
# Match on the binary path: the running process is named plain "brave", and a
4533
# bare -f brave-origin pattern would also match the installer's own terminal.
4634
refresh_running_browser /opt/brave-origin-bin/ brave-origin -f
35+
36+
exit "$failed"
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#!/bin/bash
2+
3+
# omarchy:summary=Write the current theme color into the browser policy directories
4+
# omarchy:args=<rrggbb>
5+
# omarchy:hidden=true
6+
7+
set -euo pipefail
8+
9+
# Whenever this runs as root — invoked directly through the passwordless
10+
# sudoers rule, or re-execed by require_root below — sudo's secure_path decides
11+
# where a bare helper resolves, and a dev link (etc/sudoers.d/omarchy-dev-path)
12+
# prepends a user-writable checkout bin/ to it. Every helper this script calls
13+
# by bare name (printf's builtin aside: install, mktemp, rm) is a system tool,
14+
# never an omarchy-* command, so pin PATH to trusted system directories and keep
15+
# root from resolving one out of that checkout. The unprivileged wrapper phase
16+
# keeps the caller's PATH so it can still find sudo/pkexec.
17+
if (( EUID == 0 )); then
18+
export PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin
19+
fi
20+
21+
# Enterprise policy trust roots. The list is fixed here rather than taken from
22+
# the caller: the caller chooses a color, never a path.
23+
POLICY_DIRS=(
24+
/etc/chromium/policies/managed
25+
/etc/opt/chrome/policies/managed
26+
/etc/opt/edge/policies/managed
27+
/etc/brave/policies/managed
28+
)
29+
30+
# The path etc/sudoers.d/omarchy-theme-browser names. The privileged half always
31+
# runs from there rather than from whichever copy was invoked, so the rule
32+
# matches even where $OMARCHY_PATH points at a checkout.
33+
PACKAGED_PATH=/usr/bin/omarchy-theme-set-browser-policy
34+
35+
usage() {
36+
echo "Usage: omarchy-theme-set-browser-policy <rrggbb>" >&2
37+
}
38+
39+
if (( $# != 1 )); then
40+
usage
41+
exit 1
42+
fi
43+
44+
color="$1"
45+
46+
# Six lowercase hex digits is the whole of what this accepts. The leading "#"
47+
# is added when the JSON is written rather than passed in: "#" opens a comment
48+
# in sudoers, and keeping it out of argv lets the sudoers rule spell the
49+
# argument as a plain six-character glob.
50+
if [[ ! $color =~ ^[0-9a-f]{6}$ ]]; then
51+
echo "omarchy-theme-set-browser-policy: expected six lowercase hex digits, got '$color'" >&2
52+
exit 1
53+
fi
54+
55+
# True when sudo would run this exact command without stopping for a password.
56+
# `sudo -l` on its own reports whether a command is permitted, which the blanket
57+
# %wheel rule answers yes to for everything; the long listing prints the matched
58+
# entry's tags, so !authenticate is the grant in
59+
# etc/sudoers.d/omarchy-theme-browser and nothing else. Listing runs nothing
60+
# and, under -n, prompts for nothing.
61+
sudo_grants_passwordless() {
62+
sudo -n -l -l "$PACKAGED_PATH" "$@" 2>/dev/null | grep -q '!authenticate'
63+
}
64+
65+
require_root() {
66+
if (( EUID == 0 )); then
67+
return
68+
elif [[ -t 0 ]] || sudo_grants_passwordless "$@"; then
69+
exec sudo "$PACKAGED_PATH" "$@"
70+
else
71+
exec pkexec "$PACKAGED_PATH" "$@"
72+
fi
73+
}
74+
75+
require_root "$color"
76+
77+
failed=0
78+
staged=""
79+
cleanup() {
80+
[[ -n $staged ]] && rm -f "$staged"
81+
}
82+
trap cleanup EXIT
83+
84+
for policy_dir in "${POLICY_DIRS[@]}"; do
85+
# Only browsers Omarchy has installed have a policy directory. Creating one
86+
# here would hand a browser a managed-policy root it does not otherwise have.
87+
[[ -d $policy_dir && ! -L $policy_dir ]] || continue
88+
89+
dest=$policy_dir/color.json
90+
staged=$(mktemp) || {
91+
failed=1
92+
continue
93+
}
94+
printf '{"BrowserThemeColor": "#%s", "BrowserColorScheme": "device"}\n' "$color" >"$staged"
95+
96+
if [[ -L $dest || -d $dest ]]; then
97+
if ! rm -rf -- "$dest"; then
98+
rm -f "$staged"
99+
staged=""
100+
echo "omarchy-theme-set-browser-policy: cannot replace $dest" >&2
101+
failed=1
102+
continue
103+
fi
104+
fi
105+
106+
if ! install -m 0644 -o root -g root -T "$staged" "$dest"; then
107+
rm -f "$staged"
108+
staged=""
109+
echo "omarchy-theme-set-browser-policy: cannot write $dest" >&2
110+
failed=1
111+
continue
112+
fi
113+
114+
rm -f "$staged"
115+
staged=""
116+
done
117+
118+
exit "$failed"

bin/omarchy-upgrade-to-quattro

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1312,7 +1312,21 @@ apply_system_transition() {
13121312
/usr/share/icons/Yaru/scalable/actions/go-next-symbolic.svg
13131313
as_root gtk-update-icon-cache /usr/share/icons/Yaru >/dev/null 2>&1 || true
13141314

1315-
as_root install -d -m 0777 /etc/chromium/policies/managed
1315+
local browser_policy_helper=/usr/share/omarchy/install/helpers/browser-policy.sh
1316+
if ! as_root test -f "$browser_policy_helper"; then
1317+
warn "$browser_policy_helper is unavailable; Chromium policy directories were not hardened."
1318+
else
1319+
as_root env OMARCHY_PATH=/usr/share/omarchy \
1320+
bash -euo pipefail -c '
1321+
source "$OMARCHY_PATH/install/helpers/browser-policy.sh"
1322+
browser_policy_setup_dir /etc/chromium/policies/managed
1323+
for dir in "${BROWSER_POLICY_MANAGED_DIRS[@]}"; do
1324+
[[ $dir == "/etc/chromium/policies/managed" ]] && continue
1325+
[[ -d $dir || -L $dir ]] || continue
1326+
browser_policy_setup_dir "$dir"
1327+
done
1328+
'
1329+
fi
13161330
as_root install -d -m 0755 /usr/lib/chromium
13171331
printf '%s\n' '{"browser":{"theme":{"color_scheme":0,"color_scheme2":0}}}' | \
13181332
as_root tee /usr/lib/chromium/initial_preferences >/dev/null
@@ -2306,6 +2320,11 @@ refresh_current_theme_after_upgrade() {
23062320
# hooks because one of them runs `hyprctl reload`. Still poke terminal
23072321
# emulators so the active upgrade terminal picks up generated theme files.
23082322
run_as_user_omarchy omarchy-restart-terminal >/dev/null 2>&1 || true
2323+
2324+
# apply_system_transition purged user-owned color.json. Headless theme-set
2325+
# skipped omarchy-theme-set-browser, so rewrite the colour here.
2326+
run_as_user_omarchy omarchy-theme-set-browser >/dev/null 2>&1 ||
2327+
warn "Could not apply browser theme colour. Run 'omarchy theme set \"$theme_name\"' after reboot if Chromium's theme looks stale."
23092328
}
23102329

23112330
# Everything below mutates the system, so a non-zero exit from here on leaves a
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Theme switching is a menu action with no terminal to carry a password prompt,
2+
# and it repaints the browser accent on every switch, so this one write must not
3+
# stop for a password. The argument is spelled out as six hex digits rather than
4+
# a wildcard: the grant covers a color and nothing else, and sudoers matches a
5+
# command's arguments exactly, so it cannot be stretched into extra ones. The
6+
# helper revalidates the same shape, since the terminal path does not come
7+
# through this rule.
8+
%wheel ALL=(root) NOPASSWD: /usr/bin/omarchy-theme-set-browser-policy [0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]

install/config/all.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
run_logged "$OMARCHY_INSTALL/config/theme-system.sh"
2+
run_logged "$OMARCHY_INSTALL/config/browser-policy.sh"
23
run_logged "$OMARCHY_INSTALL/config/increase-lockout-limit.sh"
34
run_logged "$OMARCHY_INSTALL/config/lockscreen-pam.sh"
45
run_logged "$OMARCHY_INSTALL/config/fix-powerprofilesctl-shebang.sh"

install/config/browser-policy.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
source "$OMARCHY_PATH/install/helpers/browser-policy.sh"
2+
browser_policy_setup_dir /etc/chromium/policies/managed

install/config/theme-system.sh

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@ ln -snf /usr/share/icons/Adwaita/symbolic/actions/go-next-symbolic.svg \
66
/usr/share/icons/Yaru/scalable/actions/go-next-symbolic.svg
77
gtk-update-icon-cache /usr/share/icons/Yaru &>/dev/null || true
88

9-
# Chromium policy directory for theme
10-
mkdir -p /etc/chromium/policies/managed
11-
chmod a+rw /etc/chromium/policies/managed
12-
139
# Default Chromium to follow system appearance ("device") instead of dark
1410
mkdir -p /usr/lib/chromium
1511
echo '{"browser":{"theme":{"color_scheme":0,"color_scheme2":0}}}' > \

install/helpers/as-root.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
as_root() {
2+
if (( EUID == 0 )); then
3+
"$@"
4+
else
5+
sudo "$@"
6+
fi
7+
}

0 commit comments

Comments
 (0)