Firejail vs Bubblewrap: Which Linux Sandbox Should You Use?

Firejail and Bubblewrap are the two top lightweight sandbox tools for Linux. They take very different paths to the same job. Firejail is a SUID-root sandbox with over 1,000 ready-made profiles. It works out of the box for browsers, chat apps, and media players. Bubblewrap (bwrap) is a small, unprivileged namespace tool. It’s the same one Flatpak uses inside. You get exact control over what a sandboxed app can see, but you build the sandbox yourself. Want quick desktop isolation with sane defaults? Pick Firejail. Need a tight, auditable sandbox with no SUID binary? Pick Bubblewrap.
Why Sandbox Desktop Applications at All?
Every process under your Linux user account inherits your full rights. So any app, a browser, a chat client, a random Electron tool, can read ~/.ssh/, ~/.gnupg/, your browser cookies, your password manager, and every file in your home folder. There’s no permission wall between programs run as the same user.
This isn’t a theory. Supply chain attacks via npm and PyPI packages happen all the time. Browser zero-days still show up. Electron apps like Discord, Zoom, and Slack reach into clipboard contents and file paths far past their stated job. One hacked app or shady browser extension gets access to everything your user account can touch.
Sandboxing restricts what an application can see and do:
- Filesystem view: hide folders like
~/.ssh,~/.gnupg, and~/.configfrom apps that have no need to read them - Network access: block the network or limit it to set protocols
- IPC isolation: stop X11 keylogging, a real risk under Xorg where any app can grab keystrokes from any other
- Device access: block webcam and microphone unless granted
- Syscall filtering: seccomp-bpf filters limit which kernel calls the process can use
The same seccomp-bpf and capability-dropping tricks apply to hardening container images . Defense in depth maps directly between namespace sandboxes and Docker.
Flatpak and Snap already sandbox apps. Still, not every app ships as a Flatpak, and many Flatpak packages ask for --filesystem=home, which guts the point. Firejail and Bubblewrap let you sandbox any native package from your distro’s package manager.
Wayland’s protocol gives per-surface isolation by default: no app can grab another’s input or output. But Xwayland, which many legacy apps still need, breaks that wall. Sandboxing fills the gap.
Sandboxing complements patched software rather than replacing it. When prevention fails, the blast radius stays inside the sandbox instead of spreading across your home folder.
Firejail: Feature-Rich Sandboxing with Pre-Built Profiles
Firejail is the friendlier of the two. Install it, type firejail firefox, and your browser starts inside a sandbox with a curated rule set drawn from Firefox’s built-in profile. The stable version is 0.9.80. The 0.9.74 release (March 2025) added test-grade Landlock LSM
support for kernel-level filesystem control.
Installation
On Debian 13+ or Ubuntu 24.04+:
sudo apt install firejail firejail-profilesOn Fedora 41+:
sudo dnf install firejailVerify with firejail --version. You should see 0.9.74 or later.
How It Works
Firejail is a SUID-root binary. When you run firejail firefox, it:
- Creates Linux namespaces (mount, PID, network, UTS) to wall off the process
- Applies seccomp-bpf syscall filters to limit kernel calls
- Mounts a trimmed filesystem view from the app’s profile
- Drops all root rights
- Runs the target app inside the sandbox
The SUID-root design means Firejail works on any Linux box, even when unprivileged user namespaces are off. That’s both its main strength and its main critique (more on this in the comparison section).

Basic Usage
Launch Firefox with its default sandbox profile:
firejail firefoxLaunch Discord with a throwaway empty home folder, wiped on exit:
firejail --private discordSee what restrictions a profile applies:
firejail --debug firefoxKey Profile Directives
Firejail profiles use a plain syntax to spell out limits:
| Directive | Effect |
|---|---|
whitelist ~/Downloads | Only expose the Downloads directory |
blacklist ~/.ssh | Hide SSH keys from the sandboxed app |
net none | Disable all network access |
protocol unix,inet,inet6 | Restrict allowed socket types |
seccomp | Enable default syscall filter |
caps.drop all | Drop all Linux capabilities |
noroot | Prevent SUID binaries inside the sandbox |
--landlock | Enable Landlock filesystem restrictions (0.9.74+) |
Customizing Profiles
To tweak a profile, copy it to your user config folder:
cp /etc/firejail/firefox.profile ~/.config/firejail/firefox.profileEdit the copy to add or drop rules. Your user profile wins over the system one.
Desktop Integration
Running sudo firecfg rewrites symlinks in /usr/local/bin/. After that, every profiled app you launch from your desktop menu, dmenu, or rofi runs through Firejail. It’s the easiest way to sandbox your whole desktop without changing habits.

