Browser Isolation with Firejail Guide
Firejail is a SUID sandbox that restricts what processes can access using Linux namespaces, seccomp-bpf, and capabilities. When your browser is sandboxed with Firejail, a successful exploit — remote code execution via a malicious PDF or JavaScript vulnerability — is contained: the attacker’s code can’t read your SSH keys, home directory files, or make arbitrary system calls.
What Firejail Does
Firejail creates restricted containers using:
- Linux namespaces: Separate filesystem view, process table, network stack, and user namespace
- seccomp-bpf: Whitelist of allowed system calls — unknown/dangerous calls are blocked
- Capabilities: Drop Linux capabilities the application doesn’t need (e.g., no raw socket access)
- AppArmor (optional): Additional MAC policy layer
The result: a browser running under Firejail sees a restricted subset of your filesystem and can only make system calls that are in the allowed list.
Install Firejail
# Debian/Ubuntu
sudo apt install firejail firejail-profiles
# Fedora
sudo dnf install firejail
# Arch Linux
sudo pacman -S firejail
# Check version
firejail --version
# List available profiles
ls /etc/firejail/*.profile | head -20
Basic Usage
# Run Firefox in a Firejail sandbox
firejail firefox
# Run Chromium sandboxed
firejail chromium
# Run with default profile for the application
firejail --profile=/etc/firejail/firefox.profile firefox
# Inspect what's running inside Firejail
firejail --list
# See the security details of a running sandboxed process
firejail --tree
# Get detailed security status of a specific PID
firejail --status
Desktop Integration (Launch From App Menu)
To always launch Firefox sandboxed, create a desktop entry override:
# Copy system desktop entry to user override directory
cp /usr/share/applications/firefox.desktop ~/.local/share/applications/
# Edit the Exec line
nano ~/.local/share/applications/firefox.desktop
Change Exec=firefox %u to Exec=firejail firefox %u:
[Desktop Entry]
Name=Firefox
Exec=firejail firefox %u
Icon=firefox
Type=Application
Categories=Network;WebBrowser;
MimeType=text/html;text/xml;...
# Refresh desktop database
update-desktop-database ~/.local/share/applications/
# Or use firecfg to automate this for all supported apps
sudo firecfg
# Creates symlinks in /usr/local/bin/ that wrap apps with firejail
Understanding Default Firefox Profile
Examine the default Firejail Firefox profile:
cat /etc/firejail/firefox.profile
Key restrictions applied:
# From firefox.profile:
include globals.local
# Private home directory (creates a temporary home)
private-home firefox-home
# Whitelist specific directories
whitelist ${HOME}/Downloads
whitelist ${HOME}/.mozilla
# Block sensitive paths
blacklist ${HOME}/.ssh
blacklist ${HOME}/.gnupg
blacklist ${HOME}/.config/keepassxc
# Network restrictions
# (by default, network access is unrestricted)
# Disable D-Bus (prevents IPC with system)
nodbus
# Drop dangerous capabilities
caps.drop all
caps.keep net_bind_service
# Seccomp filter (deny dangerous syscalls)
seccomp
Custom Profile: Hardened Firefox
Create a stricter profile for maximum isolation:
# Create custom profile
nano ~/.config/firejail/firefox.local
# ~/.config/firejail/firefox.local
# This file is included by /etc/firejail/firefox.profile
# Block clipboard access to/from system (prevents clipboard snooping)
# Remove if you need copy-paste between sandboxed and non-sandboxed apps
# x11
# Restrict file access to only Downloads
private-home firefox-sandbox
whitelist ${HOME}/Downloads
whitelist ${HOME}/.mozilla
# Block access to other user data
blacklist ${HOME}/Documents
blacklist ${HOME}/Pictures
blacklist ${HOME}/.ssh
blacklist ${HOME}/.aws
blacklist ${HOME}/.config/keepassxc
blacklist ${HOME}/.local/share/keyrings
# Disable sound if not needed (reduces attack surface)
# nosound
# Use a private /tmp (prevents /tmp sniffing)
private-tmp
# Private network namespace: only allow specific interfaces
# net eth0 # Uncomment to restrict to specific interface
Network Isolation for Sandboxed Apps
Firejail can create a completely separate network namespace:
# Run browser with isolated network (requires network bridge setup)
firejail --net=eth0 firefox
# Run with no network access at all
firejail --net=none firefox # Useful for testing or offline use
# Run on a VPN interface only (forces all traffic through VPN)
firejail --net=wg0 firefox
# If VPN drops, browser loses network entirely (natural kill switch)
# Create a network sandbox that can only reach Tor
firejail --net=lo --netfilter firefox
# Then use tor's SOCKS proxy at 127.0.0.1:9050
Sandbox Testing: Verify What’s Blocked
# Run a test to see what Firejail blocks
firejail --debug bash
# Inside the sandbox, try to access restricted paths:
cat ~/.ssh/id_rsa # Should fail: No such file or directory
ls ~/Documents # Should fail if blacklisted
# Check what filesystem the sandbox sees
mount | grep tmpfs # Shows private mounts created by Firejail
# Check system call filtering
strace -e trace=all ls 2>&1 | head -20
# Certain syscalls will show EPERM if blocked by seccomp
Firejail for Other Applications
# Sandbox a PDF reader (high-value target for malicious PDFs)
firejail evince malicious-document.pdf
firejail okular research-paper.pdf
# Sandbox media players
firejail vlc downloaded-video.mp4
# Sandbox email client
firejail thunderbird
# Sandbox an unknown binary (testing)
firejail --net=none --private ./unknown-program
# No network + private home = maximum isolation for unknown executables
Audit Firejail’s Effectiveness
# Check what seccomp filters are applied
firejail --debug --seccomp firefox 2>&1 | grep "seccomp"
# See the full security report for a running sandboxed process
firejail --list
# Get the PID, then:
firejail --status [PID]
# Try to escape from inside a sandbox (penetration testing)
# Inside sandboxed bash:
ls /proc/1/root # Should be restricted
cat /etc/shadow # Should fail
cat ~/.ssh/id_rsa # Should fail if blacklisted
Combining Firejail with AppArmor
For double-layered isolation, combine Firejail (process-level) with AppArmor (MAC policy):
# Check AppArmor status
sudo aa-status | grep -i firefox
# Firejail's AppArmor profile is auto-applied if AppArmor is active
firejail --apparmor firefox
# Create a tight AppArmor profile for the sandboxed browser
sudo aa-genprof firejail
# Follow prompts to define allowed behavior
sudo systemctl reload apparmor
Performance Impact
Firejail adds minimal CPU overhead (< 1% for most apps). The main cost is startup time:
# Compare startup times
time firejail firefox --headless --window-size 1 1 &
time firefox --headless --window-size 1 1 &
# Difference is typically 0.1-0.5 seconds for namespace setup
For GPU-accelerated applications (browsers, video players), Firejail requires DRI device access:
# Allow DRI (GPU) access in profile:
# In your local profile file:
# whitelist /dev/dri
# noblacklist /dev/dri
Related Reading
- How to Use Qubes OS for Maximum Compartmentalization
- Browser Fingerprinting and Privacy
- How to Use Whonix for Anonymous Browsing
Built by theluckystrike — More at zovo.one
Frequently Asked Questions
How long does it take to complete this setup?
For a straightforward setup, expect 30 minutes to 2 hours depending on your familiarity with the tools involved. Complex configurations with custom requirements may take longer. Having your credentials and environment ready before starting saves significant time.
What are the most common mistakes to avoid?
The most frequent issues are skipping prerequisite steps, using outdated package versions, and not reading error messages carefully. Follow the steps in order, verify each one works before moving on, and check the official documentation if something behaves unexpectedly.
Do I need prior experience to follow this guide?
Basic familiarity with the relevant tools and command line is helpful but not strictly required. Each step is explained with context. If you get stuck, the official documentation for each tool covers fundamentals that may fill in knowledge gaps.
Can I adapt this for a different tech stack?
Yes, the underlying concepts transfer to other stacks, though the specific implementation details will differ. Look for equivalent libraries and patterns in your target stack. The architecture and workflow design remain similar even when the syntax changes.
Where can I get help if I run into issues?
Start with the official documentation for each tool mentioned. Stack Overflow and GitHub Issues are good next steps for specific error messages. Community forums and Discord servers for the relevant tools often have active members who can help with setup problems.