Sandboxing apps
Upon letting strangers into your house, just so long as they don’t open the door to that one forbidden room
2019-08-09 — 2026-06-29
Wherein the Isolation of Untrusted Applications Is Examined, With Attention to the Practical Weaknesses of Flatpak, Firejail, Bubblewrap, AppArmor, and macOS Seatbelt.
Running apps made by strangers in their own little sandbox environments to mitigate the harm they can do to you or, failing that, at least provide an unwarranted feeling of safety.
Related, but not the same, containerization is more about distributing lightly configured machine services than desktop apps.
Also related, application firewalls are built from some of the same stuff, differing mostly in the emphasis (network resources specifically) and granularity (“don’t talk to this site”).
One sandboxes because it is aspirationally more secure. In practice, actually existing sandbox systems are not especially secure, and indeed as GTFOBinaries documents, sandboxes are commonly laughably easy to escape using standard affordances.
Some package app standards, notably Flatpak and Snap, have facilities for sandboxing, although these are usually perfunctory, AFAICT. The other major packaging standard, AppImage, doesn’t actually sandbox at all by default, but they encourage you to use Firejail to manually sandbox. Hands up who remembers to do that?
On one hand, this is not ideal, having to manually assign permissions to everything. On the other hand, there is little evidence that package maintainers put much thought into the permissions they give sandboxed apps generally, so it is probably not substantially worse than the alternatives.
Not sure how any of this weathers famous exploits like Meltdown and SPECTRE and other such ridiculous security flaws in our rickety computing systems, so, like, do be careful. Sandboxes are more like speed bumps than crash barriers before the monster truck ram-raid of our vulnerabilities. But also, perhaps they might upset the shopping cart of the low-effort shoplifter? And they are relatively easy and computationally affordable.
1 Firejail
Firejail is an easy-to-use SUID sandbox program that reduces the risk of security breaches by restricting the running environment of untrusted applications using Linux namespaces, seccomp-bpf and Linux capabilities.
nachoparker’s intro is comprehensible.
2 Bubblewrap
Abstracted from the app standard Flatpak is bubblewrap.
Many container runtime tools like systemd-nspawn, docker, etc. focus on providing infrastructure for system administrators and orchestration tools (e.g. Kubernetes) to run containers.
These tools are not suitable to give to unprivileged users, because it is trivial to turn such access into a fully privileged root shell on the host.
Rumour has it that bubblewrap is more secure than Firejail because it deliberately does less: by design bubblewrap does not try to cover every scenario, so out of the box it does not bridge PulseAudio, X11, or DBus into the sandbox for us. Essentially there is a trade-off in modern architectures, between fun interactive multimedia and doing things securely.
Where Firejail ships profiles that guess what an app needs, bubblewrap makes us assemble the sandbox’s filesystem by hand, one bind mount at a time. A throwaway shell with a read-only system, no network and a private /tmp:
The process sees only what we mounted: --unshare-all severs every namespace, the network among them; --tmpfs /tmp gives it a /tmp that evaporates when the shell exits; and there is no /home — nor any audio socket — unless we bind one in ourselves.
Notably Flatpak apps do support audio. Binding that socket in is what Flatpak does for us. This didn’t work great for a while because linux audio is a shitnado, but the desktop is moving to PipeWire, which is a more sane design and easier to configure for a sandbox.
3 Apparmor
AppArmor, the ACL system preferred by Ubuntu is another way to build sandboxes for apps, in that it controls access to resources for processes. It’s probably a good way to do things, but the documentation is not accessible or comprehensible to normal schmucks like me. The Ubuntu community wiki is as close as it gets to a manual that one can read online AFAICT.
4 Seatbelt
macOS ships its own sandbox, Seatbelt, implemented as a “TrustedBSD mandatory-access-control module” at the kernel level. There is a user-facing wrapper, sandbox-exec, which executes an arbitrary command under a supplied policy.
A policy is a TinyScheme program — wherein we do stuff like (deny foo) and then (allow bar) back the operations the program is actually permitted to touch: file-read*, file-write*, network*, process-exec, mach-lookup and friends. We can pass the profile inline with -p, or keep it in a .sb file passed -f.
Running something with no network at all:
Or the more paranoid deny-everything-then-allow-back stance favoured by Apple itself:
As with other sandboxing systems, there is a trade-off between security and convenience.
A peculiar thing about Seatbelt is that sandbox-exec has been deprecated since about 2017 — its own man page opens with the word DEPRECATED in capitals — and yet it is everywhere and the whole operating system leans on the same machinery.1
The supported replacement is the App Sandbox, which uses the same kernel mechanism but less dynamically (i.e. more AppArmor-like) — entitlements are baked into a code-signed app rather than a scheme file.
Chromium uses Seatbelt to lock down its renderer processes. Lately the technique has found a second audience among people scrambling to wrap AI agents and exploit-heavy apps like npm.
Footnotes
The shipped profiles live in
/usr/share/sandbox/and/System/Library/Sandbox/Profiles/, should we want to read how Apple sandboxes its own daemons.↩︎