Recent Notable Changes
The 0.9.78 release (January 2026) was an urgent GTK fix. Apps using glycin
2.0.0 or later via gdk-pixbuf2 (Firefox, Thunderbird, GIMP) crashed inside Firejail sandboxes. The fix swapped bubblewrap calls in the sandbox for a stub fbwrap program. A new --allow-bwrap flag covers the cases where real bwrap is needed.
Bubblewrap: Minimal Unprivileged Namespace Sandboxing
Bubblewrap goes the other way. It’s a small, low-level tool for building Linux namespaces without SUID-root. You build the sandbox mount by mount, spelling out which folders the process can see and whether each one is read-only or writable. You get full control and easy audit, but you also pay in time per app.
The stable version is 0.11.1.
Installation
On Debian 13+ or Ubuntu 24.04+:
sudo apt install bubblewrapOn Fedora 41+:
sudo dnf install bubblewrapVerify with bwrap --version.
How It Works
Bubblewrap calls clone() with CLONE_NEWUSER, CLONE_NEWNS, CLONE_NEWPID, and related flags to spawn unprivileged user namespaces
. On most modern distros (Ubuntu 24.04+, Fedora 40+, Arch), kernel.unprivileged_userns_clone is on by default, so bwrap runs with no SUID binary. That smaller trust base is one of its main wins.
Basic Sandbox Example
Launch Firefox with a tiny root filesystem and an empty home folder:
bwrap \
--ro-bind /usr /usr \
--ro-bind /lib /lib \
--ro-bind /lib64 /lib64 \
--ro-bind /etc/fonts /etc/fonts \
--ro-bind /etc/resolv.conf /etc/resolv.conf \
--proc /proc \
--dev /dev \
--tmpfs /tmp \
--tmpfs /home \
--unshare-all \
--share-net \
--new-session \
-- /usr/bin/firefoxThis sets up a read-only view of the system libs, an empty home, and a shared host network (Firefox needs it). Everything else is hidden.
Mount Types
| Flag | Effect |
|---|---|
--bind src dest | Read-write bind mount |
--ro-bind src dest | Read-only bind mount |
--tmpfs path | Ephemeral tmpfs (contents lost on exit) |
--dev-bind src dest | Device access (for GPU, etc.) |
--symlink src dest | Create a symlink for FHS compatibility |
--unshare-net | Loopback-only network namespace |
--share-net | Keep host networking |
--die-with-parent | Kill sandboxed process when parent exits |
Network Isolation
Adding --unshare-net gives the process a loopback-only network namespace with no outside link. Use --share-net to keep host networking. Unlike Firejail, there’s no built-in support for bridges, bandwidth caps, or DNS filtering. It’s strictly all-or-nothing.
Wrapper Scripts
Bwrap commands run long, so the standard fix is a shell wrapper script. For example, ~/bin/sandboxed-firefox.sh:
#!/bin/bash
exec bwrap \
--ro-bind /usr /usr \
--ro-bind /lib /lib \
--ro-bind /lib64 /lib64 \
--ro-bind /etc/fonts /etc/fonts \
--ro-bind /etc/resolv.conf /etc/resolv.conf \
--bind ~/.mozilla ~/.mozilla \
--bind ~/Downloads ~/Downloads \
--proc /proc \
--dev /dev \
--tmpfs /tmp \
--unshare-all \
--share-net \
--new-session \
-- /usr/bin/firefox "$@"Bubblejail: A Higher-Level Frontend
If raw bwrap commands feel tedious, Bubblejail
sits on top of Bubblewrap with a Firejail-like feel. It has a GUI for managing sandboxed instances, and each one gets its own home folder. You set up profiles through a services.toml file. It lists which host parts (PulseAudio, GPU, network) the sandbox can reach.

