Wren Linux

wren-linux / docs / extras / firefox-sandbox.md (as plain text)

Firefox as its own user (extras/firefox-sandbox.sh)

SYNOPSIS

wrenctl install firefox-sandbox                     install it (with Firefox's hardening and incognito)
wrenctl remove firefox-sandbox                      remove it (asks about incognito and the profile)
wrenctl manual firefox-sandbox                      print the manual steps (firefox.md's, then these)

firefox [URL]       the sandboxed Firefox, as a normal window (links from other programs open in it)
firefox-unsafe      the same Firefox run as you, with everything you can reach
firefox-esr         (Debian's name, and /usr/bin/firefox, x-www-browser): the sandboxed one

The firefox command opens Firefox as a normal window on your sway, but it runs as a different user, firefox, with no password, no login and none of your files, so a hacked page reaches only that user's own profile (/var/lib/wren-firefox: your logins, history and bookmarks), not your documents, keys or passwords.

The clipboard is shared while its window has focus, and ~/Downloads both ways (a file there opens in it too: firefox file://$HOME/Downloads/page.html; nothing else of yours does).

Its sound goes through a pipe into a player of yours, so it can't hear your microphone, and it gets a restricted Wayland socket.

A firewall rule on its group, wren-fx (data/firefox-firewall.nft), keeps it off your router, printers and this computer's own services; DNS stays open.

Your user may run exactly one thing as it, the session script bin/firefox-session, through a rule in /etc/sudoers.d, and a limit on processes keeps a runaway page from filling the machine.

Its install asks six things, remembered in /etc/wren/firefox.conf (which only root can write) and asked again when you run it again in a terminal: fast JavaScript (the JIT; default no, since it is where many browser attacks happen), sound (default yes), whether it is your default browser, so links from other programs open in it (default yes), and uBlock Origin's mode: medium (default: other sites' scripts blocked too; ublock-allow SITE gives one that breaks standard mode) or standard (ads, trackers and malware sites blocked, sites work), and, for when secure DNS is switched off, Firefox's own encrypted DNS to Quad9: strict (default: never plain DNS) or with fallback to the network's; and whether its cookies, site data and cache are deleted when it closes (default delete), so websites and the ad and tracker companies behind them can't recognise you from one visit to the next: you are then logged out of every site at each close, except sites you allow under Firefox's Settings > Privacy & Security > Cookies and Site Data > Manage Exceptions.

History, bookmarks and saved passwords stay either way (no website can read them), and saved passwords fill in when you click a login box, not as the page loads (tracking scripts have read what Firefox filled into hidden boxes).

Per-site profiles keep their cookies: that is what they are for.

It follows Wren Linux's light or dark theme (theme), and a JPEG or PNG in ~/Pictures/wren/firefox replaces the fox behind its New Tab page: your firefox command hands it a checked copy, which only the firefox user can read, at each start, so it never sees your pictures folder.

It also sets up Firefox's hardening and incognito (firefox.md), and the profiles made with extras/firefox-profiles/new-profile.sh each get a user like it.

LIMITS

MANUAL INSTALL

Do the steps in firefox.md first: Firefox's hardening, then incognito. (--manual prints them above these.)

# Firefox, video codecs, uBlock, acl for sharing the socket and ~/Downloads,
# nftables, its own audio server and player, dbus for links to the running Firefox
sudo apt install --no-install-recommends firefox-esr libavcodec61 webext-ublock-origin-firefox acl nftables python3 dbus-daemon \
    pipewire-bin pipewire-pulse wireplumber
# Those don't start a sound server for you: without the sound extra (pipewire-audio)
# Debian's own start for every user is switched off, and Firefox gets no sound
dpkg -s pipewire-audio >/dev/null 2>&1 ||
    sudo systemctl --global disable pipewire.socket pipewire.service pipewire-pulse.socket pipewire-pulse.service wireplumber.service filter-chain.service

# The group every sandboxed Firefox user is in (the firewall rule matches it)
sudo groupadd --system wren-fx
# The firefox user: no password, no login shell, a home only it can enter;
# render lets Firefox open the GPU's render node (not the screen)
sudo useradd --system --gid wren-fx --create-home --home-dir /var/lib/wren-firefox --shell /usr/sbin/nologin --comment "Wren Linux sandboxed Firefox" firefox
sudo usermod --lock --shell /usr/sbin/nologin firefox
sudo chmod 0700 /var/lib/wren-firefox
sudo usermod -aG render firefox

# The command, its session script and prefs, the restricted Wayland socket
# and the no-abstract-sockets wrapper
sudo install -d -o root -g root -m 0755 /usr/local/share/wren /usr/local/libexec
install -D -m 0755 @WREN_DIR@/bin/wayland-restrict ~/.local/bin/wayland-restrict
sudo install -o root -g root -m 0755 @WREN_DIR@/bin/no-abstract-sockets /usr/local/libexec/wren-no-abstract-sockets
# The check that its firewall really holds: it won't start without it, and ends if it goes
sudo install -o root -g root -m 0755 @WREN_DIR@/bin/sandbox-net-check /usr/local/libexec/wren-sandbox-net-check
sudo install -o root -g root -m 0755 @WREN_DIR@/bin/firefox /usr/local/bin/firefox
sudo install -o root -g root -m 0755 @WREN_DIR@/bin/firefox-session /usr/local/libexec/firefox-session
sudo install -o root -g root -m 0644 @WREN_DIR@/data/firefox-user.js /usr/local/share/wren/firefox-user.js
# Your choices: fast JavaScript (yes/no), sound, default browser; only root can change them
sudo install -d -o root -g root -m 0755 /etc/wren
printf 'fast_js=no\nsound=yes\ndefault_browser=yes\nublock=medium\ndns=strict\ncookies=delete\n' | sudo tee /etc/wren/firefox.conf
sudo /usr/local/bin/ublock-allow --mode medium

# Your user may run the session script, and nothing else, as firefox. visudo
# checks the rule first: never put a rule in /etc/sudoers.d it hasn't passed.
printf '%s ALL=(firefox) NOPASSWD: /usr/local/libexec/firefox-session\n' "$(id -un)" >/tmp/wren-firefox
sudo visudo -cf /tmp/wren-firefox
sudo install -o root -g root -m 0440 /tmp/wren-firefox /etc/sudoers.d/wren-firefox
rm /tmp/wren-firefox
# A limit on processes for every sandboxed Firefox user, and no core dumps
printf '%s\n' '@wren-fx hard nproc 4096' '@wren-fx hard core 0' | sudo tee /etc/security/limits.d/50-wren-firefox.conf

# The firewall rule, loaded at every boot before the network comes up
sudo install -D -o root -g root -m 0644 @WREN_DIR@/data/firefox-firewall.nft /etc/wren/firefox.nft
printf '%s\n' '[Unit]' 'Description=Keep the firefox user off the local network' \
    'Before=network-pre.target' 'Wants=network-pre.target' '' '[Service]' \
    'Type=oneshot' 'RemainAfterExit=yes' 'ExecStart=/usr/sbin/nft -f /etc/wren/firefox.nft' \
    'ExecStop=/usr/sbin/nft delete table inet wren_firefox' '' '[Install]' 'WantedBy=multi-user.target' |
    sudo tee /etc/systemd/system/wren-firefox-firewall.service
sudo systemctl daemon-reload
sudo systemctl enable --now wren-firefox-firewall.service

# The default browser: links from other programs open in it
install -D -m 0644 @WREN_DIR@/data/wren-firefox.desktop ~/.local/share/applications/wren-firefox.desktop
mkdir -p ~/.config && touch ~/.config/mimeapps.list
grep -qx '\[Default Applications\]' ~/.config/mimeapps.list || echo '[Default Applications]' >>~/.config/mimeapps.list
for t in x-scheme-handler/http x-scheme-handler/https; do
    sed -i "\\|^$t=|d; /^\\[Default Applications\\]\$/a $t=wren-firefox.desktop" ~/.config/mimeapps.list
done
# Debian's firefox-esr becomes firefox-unsafe (its updates land there too), and
# firefox-esr by name (and /usr/bin/firefox, x-www-browser) opens the sandbox
sudo dpkg-divert --local --rename --divert /usr/bin/firefox-unsafe --add /usr/bin/firefox-esr
printf '#!/bin/sh\nexec /usr/local/bin/firefox "$@"\n' | sudo tee /usr/bin/firefox-esr >/dev/null
sudo chmod 0755 /usr/bin/firefox-esr
printf '[Desktop Entry]\nType=Application\nName=Firefox ESR\nHidden=true\n' >~/.local/share/applications/firefox-esr.desktop
firefox

To undo (remove each profile made with new-profile.sh first):

# The firewall rule
sudo systemctl disable --now wren-firefox-firewall.service
sudo rm /etc/systemd/system/wren-firefox-firewall.service /etc/wren/firefox.nft
sudo systemctl daemon-reload
# The sudo rule, the limits, the command, its session script and prefs
sudo rm /etc/sudoers.d/wren-firefox /etc/security/limits.d/50-wren-firefox.conf
sudo rm /usr/local/bin/firefox /usr/local/libexec/firefox-session /usr/local/share/wren/firefox-user.js /etc/wren/firefox.conf
sudo rm -rf /dev/shm/firefox-run
# firefox-esr is Firefox as you again
sudo rm /usr/bin/firefox-esr
sudo dpkg-divert --local --rename --remove /usr/bin/firefox-esr
rm ~/.local/share/applications/firefox-esr.desktop
# Links open in firefox-esr again
sed -i '/=wren-firefox\.desktop$/d' ~/.config/mimeapps.list
rm ~/.local/share/applications/wren-firefox.desktop
# The user and its group
sudo pkill -KILL -u firefox
sudo userdel firefox
sudo groupdel wren-fx
# Its profile: your logins, history and bookmarks in it (only if you want them gone)
sudo rm -rf /var/lib/wren-firefox

Then undo firefox.md's steps, unless you keep incognito.