diff --git a/hosts/common/programs/aerc.nix b/hosts/common/programs/aerc.nix index 87bff6c55..1c47d3184 100644 --- a/hosts/common/programs/aerc.nix +++ b/hosts/common/programs/aerc.nix @@ -4,6 +4,8 @@ { sane.programs.aerc = { sandbox.method = "bwrap"; + sandbox.wrapperType = "inplace"; + sandbox.net = "clearnet"; secrets.".config/aerc/accounts.conf" = ../../../secrets/common/aerc_accounts.conf.bin; mime.associations."x-scheme-handler/mailto" = "aerc.desktop"; }; diff --git a/hosts/common/programs/assorted.nix b/hosts/common/programs/assorted.nix index 86de327d6..768fefff1 100644 --- a/hosts/common/programs/assorted.nix +++ b/hosts/common/programs/assorted.nix @@ -232,11 +232,13 @@ in delfin.sandbox.method = "bwrap"; delfin.sandbox.wrapperType = "wrappedDerivation"; delfin.sandbox.whitelistDri = true; + delfin.sandbox.net = "clearnet"; delfin.persist.byStore.private = [ ".config/delfin" ]; # creds, but also 200 MB of node modules, etc discord.sandbox.method = "bwrap"; discord.sandbox.wrapperType = "inplace"; #< /opt-style packaging + discord.sandbox.net = "clearnet"; discord.persist.byStore.private = [ ".config/discord" ]; dtc.sandbox.method = "bwrap"; @@ -343,6 +345,7 @@ in mercurial.sandbox.method = "bwrap"; # TODO:sandbox: untested mercurial.sandbox.wrapperType = "wrappedDerivation"; + mercurial.sandbox.net = "clearnet"; mercurial.sandbox.whitelistPwd = true; mimeo.sandbox.method = "capshonly"; # xdg-open replacement @@ -371,6 +374,7 @@ in rsync.sandbox.method = "bwrap"; # TODO:sandbox: untested rsync.sandbox.wrapperType = "wrappedDerivation"; + rsync.sandbox.net = "clearnet"; rsync.sandbox.autodetectCliPaths = "existingFileOrParent"; sequoia.sandbox.method = "bwrap"; # TODO:sandbox: untested @@ -397,6 +401,7 @@ in subversion.sandbox.method = "bwrap"; subversion.sandbox.wrapperType = "wrappedDerivation"; + subversion.sandbox.net = "clearnet"; subversion.sandbox.whitelistPwd = true; sudo.sandbox.enable = false; @@ -413,6 +418,7 @@ in tcpdump.sandbox.method = "landlock"; tcpdump.sandbox.wrapperType = "wrappedDerivation"; + tcpdump.sandbox.net = "all"; tcpdump.sandbox.autodetectCliPaths = "existingFileOrParent"; tcpdump.sandbox.capabilities = [ "net_admin" "net_raw" ]; tree.sandbox.method = "landlock"; @@ -436,6 +442,7 @@ in wget.sandbox.method = "bwrap"; wget.sandbox.wrapperType = "wrappedDerivation"; + wget.sandbox.net = "all"; wget.sandbox.whitelistPwd = true; # saves to pwd by default whalebird.persist.byStore.private = [ ".config/Whalebird" ]; @@ -447,6 +454,7 @@ in yt-dlp.sandbox.method = "bwrap"; # TODO:sandbox: untested yt-dlp.sandbox.wrapperType = "wrappedDerivation"; + yt-dlp.sandbox.net = "all"; yt-dlp.sandbox.whitelistPwd = true; # saves to pwd by default }; diff --git a/hosts/common/programs/brave.nix b/hosts/common/programs/brave.nix index 1e7761ba4..089fd0b7e 100644 --- a/hosts/common/programs/brave.nix +++ b/hosts/common/programs/brave.nix @@ -3,6 +3,7 @@ sane.programs.brave = { sandbox.method = "bwrap"; sandbox.wrapperType = "inplace"; # /opt/share/brave.com vendor-style packaging + sandbox.net = "all"; sandbox.extraHomePaths = [ "dev" # for developing anything web-related "tmp" diff --git a/hosts/common/programs/conky/default.nix b/hosts/common/programs/conky/default.nix index e8bbed12e..54bdcfc49 100644 --- a/hosts/common/programs/conky/default.nix +++ b/hosts/common/programs/conky/default.nix @@ -3,6 +3,7 @@ sane.programs.conky = { # TODO: non-sandboxed `conky` still ships via `sxmo-utils`, but unused sandbox.method = "bwrap"; + sandbox.net = "clearnet"; #< for the scripts it calls (weather) sandbox.extraPaths = [ "/sys/class/power_supply" "/sys/devices" # needed by battery_estimate diff --git a/hosts/common/programs/dialect.nix b/hosts/common/programs/dialect.nix index 852c96bcf..29e9a7e84 100644 --- a/hosts/common/programs/dialect.nix +++ b/hosts/common/programs/dialect.nix @@ -3,6 +3,7 @@ sane.programs.dialect = { sandbox.method = "bwrap"; sandbox.wrapperType = "inplace"; # share/search_providers/ calls back into the binary, weird wrap semantics + sandbox.net = "clearnet"; sandbox.extraHomePaths = [ ".config/dconf" # to persist settings ]; diff --git a/hosts/common/programs/dino.nix b/hosts/common/programs/dino.nix index ffcaacc89..82327c4cb 100644 --- a/hosts/common/programs/dino.nix +++ b/hosts/common/programs/dino.nix @@ -47,6 +47,7 @@ in sandbox.method = "bwrap"; sandbox.wrapperType = "wrappedDerivation"; + sandbox.net = "clearnet"; persist.byStore.private = [ ".local/share/dino" ]; diff --git a/hosts/common/programs/element-desktop.nix b/hosts/common/programs/element-desktop.nix index 0fbc76513..ddaf2cb24 100644 --- a/hosts/common/programs/element-desktop.nix +++ b/hosts/common/programs/element-desktop.nix @@ -9,6 +9,7 @@ sane.programs.element-desktop = { sandbox.method = "bwrap"; sandbox.wrapperType = "wrappedDerivation"; + sandbox.net = "clearnet"; packageUnwrapped = pkgs.element-desktop.override { # use pre-build electron because otherwise it takes 4 hrs to build from source. electron = pkgs.electron-bin; diff --git a/hosts/common/programs/epiphany.nix b/hosts/common/programs/epiphany.nix index 974132d9f..3bef77903 100644 --- a/hosts/common/programs/epiphany.nix +++ b/hosts/common/programs/epiphany.nix @@ -10,6 +10,7 @@ sane.programs.epiphany = { sandbox.method = "bwrap"; sandbox.wrapperType = "inplace"; # /share/epiphany/default-bookmarks.rdf refers back to /share; dbus files to /libexec + sandbox.net = "clearnet"; # default sandboxing breaks rendering in weird ways. sites are super zoomed in / not scaled. # enabling DRI/DRM (as below) seems to fix that. sandbox.whitelistDri = true; diff --git a/hosts/common/programs/firefox.nix b/hosts/common/programs/firefox.nix index 3a43f1bd7..d31698636 100644 --- a/hosts/common/programs/firefox.nix +++ b/hosts/common/programs/firefox.nix @@ -234,6 +234,8 @@ in sane.programs.firefox = { inherit packageUnwrapped; sandbox.method = "bwrap"; # landlock works, but requires all of /proc to be linked + sandbox.wrapperType = "inplace"; # probably wrappedDerivation could work too. + sandbox.net = "all"; sandbox.extraHomePaths = [ "dev" # for developing anything web-related "tmp" diff --git a/hosts/common/programs/fractal.nix b/hosts/common/programs/fractal.nix index 40b3c6cce..85aaef8c9 100644 --- a/hosts/common/programs/fractal.nix +++ b/hosts/common/programs/fractal.nix @@ -29,6 +29,7 @@ in sandbox.method = "bwrap"; sandbox.wrapperType = "wrappedDerivation"; + sandbox.net = "clearnet"; sandbox.whitelistDri = true; # otherwise video playback buuuuurns CPU configOption = with lib; mkOption { diff --git a/hosts/common/programs/frozen-bubble.nix b/hosts/common/programs/frozen-bubble.nix index ae64e6050..f029a7831 100644 --- a/hosts/common/programs/frozen-bubble.nix +++ b/hosts/common/programs/frozen-bubble.nix @@ -4,6 +4,7 @@ sane.programs.frozen-bubble = { sandbox.method = "bwrap"; sandbox.wrapperType = "wrappedDerivation"; + sandbox.net = "clearnet"; # net play packageUnwrapped = pkgs.frozen-bubble.overrideAttrs (upstream: { # patch so it stores its dot-files not in root ~. postPatch = (upstream.postPatch or "") + '' diff --git a/hosts/common/programs/geary.nix b/hosts/common/programs/geary.nix index e3d7c90ad..2bd0732cb 100644 --- a/hosts/common/programs/geary.nix +++ b/hosts/common/programs/geary.nix @@ -21,6 +21,7 @@ in sandbox.method = "bwrap"; sandbox.wrapperType = "wrappedDerivation"; + sandbox.net = "clearnet"; sandbox.extraPaths = [ # geary sandboxes *itself* with bwrap, and dbus-proxy which, confusingly, causes it to *require* these paths. # TODO: these could maybe be mounted empty. or maybe there's an env-var to disable geary's dbus-proxy. diff --git a/hosts/common/programs/git.nix b/hosts/common/programs/git.nix index 918713bfc..923ab59c2 100644 --- a/hosts/common/programs/git.nix +++ b/hosts/common/programs/git.nix @@ -8,6 +8,8 @@ in { sane.programs.git = { sandbox.method = "bwrap"; + sandbox.wrapperType = "inplace"; + sandbox.net = "clearnet"; sandbox.whitelistPwd = true; sandbox.autodetectCliPaths = true; # necessary for git-upload-pack sandbox.extraHomePaths = [ diff --git a/hosts/common/programs/gnome-weather.nix b/hosts/common/programs/gnome-weather.nix index 1f7522e88..8216f648a 100644 --- a/hosts/common/programs/gnome-weather.nix +++ b/hosts/common/programs/gnome-weather.nix @@ -4,6 +4,8 @@ { sane.programs."gnome.gnome-weather" = { sandbox.method = "bwrap"; + sandbox.wrapperType = "inplace"; + sandbox.net = "clearnet"; sandbox.extraHomePaths = [ ".config/dconf" # stores city/location settings ]; diff --git a/hosts/common/programs/go2tv.nix b/hosts/common/programs/go2tv.nix index d5343ad9b..333ef9676 100644 --- a/hosts/common/programs/go2tv.nix +++ b/hosts/common/programs/go2tv.nix @@ -35,6 +35,7 @@ in sane.programs.go2tv = { sandbox.method = "bwrap"; sandbox.wrapperType = "wrappedDerivation"; + sandbox.net = "clearnet"; sandbox.autodetectCliPaths = true; # for GUI invocation, allow the common media directories sandbox.extraHomePaths = [ diff --git a/hosts/common/programs/gtkcord4.nix b/hosts/common/programs/gtkcord4.nix index c948267c7..ede878396 100644 --- a/hosts/common/programs/gtkcord4.nix +++ b/hosts/common/programs/gtkcord4.nix @@ -33,6 +33,7 @@ in }); sandbox.method = "bwrap"; sandbox.wrapperType = "wrappedDerivation"; + sandbox.net = "clearnet"; persist.byStore.private = [ ".cache/gtkcord4" diff --git a/hosts/common/programs/komikku.nix b/hosts/common/programs/komikku.nix index 22a3cd9ec..a655784f7 100644 --- a/hosts/common/programs/komikku.nix +++ b/hosts/common/programs/komikku.nix @@ -3,6 +3,7 @@ sane.programs.komikku = { sandbox.method = "bwrap"; # TODO:sandbox untested sandbox.wrapperType = "wrappedDerivation"; + sandbox.net = "clearnet"; sandbox.whitelistDri = true; #< required secrets.".local/share/komikku/keyrings/plaintext.keyring" = ../../../secrets/common/komikku_accounts.json.bin; # downloads end up here, and without the toplevel database komikku doesn't know they exist. diff --git a/hosts/common/programs/koreader/default.nix b/hosts/common/programs/koreader/default.nix index aa03d6264..0f818b34c 100644 --- a/hosts/common/programs/koreader/default.nix +++ b/hosts/common/programs/koreader/default.nix @@ -47,6 +47,7 @@ in { packageUnwrapped = pkgs.koreader-from-src; sandbox.method = "bwrap"; # sandboxes fine under landlock too, except for FTP sandbox.wrapperType = "wrappedDerivation"; + sandbox.net = "clearnet"; sandbox.whitelistDri = true; # reduces startup time and subjective page flip time sandbox.embedProfile = true; sandbox.extraHomePaths = [ diff --git a/hosts/common/programs/mpv.nix b/hosts/common/programs/mpv.nix index c8c98a263..ca711ca77 100644 --- a/hosts/common/programs/mpv.nix +++ b/hosts/common/programs/mpv.nix @@ -64,6 +64,7 @@ in sandbox.method = "bwrap"; sandbox.autodetectCliPaths = true; + sandbox.net = "all"; sandbox.whitelistDri = true; #< mpv has excellent fallbacks to non-DRI, but DRI offers a good 30%-50% reduced CPU persist.byStore.plaintext = [ ".local/state/mpv/watch_later" ]; diff --git a/hosts/common/programs/nicotine-plus.nix b/hosts/common/programs/nicotine-plus.nix index 5d33dc058..9775e907c 100644 --- a/hosts/common/programs/nicotine-plus.nix +++ b/hosts/common/programs/nicotine-plus.nix @@ -9,8 +9,9 @@ rm $out/bin/nicotine-plus ''; }); - net = "vpn"; sandbox.method = "firejail"; + sandbox.wrapperType = "wrappedDerivation"; + sandbox.net = "vpn"; # ".config/nicotine": contains the config file, with plaintext creds. # TODO: define this as a secret instead of persisting it. persist.byStore.private = [ ".config/nicotine" ]; diff --git a/hosts/common/programs/signal-desktop.nix b/hosts/common/programs/signal-desktop.nix index 5abffc473..ec704ce72 100644 --- a/hosts/common/programs/signal-desktop.nix +++ b/hosts/common/programs/signal-desktop.nix @@ -24,6 +24,7 @@ in packageUnwrapped = pkgs.signal-desktop-from-src; sandbox.method = "bwrap"; sandbox.wrapperType = "wrappedDerivation"; + sandbox.net = "clearnet"; # creds, media persist.byStore.private = [ diff --git a/hosts/common/programs/spot.nix b/hosts/common/programs/spot.nix index 50e9445f8..596eceb2d 100644 --- a/hosts/common/programs/spot.nix +++ b/hosts/common/programs/spot.nix @@ -3,6 +3,7 @@ sane.programs.spot = { sandbox.method = "bwrap"; sandbox.wrapperType = "wrappedDerivation"; + sandbox.net = "clearnet"; secrets.".cache/spot/librespot/credentials/credentials.json" = ../../../secrets/common/spot_credentials.json.bin; persist.byStore.plaintext = [ ".cache/spot/img" # album art diff --git a/hosts/common/programs/spotify.nix b/hosts/common/programs/spotify.nix index 2b79bea9f..fd47bfc1b 100644 --- a/hosts/common/programs/spotify.nix +++ b/hosts/common/programs/spotify.nix @@ -3,6 +3,7 @@ sane.programs.spotify = { sandbox.method = "bwrap"; sandbox.wrapperType = "inplace"; # nontraditional package structure, where binaries live in /share/spotify + sandbox.net = "clearnet"; sandbox.extraConfig = [ "--sane-sandbox-firejail-arg" "--keep-dev-shm" diff --git a/hosts/common/programs/supertuxkart.nix b/hosts/common/programs/supertuxkart.nix index 1adcf3434..1b0c0341c 100644 --- a/hosts/common/programs/supertuxkart.nix +++ b/hosts/common/programs/supertuxkart.nix @@ -3,6 +3,7 @@ sane.programs.superTuxKart = { sandbox.method = "bwrap"; sandbox.wrapperType = "wrappedDerivation"; + sandbox.net = "clearnet"; # net play sandbox.whitelistDri = true; persist.byStore.plaintext = [ ".cache/supertuxkart" diff --git a/hosts/common/programs/tor-browser.nix b/hosts/common/programs/tor-browser.nix index 9db6654fa..c0484bf8a 100644 --- a/hosts/common/programs/tor-browser.nix +++ b/hosts/common/programs/tor-browser.nix @@ -9,6 +9,7 @@ # }; sandbox.method = "bwrap"; sandbox.wrapperType = "wrappedDerivation"; + sandbox.net = "clearnet"; # tor over VPN wouldn't make sense persist.byStore.cryptClearOnBoot = [ ".local/share/tor-browser" ]; diff --git a/hosts/common/programs/tuba.nix b/hosts/common/programs/tuba.nix index 31347b5f2..8c3833ac6 100644 --- a/hosts/common/programs/tuba.nix +++ b/hosts/common/programs/tuba.nix @@ -3,6 +3,7 @@ sane.programs.tuba = { sandbox.method = "bwrap"; sandbox.wrapperType = "wrappedDerivation"; + sandbox.net = "clearnet"; suggestedPrograms = [ "gnome-keyring" ]; }; } diff --git a/hosts/common/programs/vlc.nix b/hosts/common/programs/vlc.nix index 80d2255c8..81854c506 100644 --- a/hosts/common/programs/vlc.nix +++ b/hosts/common/programs/vlc.nix @@ -16,6 +16,7 @@ in }; sandbox.method = "bwrap"; sandbox.wrapperType = "wrappedDerivation"; + sandbox.net = "clearnet"; sandbox.autodetectCliPaths = true; persist.byStore.private = [ # vlc remembers play position in ~/.config/vlc/vlc-qt-interface.conf diff --git a/hosts/common/programs/wike.nix b/hosts/common/programs/wike.nix index 52ec6951a..82ad8b444 100644 --- a/hosts/common/programs/wike.nix +++ b/hosts/common/programs/wike.nix @@ -3,6 +3,7 @@ sane.programs.wike = { sandbox.method = "bwrap"; sandbox.wrapperType = "inplace"; # share/wike/wike-sp refers back to the binaries and share + sandbox.net = "clearnet"; sandbox.extraPaths = [ # wike sandboxes *itself* with bwrap, and dbus-proxy which, confusingly, causes it to *require* these paths. # TODO: these could maybe be mounted empty. diff --git a/hosts/common/programs/wireshark.nix b/hosts/common/programs/wireshark.nix index 78dbdade8..e7ccb1378 100644 --- a/hosts/common/programs/wireshark.nix +++ b/hosts/common/programs/wireshark.nix @@ -6,6 +6,7 @@ in sane.programs.wireshark = { sandbox.method = "landlock"; sandbox.wrapperType = "wrappedDerivation"; + sandbox.net = "all"; sandbox.extraPaths = [ "/proc/net" #< only needed if using landlock ]; diff --git a/modules/programs/default.nix b/modules/programs/default.nix index d3d3f2ea8..c21635afa 100644 --- a/modules/programs/default.nix +++ b/modules/programs/default.nix @@ -33,7 +33,7 @@ let defaultEnables = solveDefaultEnableFor cfg; # wrap a package so that its binaries (maybe) run in a sandbox - wrapPkg = pkgName: { fs, net, persist, sandbox, ... }: package: ( + wrapPkg = pkgName: { fs, persist, sandbox, ... }: package: ( if !sandbox.enable || sandbox.method == null then package else @@ -54,11 +54,11 @@ let whitelistPwd wrapperType ; - netDev = if net == "vpn" then + netDev = if sandbox.net == "vpn" then vpn.bridgeDevice else - net; - dns = if net == "vpn" then + sandbox.net; + dns = if sandbox.net == "vpn" then vpn.dns else null; @@ -220,12 +220,17 @@ let marking packages like this can be used to achieve faster, but limited, rebuilds/deploys (by omitting the package). ''; }; - net = mkOption { - type = types.enum [ null "clearnet" "vpn" ]; - default = "clearnet"; + sandbox.net = mkOption { + type = types.coercedTo + types.str + (s: if s == "clearnet" then "all" else s) + (types.enum [ null "all" "vpn" ]); + default = null; description = '' how this app should have its network traffic routed. - - "clearnet": for unsandboxed network. + - "all": unsandboxed network. + - "clearnet": traffic is routed only over clearnet. + currently, just an alias for "all" - "vpn": to route all traffic over the default VPN. - null: to maximally isolate from the network. ''; @@ -401,8 +406,8 @@ let message = "program ${name} specified no `sandbox.method`; please configure a method, or set sandbox.enable = false."; } { - assertion = p.net == "clearnet" || p.sandbox.method != null; - message = ''program "${name}" requests net "${p.net}", which requires sandboxing, but sandboxing wasn't configured''; + assertion = p.sandbox.net == "all" || p.sandbox.method != null || !p.enabled || p.package == null || config.sane.strictSandboxing != "assert"; + message = ''program "${name}" requests net "${builtins.toString p.sandbox.net}", which requires sandboxing, but sandboxing wasn't configured''; } ] ++ builtins.map (sug: { assertion = cfg ? "${sug}";