Create a sandboxed Firefox instance:
bubblejail create --profile firefox FirefoxInstanceBubblejail ships about 50 pre-built profiles versus Firejail’s 1,000+. Still, it covers the most common desktop apps.
Head-to-Head Comparison
The right pick depends on your threat model, your comfort with config, and how much time you want to spend tuning.
| Dimension | Firejail | Bubblewrap |
|---|---|---|
| Setup effort | firejail app-name works immediately | Manual mount construction required |
| Profile ecosystem | 1,000+ upstream profiles | None built-in (Bubblejail has ~50) |
| SUID requirement | Yes (SUID-root binary) | No (unprivileged namespaces) |
| Attack surface | Larger (SUID binary has had CVEs) | Smaller (no privileged binary) |
| Network sandboxing | Per-app bridges, bandwidth limits, DNS filtering | All-or-nothing namespace isolation |
| D-Bus filtering | Built-in proxy support | Requires external xdg-dbus-proxy |
| Landlock support | Experimental (0.9.74+) | Not applicable (use with other tools) |
| Performance overhead | Negligible (~5ms namespace setup) | Negligible (~5ms namespace setup) |
| Desktop integration | firecfg auto-sandboxes all profiled apps | Manual (wrapper scripts or Bubblejail) |
The SUID Question
Firejail’s SUID-root binary has caused real security bugs. CVE-2022-31214 was a privilege-escalation flaw in Firejail’s join.c. Local attackers could craft a fake Firejail container, trick the SUID-root binary into joining it, and break out to full root. The bug hit versions before 0.9.68 and got patched. Still, it shows the core tension: a security tool with root rights turns into a juicy target itself.
Bubblewrap sidesteps this by running inside unprivileged user namespaces. There’s no privileged binary to attack. The trade-off: bwrap needs the kernel to have unprivileged user namespaces on. That’s the default on most distros since 2024, but admins can turn it off.
When to Pick Which
Choose Firejail when:
- You want to sandbox many desktop apps with little effort
- You need network filtering, DNS overrides, or bandwidth caps per app
- You’re on a system without unprivileged user namespaces
- You want the
firecfgauto-sandbox for your whole desktop
Choose Bubblewrap when:
- SUID-root binaries are off the table in your threat model
- You need to audit every part of the sandbox config
- You’re sandboxing a small set of specific apps and can spend time per app
- You already use Flatpak and want to learn or tweak its built-in sandbox
Practical Sandboxing Recipes
Firefox with Firejail
Allow only Downloads and the Firefox profile folder:
firejail --whitelist=~/Downloads --whitelist=~/.mozilla firefoxAdd DNS override for privacy:
firejail --whitelist=~/Downloads --whitelist=~/.mozilla --dns=9.9.9.9 firefoxDiscord with an Isolated Home
Give Discord its own home folder, kept apart from your real one:
firejail --private=~/.sandboxes/discord discordAnalyzing an Untrusted Binary
Run a shady binary with no network, no home folder, and auto cleanup:
bwrap \
--ro-bind /usr /usr \
--ro-bind /lib /lib \
--ro-bind /lib64 /lib64 \
--proc /proc \
--dev /dev \
--tmpfs /tmp \
--tmpfs /home \
--unshare-all \
--new-session \
--die-with-parent \
-- ./suspicious-binaryThe --die-with-parent flag kills the sandboxed process when your terminal session exits, cleaning up resources automatically. This pattern is essential for running untrusted code in throwaway sandboxes.
VS Code with Restricted Filesystem
Limit VS Code to only your Projects and Downloads folders:
firejail --whitelist=~/Projects --whitelist=~/Downloads --seccomp codeVS Code’s built-in terminal inherits the same sandbox rules, so shell commands inside VS Code are confined too.
Browser Profile Isolation
Run separate browser instances for separate tasks, each with its own storage:
# Banking browser, no access to other profiles
firejail --private=~/.sandboxes/browser-banking firefox --no-remote
# Social media browser
firejail --private=~/.sandboxes/browser-social firefox --no-remote
# General browsing
firejail --private=~/.sandboxes/browser-general firefox --no-remoteEach one keeps its own cookies, history, and extensions with no cross-access.
Steam with Restricted Access
Stop Steam from reading your documents, SSH keys, or browser data:
firejail --whitelist=~/.local/share/Steam --whitelist=~/Games steamFull GPU and network access stays in place since games need both.
Beyond Firejail and Bubblewrap
A few related tools overlap with or pair well with these two:
Landlock
is a kernel-level LSM. It lets a process cap its own filesystem access with no root rights. Landrun
is a standalone tool on top of Landlock that feels like Firejail with no SUID. Firejail 0.9.74+ can use Landlock as an extra layer via the --landlock flag.
For system services rather than desktop apps, systemd has its own sandbox knobs: DynamicUser=, ProtectHome=, PrivateNetwork=, and similar flags. They give you isolation with no extra tools.
AppArmor and SELinux are MAC systems. They push rules at the kernel level, apart from namespaces. Both stack cleanly on top of Firejail or Bubblewrap.
The xdg-desktop-portal system gives gated access to host parts like the file picker, screen sharing, and printing through D-Bus. Sandboxed apps ask for set rights on demand rather than getting blanket filesystem access.
For most desktop Linux users, Firejail’s profile library and easy on-ramp make it the practical start. If the SUID-root model worries you, Bubblejail sits between Firejail’s ease and Bubblewrap’s small trust base. And for the security-minded who can spend time per app, raw Bubblewrap gives you the tightest sandbox with a full audit trail.
Botmonster Tech