Linux Application Sandboxing with Bubblewrap, Firejail and Flatpak
How the Basilisk team isolates browsers, PDF readers and risky tools on Linux desktops using audited, reproducible sandbox profiles.
A Basilisk researcher opened a bug bounty PDF in Evince and thirty seconds later auditd logged a read attempt against ~/.ssh/id_ed25519. The process had zero legitimate reason to touch that directory, yet it tried. That incident, which ended fine because Evince was running inside a restrictive Bubblewrap profile, is why this post exists. Desktop Linux sandboxing is not security theater: it is the layer that separates an annoying exploit from a quiet exfiltration of SSH keys, cloud tokens and session cookies. Lets land Bubblewrap, Firejail and Flatpak with profiles battle-tested in production OPSEC for Security Researchers: Building a Personal Threat Model.
Bubblewrap (bwrap) is the foundation. It is the unprivileged container runtime Flatpak uses under the hood, maintained by the containers project and auditable in a few hundred lines of C. A minimal profile to open PDFs looks like: `bwrap --ro-bind /usr /usr --ro-bind /etc /etc --proc /proc --dev /dev --tmpfs /tmp --bind ~/Downloads/sandbox-pdf /home/user --unshare-all --share-net /usr/bin/zathura file.pdf`. Note `--unshare-all` followed by `--share-net` only if required, and the bind of a specific folder instead of full $HOME. That allow-list pattern is what separates real sandboxing from placebo, and it pairs well with DFIR investigations DFIR on Linux: Live Triage with UAC and Velociraptor.
Firejail sits at a higher level and ships roughly 1,000 ready profiles under /etc/firejail. For daily researcher workstation use, the trio firefox.profile, thunderbird.profile and libreoffice.profile covers 80% of the attack surface. Start with `firejail --profile=/etc/firejail/firefox.profile --private-tmp --dns=9.9.9.9 firefox`. Enable AppArmor with `firejail --apparmor` and inspect status via `firejail --list`. Firejails historical Achilles heel is the SUID binary; if that bothers you, install with `setcap cap_sys_admin+ep` on recent kernels or migrate to plain Bubblewrap. To open suspected phishing docs, combine it with metadata hygiene before any forwarding Metadata Hygiene: Stripping EXIF, PDF and Office Before You Publish.
Flatpak ships apps with a declarative permission manifest. The command worth memorizing is `flatpak override --user --nofilesystem=home org.mozilla.firefox` followed by `flatpak override --user --filesystem=~/Downloads org.mozilla.firefox`. That revokes full $HOME access and returns only Downloads. To audit what each app asks for, run `flatpak info --show-permissions org.telegram.desktop` or open Flatseal. Apps like Zoom, Slack and Discord running via Flatpak with `--nofilesystem=host` and `--nodevice=all` drastically cut the blast radius of a rendering CVE. It plugs straight into hardening high-risk workstations Linux Server Hardening: Applying CIS Benchmark Without Breaking Production.
Real-world scenarios we run at Basilisk: analysis of client-supplied samples lives in a dedicated Remnux VM, not desktop sandbox Malware Analysis in an Isolated Lab: Safe Setup with FlareVM and REMnux. But reading report PDFs, opening client docx, browsing bug bounty sites and testing a browser extension all happen inside Bubblewrap profiles with a separate network namespace via slirp4netns. For clients that mandate Signal Desktop, we run the Flatpak build with `--nofilesystem=home --filesystem=xdg-download` and pass a hardware token via `--device=all` only during pairing Comms OPSEC: Signal, SimpleX and Session Technically Compared. Every profile lives in git, reviewed in pull requests, exactly like production code.
Three common pitfalls. First: skipping `--unshare-user-try` or `--unshare-net` because the app complains, leaving you with paper sandboxing. Fix it by isolating first with `--share-net` then tightening, monitoring with `strace -f -e network`. Second: trusting Flatpak alone to protect against escape via a misconfigured D-Bus portal; review portals with `flatpak permissions`. Third: leaving the microphone open. Apply `flatpak override --nodevice=all` globally and grant case by case. For continuous verification, wire profiles into Sigma rules that catch escape attempts Threat Hunting with Sigma and Elastic: From Indicator to Detection Rule and review quarterly, because manifests drift every update cycle.
Practical takeaway: start today by running `flatpak override --user --nofilesystem=home` on every installed Flatpak app, swap your default PDF reader for a Bubblewrap wrapper bound only to ~/Downloads, and version those scripts in a private repo. In one afternoon you raise the exploitation bar of your desktop more than a year of reactive patching. Properly configured sandboxing wont stop every intrusion, but it guarantees the months first browser CVE wont mutate into an SSH-key-leak incident. The ROI of this setup is measured in incidents that never happened.