Files
nix-config-ryan4yin/hardening
ryan4yin | 二花 818965a11f feat(nixpak): unify desktop app sandboxes (#491)
* refactor(nixpak): unify desktop app sandboxes

Move common GUI, portal, and network policy into reusable modules and migrate browsers plus Zoom/WeChat/QQ/Telegram to the same boundary.

Assisted-by: DeepSeek Harness (deepseek-flash)
2026-10-31 22:27:58 +08:00
..

Linux Hardening

Deployed and interactively validated on ai (2026-10-31). Policy and limits: SECURITY.md.

Shared boundaries

  • Cleared environment; filtered session D-Bus; private /dev/shm; per-app /tmp. Chromium-family browsers share an app-specific /tmp so external URLs reuse one browser instance.
  • Read-only /nix/store; GPU and display; fonts and themes; LAN and Internet.
  • Portals for file chooser, URI opening, notifications, input methods and document exports.
  • No whole host home, system D-Bus, SSH agent, USB/serial, raw camera or raw PipeWire socket.
  • Host loopback only for Firefox/Chromium; all other apps use pasta-isolated loopback.

App permissions

Media means audio playback, microphone, Camera and ScreenCast portals. Writable paths are listed explicitly; other files use the document portal. Every app also has private writable state.

App Network Writable paths Grants
Firefox Host loopback ~/.mozilla, personal files, Trash, Firefox artwork Media, browserpass, MPRIS, idle
Chromium Host loopback ~/.config/chromium, personal files Media, browserpass, MPRIS, idle, v12 Secret
Chrome Isolated ~/.config/google-chrome, Downloads Media, browserpass, MPRIS, idle, v12 Secret
Brave Origin Isolated ~/.config/BraveSoftware/Brave-Origin, Downloads v12 Secret
Edge Isolated ~/.config/microsoft-edge, Downloads v12 Secret
QQ Isolated Personal files, private app state Media, notifications, tray, MPRIS, idle, accessibility
Telegram Isolated Personal files, private app state Media, notifications, tray, MPRIS, idle, accessibility, Ayatana indicators
Zoom Isolated ~/.zoom, zoomus.conf, zoom.conf, Downloads, Documents/Zoom, private app state Media, X11/XWayland, FHS, SNI tray, idle, /dev/video0-1, read-only /sys/class/drm
WeChat Isolated Documents/WeChat_Data, its HOME mapping and xwechat_files link, private app state Media, X11/xcb, FHS, SNI tray

All browsers get read-only NSS certificates, printing, native notifications and accessibility.

Browser secrets

  • Chromium family: app-scoped Secret portal only. SecretPortalKeyProviderUseForEncryption writes v12 cookies; no org.freedesktop.secrets or broad keyring access.
  • If the Secret portal is unavailable, Chromium can fall back to v10. Monitor Local State.os_crypt.portal.prev_init_success.
  • Firefox uses NSS: key4.db and logins.json for logins, cookies.sqlite for cookies. It has no Secret portal or keyring grant. A Primary Password protects saved logins, not cookies.
  • browserpass is separate: it exposes the password store and GPG-agent socket, not cookie encryption.
  • Bookmarks, history, localStorage, IndexedDB and extension data remain readable by the browser. nixpak isolates them from other apps, not from browser compromise.

Limits

  • X11: Zoom and WeChat have shared-display trust; portal permissions cannot enforce portal-only capture.
  • PulseAudio grants recording authority. Read-only GPG sockets still permit signing and decryption.
  • pasta isolates loopback, not LAN access. Chromecast discovery is unverified.
  • Brave/Edge renderer and permission checks pass, but headless page export still times out.

Validation

  • Passed: just fmt, just test, ai-niri build and shoukei-niri eval.
  • Deployed on ai; interactive startup and tray checks passed for Chrome, Firefox, QQ, Telegram, Zoom and WeChat.
  • Chromium/Chrome: renderer sandbox, mounts, rendering and disposable-profile persistence passed. Chromium reaches host loopback; Chrome cannot.
  • Firefox: disposable headless screenshot passed.
  • Brave/Edge: renderer and permission checks passed; headless page export timed out.
  • Evidence: browsers, Firefox/QQ/Telegram, Zoom, WeChat.

Code map