FIREJAIL(1)
๐ FIREJAIL(1) ๐
okay bestie, welcome to the firejail man page โ the firejail manual, section 1, and honestly? it's a whole journey. grab a strawberry drink ๐ and let's go.
โจ NAME โจ
Firejail โ a Linux namespaces sandbox program. that's it, that's the name, no cap.
๐ฆ SYNOPSIS ๐ฆ
k so there's like five whole ways to summon this thing. here they all are, verbatim, don't @ me:
start a sandbox:
firejail [OPTIONS] [program and arguments]
start an AppImage program:
firejail [OPTIONS] --appimage [OPTIONS] [appimage-file and
arguments]
file transfer from an existing sandbox:
firejail {--ls | --get | --put | --cat} dir_or_filename
monitoring:
firejail {--list | --netstats | --top | --tree}
miscellaneous:
firejail {-? | --debug-caps | --debug-errnos | --debug-syscalls |
--debug-syscalls32 | --debug-protocols | --help | --version}
๐ DESCRIPTION ๐
so. Firejail is a SUID sandbox program whose whole entire job is reducing the risk of security breaches by restricting the running environment of untrusted applications โ using Linux namespaces, seccomp-bpf, and Linux capabilities. it literally lets a process and all its descendants have their own private view of the globally shared kernel resources. like the network stack, the process table, the mount table. main character energy for your process tree, fr fr. ๐
it can also work inside a SELinux or AppArmor environment, and it's integrated with Linux Control Groups. versatile icon.
written in C with virtually no dependencies, the software runs on any Linux computer with a 3.x kernel version or newer. and it can sandbox any type of process: servers, graphical applications, even user login sessions. everything. all of it. ๐ญ
Firejail lets you manage application security using security profiles. each profile defines a set of permissions for a specific application or group of applications. the software ships with security profiles for a bunch of more common Linux programs, like Mozilla Firefox, Chromium, VLC, Transmission, etc. iconic behavior honestly.
๐จ okay this part is important so pay attention bestie:Firejailis currently implemented as an SUID binary, which means that if a malicious or compromised user account manages to exploit a bug inFirejail, that could ultimately lead to a privilege escalation to root. to mitigate this, it is recommended to only allow trusted users to runfirejail(seefirejail-users(5)for details on how to achieve that). for more details on the security/usability tradeoffs ofFirejail, see:#4601.
alternative sandbox technologies like Snap (see https://snapcraft.io) and Flatpak (see https://flatpak.org) are not supported. like, at all. Snap and Flatpak packages have their own native management tools and will not work when sandboxed with Firejail. they said "we have our own thing going on" and honestly? respect.
๐ธ USAGE ๐ธ
without any options, the sandbox consists of a filesystem built in a new mount namespace, plus new PID and UTS namespaces. IPC, network and user namespaces can be added using the command line options โ you just gotta ask. โจ
the default Firejail filesystem is based on the host filesystem with the main system directories mounted read-only. those directories are /etc, /var, /usr, /bin, /sbin, /lib, /lib32, /libx32 and /lib64. only /home and /tmp are writable. so all the fun stuff is locked in glass, cute but untouchable. ๐
upon execution Firejail first looks in ~/.config/firejail/ for a profile, and if it doesn't find one, it looks in /etc/firejail/. if an appropriate profile is not found, Firejail will use a default profile. and the default profile is quite restrictive. so in case the application doesn't work, use --noprofile option to disable it. no shame in it, we've all been there.
if a program argument is not specified, Firejail starts the user's preferred shell. examples, bestie, look:
$ firejail [OPTIONS] # starting the program
specified in $SHELL, usually /bin/bash
$ firejail [OPTIONS] /usr/bin/firefox # starting Mozilla Firefox
# sudo firejail [OPTIONS] /etc/init.d/nginx start
when an option is specified multiple times (whether in a profile, on the command line, or both) or conflicts with a related option, the precedence/behavior is option-specific and usually documented in the OPTIONS section below. note that an option specified in a profile can generally be disabled on the command line using --ignore. iykyk.
๐ OPTIONS ๐
okay this is the long part. buckle up. every single flag, zero skips, let's go. ๐ง
--โ signals the end of options and disables further option processing. like a little "ok we're done with flags now" curtain drop. ๐ญ--allow-bwrapโ by defaultfirejailreplaces the/usr/bin/bwrapexecutable with a do-nothing program. our replacement just runs the bubblewrap target, and is visible only inside thefirejailsandbox. use this option to disable this default functionality. slay, but like, don't.
Example:
$ firejail --noprofile --allow-bwrap bwrap --help
firejail version 0.9.77
Parent pid 44129, child pid 44130
Base filesystem installed in 0.04 ms
Child process initialized in 5.02 ms
usage: bwrap [OPTIONS...] [--] COMMAND [ARGS...]
--help Print this help
--version Print version
--args FD Parse NUL-separated args from FD
--allow-debuggersโ allows tools such asstraceandgdbinside the sandbox by whitelisting system callsptraceandprocess_vm_readv. ๐ต๏ธ this option is only available when running on Linux kernels4.8or newer โ a kernel bug inptracesystem call allows a full bypass of the seccomp filter. so like, older kernels said no.
Example:
$ firejail --allow-debuggers
--profile=/etc/firejail/firefox.profile strace -f
/usr/bin/firefox
see also --private-etc and --trace.
--allusersโ all directories under/homeare visible inside the sandbox. by default, only the current user home directory is visible. so this is the "let them see everyone" button. ๐
Example:
$ firejail --allusers
--apparmorโ enables AppArmor confinement with the"firejail-default"AppArmor profile. for more information, please see the APPARMOR section below. ๐ก๏ธ--apparmor=profile_nameโ enables AppArmor confinement with a custom AppArmor profile. note that the profile in question must already be loaded into the kernel. for more information, please see the APPARMOR section below. no auto-magic loading, sorry bestie.--apparmor.print=name|pidโ prints the AppArmor confinement status for the sandbox identified by name or by PID. very "who are you and what are you wearing" of it.
Example:
$ firejail --apparmor.print=browser
5074:netblue:/usr/bin/firejail /usr/bin/firefox-esr
AppArmor: firejail-default enforce
--appimageโ sandboxes an AppImage (seehttps://appimage.org) application. if the sandbox is started as a regular user,nonewprivsand a default capabilities filter are enabled.private-binis disabled by default when running appimages.
Example:
$ firejail --appimage --profile=krita krita-3.0-x86_64.appimage
$ firejail --quiet --appimage --private --profile=krita
krita-3.0-x86_64.appimage
$ firejail --appimage --net=none --x11 --profile=krita
krita-3.0-x86_64.appimage
Note 1: when using both --appimage and --profile, it is recommended to always specify the former before the latter, so that any ?HAS_APPIMAGE conditionals inside of the profile evaluate to true (see ?CONDITIONAL in firejail-profile(5)). order matters, periodt. ๐
Note 2: if you want to disable networking by default every time you sandbox an appimage, add a conditional in /etc/firejail/globals.local as follows:
$ cat /etc/firejail/globals.local
?HAS_APPIMAGE: net none
--bind=filename1,filename2โ mount-binds filename1 on top of filename2. this option is only available when running as root. ๐
Example:
# firejail --bind=/config/etc/passwd,/etc/passwd
--blacklist=dirname_or_filenameโ blacklists a directory or file. this makes a file or directory completely inaccessible. all other files and directories are unaffected. the blacklisted file or directory is still visible on the filesystem, even if it's inaccessible. like it's at the party but you can't talk to it. ๐
Symbolic link handling: blacklisting a path that is a symbolic link will also blacklist the path that it points to. for example, if ~/foo is blacklisted and it points to /bar, then /bar will also be blacklisted. symlinks to /dev/null are not followed (only the symlink itself will be affected), as replacing certain paths with symlinks to /dev/null is not uncommon and restricting access to /dev/null can lead to unexpected issues (see #5803). using /dev/null directly (instead of through a symlink) should work normally.
file globbing is supported, see the FILE GLOBBING section for more details. โจ
Example:
$ firejail --blacklist=/sbin --blacklist=/usr/sbin
$ firejail --blacklist=~/.mozilla
$ firejail --blacklist="/home/username/My Virtual Machines"
--buildโ the command builds a whitelisted profile. the profile is printed on the screen. the program is run in a very relaxed sandbox, with only--caps.drop=alland--seccomp=!chroot. programs that raise user privileges are not supported. ๐๏ธ
Note: this option is intended for profile debugging and development. the profile that is generated may be incomplete, non-functional and lacking in security. if you want to try to create a new profile, see CONTRIBUTING.md. it's giving "rough draft, don't ship it".
Example:
$ firejail --build /usr/bin/vlc ~/Videos/test.mp4
$ firejail --build --appimage ~/Downloads/Subsurface.AppImage
--build=profile-fileโ the command builds a whitelisted profile, and saves it in profile-file. the program is run in a very relaxed sandbox, with only--caps.drop=alland--seccomp=!chroot. programs that raise user privileges are not supported.
Note: this option is intended for profile debugging and development. the profile that is generated may be incomplete, non-functional and lacking in security. if you want to try to create a new profile, see CONTRIBUTING.md.
Example:
$ firejail --build=vlc.profile /usr/bin/vlc ~/Videos/test.mp4
$ firejail --build=Subsurface.profile --appimage
~/Downloads/Subsurface.AppImage
-cโ login shell compatibility option. this option is used by some login programs when executing the login shell, such as whenfirejailis used as a restricted login shell. it currently does not change the execution offirejail. it's literally just there vibing. ๐ซถ--capsโ Linux capabilities is a kernel feature designed to split up the root privilege into a set of distinct privileges. these privileges can be enabled or disabled independently, thus restricting what a process running as root can do in the system. seecapabilities(7)for details. ๐ฅ--capsโ so this one's the default vibe for root programs: they run with every capability enabled ๐ฌ but--capsshuts off this whole lil' roster:CAP_SYS_MODULE,CAP_SYS_RAWIO,CAP_SYS_BOOT,CAP_SYS_NICE,CAP_SYS_TTY_CONFIG,CAP_SYSLOG,CAP_MKNOD,CAP_SYS_ADMIN. And like, the filter hits every process started inside the sandbox, no exceptions bestie ๐
Example:
$ sudo firejail --caps /etc/init.d/nginx start
--caps.drop=allโ drops all the capabilities for processes running in the sandbox. Lowkey this is the recommended one for GUI programs or literally anything that doesn't need root privileges. And honestly? It's a must-have for sandboxing untrusted stuff from unofficial sources โ games, Java programs, that whole sketchy category ๐ฎโ
Example:
$ firejail --caps.drop=all /usr/bin/warzone2100
--caps.drop=capability,capability,capabilityโ build your own custom blacklist Linux capabilities filter ๐ค
Example:
$ firejail --caps.drop=net_broadcast,net_admin,net_raw
--caps.keep=capability,capability,capabilityโ and this one's the opposite energy: a custom whitelist Linux capabilities filter ๐ค
Example:
$ sudo firejail --caps.keep=chown,net_bind_service,setgid,\
setuid /etc/init.d/nginx start
--caps.print=name|pidโ prints the caps filter for the sandbox, identified by name or by PID. Peek at the receipts ๐
Example:
$ firejail --name=mygame --caps.drop=all /usr/bin/warzone2100 &
$ firejail --caps.print=mygame
Example:
$ firejail --list
3272:netblue::firejail --private /usr/bin/firefox
$ firejail --caps.print=3272
--cat=name|pid filenameโ prints the content of a file from the sandbox container ๐ฑ (see the FILE TRANSFER section for the full tea, bestie).--cpu=cpu-number,cpu-number,cpu-numberโ sets CPU affinity, aka tells your program exactly which cores it's allowed to touch โจ
Example:
$ firejail --cpu=0,1 /usr/bin/handbrake
--cpu.print=name|pidโ prints the CPU cores in use by the sandbox, matched by name or by PID ๐
Example:
$ firejail --name=mygame --caps.drop=all /usr/bin/warzone2100 &
$ firejail --cpu.print=mygame
Example:
$ firejail --list
3272:netblue::firejail --private /usr/bin/firefox
$ firejail --cpu.print=3272
--dbus-log=fileโ tells it where to put the DBus log file ๐
The log file collects events for both the system and session buses if you've specified both --dbus-system.log and --dbus-user.log. And if you don't give a log file path at all? Logs go to standard output instead. Easy.
Example:
$ firejail --dbus-system=filter --dbus-system.log \
--dbus-log=dbus.txt
--dbus-system=filter|noneโ sets the system DBus sandboxing policy.
The filter policy enables the system DBus filter. Heads up: this option requires installing the xdg-dbus-proxy utility ๐ ๏ธ Permissions for well-known names can be specified with the --dbus-system.talk and --dbus-system.own options.
The none policy disables access to the system DBus. Like, fully.
Real talk: only the regular system DBus UNIX socket is handled by this option. To disable the abstract sockets (and force applications to use the filtered UNIX socket) you'd need to request a new network namespace using the--netcommand. Another option is to removeunixfrom the--protocolset. Iykyk ๐ซถ
Example:
$ firejail --dbus-system=none
--dbus-system.broadcast=name=[member][@path]โ lets the app receive broadcast signals from the indicated interface member at the indicated object path exposed by the indicated bus name on the system DBus ๐ก The name may have a.*suffix to match all names underneath it, including itself. The interface member may have a.*to match all members of an interface, or be*to match all interfaces. The path may have a/*suffix to indicate all objects underneath it, including itself. Omitting the interface member or the object path will match all members and object paths, respectively.
Example:
$ firejail --dbus-system=filter --dbus-system.broadcast=\
org.freedesktop.Notifications=\
org.freedesktop.Notifications.*@/org/freedesktop/Notifications
--dbus-system.call=name=[member][@path]โ lets the app call the indicated interface member at the indicated object path exposed by the indicated bus name on the system DBus ๐ Same matching rules, fr: the name may have a.*suffix to match all names underneath it, including itself. The interface member may have a.*to match all members of an interface, or be*to match all interfaces. The path may have a/*suffix to indicate all objects underneath it, including itself. Omitting the interface member or the object path will match all members and object paths, respectively.
Example:
$ firejail --dbus-system=filter --dbus-system.call=\
org.freedesktop.Notifications=\
org.freedesktop.Notifications.*@/org/freedesktop/Notifications
--dbus-system.logโ turns on DBus logging for the system DBus ๐ชต This one requires--dbus-system=filter.
Example:
$ firejail --dbus-system=filter --dbus-system.log
--dbus-system.own=nameโ lets the app own the specified well-known name on the system DBus ๐ The name may have a.*suffix to match all names underneath it, including itself (e.g."foo.bar.*"matches"foo.bar","foo.bar.baz"and"foo.bar.baz.quux", but not"foobar").
Example:
$ firejail --dbus-system=filter --dbus-system.own=\
org.gnome.ghex.*
--dbus-system.see=nameโ lets the app see the specified well-known name on the system DBus, but not talk to it ๐ Same suffix rules: the name may have a.*suffix to match all names underneath it, including itself (e.g."foo.bar.*"matches"foo.bar","foo.bar.baz"and"foo.bar.baz.quux", but not"foobar").
Example:
$ firejail --dbus-system=filter --dbus-system.see=\
org.freedesktop.Notifications
--dbus-system.talk=nameโ lets the app talk to the specified well-known name on the system DBus ๐ฌ And again: the name may have a.*suffix to match all names underneath it, including itself (e.g."foo.bar.*"matches"foo.bar","foo.bar.baz"and"foo.bar.baz.quux", but not"foobar").
Example:
$ firejail --dbus-system=filter --dbus-system.talk=\
org.freedesktop.Notifications
--dbus-user=filter|noneโ sets the session DBus sandboxing policy (yes, the session one this time, keep up bestie ๐).
The filter policy enables the session DBus filter. This option requires installing the xdg-dbus-proxy utility. Permissions for well-known names can be added with the --dbus-user.talk and --dbus-user.own options.
The none policy disables access to the session DBus.
Same caveat as the system one: only the regular session DBus UNIX socket is handled by this option. To disable the abstract sockets (and force applications to use the filtered UNIX socket) you'd need to request a new network namespace using the--netcommand. Another option is to removeunixfrom the--protocolset.
Example:
$ firejail --dbus-user=none
--dbus-user.broadcast=name=[member][@path]โ lets the app receive broadcast signals from the indicated interface member at the indicated object path exposed by the indicated bus name on the session DBus ๐ก The name may have a.*suffix to match all names underneath it, including itself. The interface member may have a.*to match all members of an interface, or be*to match all interfaces. The path may have a/*suffix to indicate all objects underneath it, including itself. Omitting the interface member or the object path will match all members and object paths, respectively.
Example:
$ firejail --dbus-user=filter --dbus-user.broadcast=\
org.freedesktop.Notifications=\
org.freedesktop.Notifications.*@/org/freedesktop/Notifications
--dbus-user.call=name=[member][@path]โ lets the app call the indicated interface member at the indicated object path exposed by the indicated bus name on the session DBus ๐ The name may have a.*suffix to match all names underneath it, including itself. The interface member may have a.*to match all members of an interface, or be*to match all interfaces. The path may have a/*suffix to indicate all objects underneath it, including itself. Omitting the interface member or the object path will match all members and object paths, respectively.
Example:
$ firejail --dbus-user=filter --dbus-user.call=\
org.freedesktop.Notifications=\
org.freedesktop.Notifications.*@/org/freedesktop/Notifications
--dbus-user.logโ turns on DBus logging for the session DBus ๐ชต Requires--dbus-user=filter.
Example:
$ firejail --dbus-user=filter --dbus-user.log
--dbus-user.own=nameโ lets the app own the specified well-known name on the session DBus ๐ The name may have a.*suffix to match all names underneath it, including itself (e.g."foo.bar.*"matches"foo.bar","foo.bar.baz"and"foo.bar.baz.quux", but not"foobar").
Example:
$ firejail --dbus-user=filter --dbus-user.own=org.gnome.ghex.*
--dbus-user.see=nameโ lets the app see, but not talk to, the specified well-known name on the session DBus ๐ The name may have a.*suffix to match all names underneath it, including itself (e.g."foo.bar.*"matches"foo.bar","foo.bar.baz"and"foo.bar.baz.quux", but not"foobar").
Example:
$ firejail --dbus-user=filter --dbus-user.see=\
org.freedesktop.Notifications
--dbus-user.talk=nameโ lets the app talk to the specified well-known name on the session DBus ๐ฌ The name may have a.*suffix to match all names underneath it, including itself (e.g."foo.bar.*"matches"foo.bar","foo.bar.baz"and"foo.bar.baz.quux", but not"foobar").
Example:
$ firejail --dbus-user=filter --dbus-user.talk=\
org.freedesktop.Notifications
--debugโ prints debug messages ๐ the classic "what is actually happening in there" button.
Example:
$ firejail --debug /usr/bin/firefox
--debug-blacklistsโ bestie this one debugs blacklisting, that's it, that's the vibe โจ
Example:
$ firejail --debug-blacklists /usr/bin/firefox
--debug-capsโ prints, like, all the recognized capabilities in the current Firejail software build and then dips ๐
Example:
$ firejail --debug-caps
--debug-errnosโ prints all recognized error numbers in the current Firejail software build and exits. slay ๐
Example:
$ firejail --debug-errnos
--debug-protocolsโ prints all recognized protocols in the current Firejail software build and exits, iconic behavior ๐
Example:
$ firejail --debug-protocols
--debug-syscall-groups[=@group1,@group2,@all,...]โ prints all system call groups and descriptions, then exits. ngl this one's kind of the main character of debug flags ๐
Pass seccomp groups comma-separated and it'll print their system calls in the current Firejail software build and exit. Also the special group @all exists for printing every seccomp group plus its related syscalls, iykyk.
Example:
$ firejail --debug-syscall-groups
$ firejail --debug-syscall-groups=@chown,@mount,@swap
$ firejail --debug-syscall-groups=@all
--debug-syscallsโ prints all recognized system calls in the current Firejail software build and exits ๐
Example:
$ firejail --debug-syscalls
Note: the syscall mapping comes directly from the architecture-specific.tblfiles in the Linux kernel sources, which get transformed into header files insrc/includeand built into firejail. Only syscalls for the build target architecture and 32-bit variants (if applicable) are included in the build โ like forx86_64andx86respectively ๐. If a syscall number or name is not listed, it is not recognized by firejail. This may be because the syscall isn't present in the.tblfile (obsolete syscalls, we see you), because it hasn't been added to firejail yet, or because your current build of firejail is just too old. not me calling out stale builds ๐ญ
Example .tbl files for x86_64 and x86 on Linux v6.19:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/entry/syscalls/syscall_64.tbl?h=v6.19
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/entry/syscalls/syscall_32.tbl?h=v6.19
--debug-syscalls32โ prints all recognized 32 bit system calls in the current Firejail software build and exits. literally the same as--debug-syscallsbut for the 32-bit syscalls ๐ฆ--debug-whitelistsโ debug whitelisting, that's the whole gig โจ
Example:
$ firejail --debug-whitelists /usr/bin/firefox
--defaultgw=addressโ use thisaddressas the default gateway in the new network namespace ๐ธ๏ธ
Example:
$ firejail --net=eth0 --defaultgw=10.10.20.1 /usr/bin/firefox
--deterministic-exit-codeโ always exit firejail with the first child's exit status. The default behavior is to use the exit status of the final child to exit, which can be nondeterministic. so if you like your outcomes predictable, this is your girl ๐--deterministic-shutdownโ always shut down the sandbox after the first child has terminated. The default behavior is to keep the sandbox alive as long as it contains running processes. choose your fighter ๐--disable-mntโ blacklists/mnt,/media,/run/mountand/run/mediaaccess. no peeking ๐
Example:
$ firejail --disable-mnt /usr/bin/firefox
--dns=addressโ set a DNS server for the sandbox. Up to three DNS servers can be defined. Use this option if you don't trust the DNS setup on your network ๐
Example:
$ firejail --dns=8.8.8.8 --dns=8.8.4.4 /usr/bin/firefox
Note: this feature is not supported on systemd-resolved setups. sad but true ๐
--dns.print=name|pidโ print DNS configuration for a sandbox identified bynameor by PID ๐จ๏ธ
Example:
$ firejail --name=mygame --caps.drop=all /usr/bin/warzone2100 &
$ firejail --dns.print=mygame
Example:
$ firejail --list
3272:netblue::firejail --private /usr/bin/firefox
$ firejail --dns.print=3272
--dnstrace[=name|pid]โ monitor DNS queries ๐๏ธ The sandbox can be specified bynameorpid. Only networked sandboxes created with--netare supported. This option is only available when running the sandbox as root.
Without a name/pid, Firejail will monitor the main system network namespace. fr fr it just watches everything ๐
Example:
$ sudo firejail --dnstrace
11:31:43 9.9.9.9 linux.com (type 1)
11:31:45 9.9.9.9 fonts.googleapis.com (type 1) NXDOMAIN
11:31:45 9.9.9.9 js.hs-scripts.com (type 1) NXDOMAIN
11:31:45 9.9.9.9 www.linux.com (type 1)
11:31:45 9.9.9.9 fonts.googleapis.com (type 1) NXDOMAIN
11:31:52 9.9.9.9 js.hs-scripts.com (type 1) NXDOMAIN
11:32:05 9.9.9.9 secure.gravatar.com (type 1)
11:32:06 9.9.9.9 secure.gravatar.com (type 1)
11:32:08 9.9.9.9 taikai.network (type 1)
11:32:08 9.9.9.9 cdn.jsdelivr.net (type 1)
11:32:08 9.9.9.9 taikai.azureedge.net (type 1)
11:32:08 9.9.9.9 www.youtube.com (type 1)
--env=name=valueโ set an environment variable in the new sandbox ๐ธ so your app gets the tea it needs
Example:
$ firejail --env=LD_LIBRARY_PATH=/opt/test/lib
--fs.print=name|pidโ print the filesystem log for the sandbox identified bynameor by PID ๐ receipts, basically
Example:
$ firejail --name=mygame --caps.drop=all /usr/bin/warzone2100 &
$ firejail --fs.print=mygame
Example:
$ firejail --list
3272:netblue::firejail --private /usr/bin/firefox
$ firejail --fs.print=3272
--get=name|pid filenameโ get a file from a sandbox container ๐ซณ see the FILE TRANSFER section for more details, bestie-?,--helpโ print options and exit. (yes, the original page says "end exit" โ typos are canon, we do not fix, we respect the artifact ๐) anyway it's the help flag, it helps ๐--hostname=nameโ set sandbox hostname. This is incompatible with--hostname-randomize. For valid names, see the NAME VALIDATION section ๐
Example:
$ firejail --hostname=officepc /usr/bin/firefox
--hostname-randomizeโ set sandbox hostname to a random value generated by firejail. This is incompatible with--hostname. chaos mode activated ๐ฒ
Example:
$ firejail --hostname-randomize /usr/bin/firefox
Note: changing the hostname may cause breakage related to networking (see#7048) and may cause X11 programs to crash on startup due to not being able to authenticate to the X server (see#7062). not to be dramatic but ๐ญ
--hosts-file=fileโ usefileas/etc/hosts๐
Example:
$ firejail --hosts-file=~/myhosts /usr/bin/firefox
--icmptrace[=name|pid]โ monitor ICMP traffic ๐ก The sandbox can be specified bynameorpid. Only networked sandboxes created with--netare supported. This option is only available when running the sandbox as root.
Without a name/pid, Firejail will monitor the main system network namespace. same energy as --dnstrace but for pings ๐
Example
$ sudo firejail --icmptrace
20:53:54 192.168.1.60 -> 142.250.65.174 - 98 bytes - Echo request/0
20:53:54 142.250.65.174 -> 192.168.1.60 - 98 bytes - Echo reply/0
20:53:55 192.168.1.60 -> 142.250.65.174 - 98 bytes - Echo request/0
20:53:55 142.250.65.174 -> 192.168.1.60 - 98 bytes - Echo reply/0
20:53:55 192.168.1.60 -> 1.1.1.1 - 154 bytes - Destination unreachable/Port unreachable
--ignore=commandโ ignorecommandin the profile file ๐ซ like a soft block, but for profile lines
Example:
$ firejail --ignore=seccomp --ignore=caps /usr/bin/firefox
$ firejail --ignore="net eth0" /usr/bin/firefox
--include=file.profileโ include a profile file before the regular profiles are used ๐ง stacking profiles like accessories
Example:
$ firejail --include=/etc/firejail/disable-devel.inc /usr/bin/gedit
--interface=interfaceโ moveinterfaceinto a new network namespace. Up to four--interfaceoptions can be specified. ๐
Note: wlan devices are not supported for this option. wifi girlies, this one's not for you ๐
Example:
$ firejail --interface=eth1 --interface=eth0.vlan100
--ip=addressโ assign IP addresses to the last network interface defined by a--netoption. A default gateway is assigned by default ๐
Example:
$ firejail --net=eth0 --ip=10.10.20.56 /usr/bin/firefox
--ip=noneโ no IP address and no default gateway are configured for the last interface defined by a--netoption. nothing. void. empty. ๐
Example:
$ firejail --net=eth0 --ip=none
If the corresponding interface doesn't have an IP address configured, this option is enabled by default. so sometimes it's just, like, the vibe already โจ
--ip6=addressโ assign IPv6 addresses to the last network interface defined by a--netoption ๐
Example:
$ firejail --net=eth0 --ip6=2001:0db8:0:f101::1/64 /usr/bin/firefox
Note: you don't need this option if you obtain your ip6 address from the router via SLAAC (your ip6 address and default route will be configured by the kernel automatically). the kernel handles it, she's got this ๐
--iprange=address,addressโ assign an IP address in the provided range to the last network interface defined by a--netoption. A default gateway is assigned by default ๐ฏ
Example:
$ firejail --net=eth0 --iprange=192.168.1.100,192.168.1.150
--ipc-namespaceโ enable a new IPC namespace if the sandbox was started as a regular user. IPC namespace is enabled by default for sandboxes started as root ๐
Note: This only affects the IPC resources that are mentioned inipc_namespaces(7). It does not affect other IPC resources, such as Unix sockets (seeunix(7)). important distinction bestie, don't let anyone tell you otherwise ๐ซถ
Example:
$ firejail --ipc-namespace /usr/bin/firefox
--join=name|pidโ join the sandbox identified bynameor by PID ๐ค By default a/bin/bashshell is started after joining the sandbox. If a program is specified, the program is run in the sandbox.
If --join is issued as a regular user, all security filters are configured for the new process the same they are configured in the sandbox. If --join is issued as root, the security filters and cpus configurations are not applied to the process joining the sandbox. yes this is a whole thing, read it twice ๐
Example:
$ firejail --name=mygame --caps.drop=all /usr/bin/warzone2100 &
$ firejail --join=mygame
Ok so we left off mid-example for --join, and bestie the payoff is this:
$ firejail --list
3272:netblue::firejail --private /usr/bin/firefox
$ firejail --join=3272
Like, you see the PID, you slide into its DMs. Iconic. ๐
--join-filesystem=name|pidโ hop into the mount namespace of the sandbox that matches that name or PID. By default you land in a/bin/bashshell once you're in there, but if you hand it a program, that program runs inside the sandbox instead. ๐ชโจ Only the root user can do this one โ sorry bestie, it's a VIP-only door. Also important: security filters and cpus configurations are not applied to the process that joins the sandbox. So it's like sneaking in through a window, not going through the metal detector.--join-network=name|pidโ same deal but for the network namespace, identified by name. By default you get a/bin/bashshell after joining; give it a program and that program runs inside the sandbox. Again, root user only. Again, security filters and cpus configurations are not applied to the joining process. Here's the whole glow-up in action:
# start firefox
$ firejail --net=eth0 --name=browser /usr/bin/firefox &
# change netfilter configuration
$ sudo firejail --join-network=browser bash -c "cat /etc/firejail/nolocal.net | /sbin/iptables-restore"
# verify netfilter configuration
$ sudo firejail --join-network=browser /sbin/iptables -vL
# verify IP addresses
$ sudo firejail --join-network=browser ip addr
Switching to pid 1932, the first child process inside the sandbox
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0-1931: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
link/ether 76:58:14:42:78:e4 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.158/24 brd 192.168.1.255 scope global eth0-1931
valid_lft forever preferred_lft forever
inet6 fe80::7458:14ff:fe42:78e4/64 scope link
valid_lft forever preferred_lft forever
Look at all those addresses. She's thriving. ๐
--join-or-start=nameโ the "either way I'm getting what I want" option ๐ซถ. It joins the sandbox identified by name, or starts a brand new one if there isn't one. Same asfirejail --join=nameif a sandbox with that name exists, otherwise same asfirejail --name=name .... Peep--namefor the details. And heads up: in contrary to other join options there is a respective profile option for this one. Lowkey special like that.--keep-config-pulseโ turns off the automatic~/.config/pulseinit. For complex setups, like remote pulse servers or non-standard socket paths. If that's your situation, you already know. ๐ง
Example:
$ firejail --keep-config-pulse /usr/bin/firefox
--keep-dev-ntsyncโ lets the sandbox touch the/dev/ntsynccharacter device (even with--private-dev), which is blocked by default. This device is mostly intended to boost performance and compatibility when running certain programs through Wine. ๐ท
Example:
$ firejail --keep-dev-ntsync --private-dev
--keep-dev-shmโ leaves the/dev/shmdirectory untouched (even with--private-dev). Hands off, she's fine. ๐ โโ๏ธ
Example:
$ firejail --keep-dev-shm --private-dev
--keep-dev-tpmโ lets the sandbox reach the Trusted Cryptography Module (TCM) and Trusted Platform Module (TPM) devices (even with--private-dev), because yeah, they're blocked by default. The paths it covers:
/dev/tcm[0-9]*
/dev/tcmrm[0-9]*
/dev/tpm[0-9]*
/dev/tpmrm[0-9]*
Example:
$ firejail --keep-dev-tpm --private-dev
--keep-fd=allโ inherit all open file descriptors into the sandbox. By default only file descriptors 0, 1 and 2 are inherited, and all the others get closed. Like, evicted. ๐
Example:
$ firejail --keep-fd=all
--keep-fd=file_descriptorโ don't close the specific open file descriptors you name. Same default story: only file descriptors 0, 1 and 2 are inherited, everything else is closed. This is the "no bestie, not that one" version. ๐
Example:
$ firejail --keep-fd=3,4,5
--keep-shell-rcโ ok context: when you're using a private home directory, firejail copies files from the system's user home template (/etc/skel) into it, which overrides any attempts to whitelist your original files (things like~/.bashrcand~/.zshrc). Rude, honestly. This option disables that feature and lets you whitelist the original files. Your rc files, your rules. ๐--keep-var-tmpโ the/var/tmpdirectory is left untouched. ๐ซง
Example:
$ firejail --keep-var-tmp
๐ง Landlock era (experimental, tread lightly) ๐ง
Every single one of these is marked (experimental). Do not come crying to me if it's quirky. ๐ญ
--landlock.enforceโ enforces the Landlock ruleset. Without it, the other Landlock commands have no effect โ they're literally just vibes. See the LANDLOCK section for more info.--landlock.fs.read=pathโ creates a Landlock ruleset (if it doesn't already exist) and adds a read access rule for path.--landlock.fs.write=pathโ creates a Landlock ruleset (if it doesn't already exist) and adds a write access rule for path.--landlock.fs.makeipc=pathโ creates a Landlock ruleset (if it doesn't already exist) and adds a rule that allows the creation of named pipes (FIFOs) and Unix domain sockets beneath the given path. Very "I made this little corner for myself" energy. ๐ช--landlock.fs.makedev=pathโ creates a Landlock ruleset (if it doesn't already exist) and adds a rule that allows the creation of block devices and character devices beneath the given path.--landlock.fs.execute=pathโ creates a Landlock ruleset (if it doesn't already exist) and adds an execution permission rule for path.
Example:
$ firejail --landlock.fs.read=/ --landlock.fs.write=/home --landlock.fs.execute=/usr --landlock.enforce
--listโ lists all the sandboxes. See the MONITORING section for more details. It's the group photo. ๐ธ
Example:
$ firejail --list
7015:netblue:browser:firejail /usr/bin/firefox
7056:netblue:torrent:firejail --net=eth0 /usr/bin/transmission-gtk
7064:netblue::firejail --noroot /usr/bin/xterm
--ls=name|pid dir_or_filenameโ lists the files inside a sandbox container. See the FILE TRANSFER section for more details. Peeking in the windows, respectfully. ๐--mac=addressโ assigns a MAC address to the last network interface defined by a--netoption. Just so you know: this option is not supported for wireless interfaces. Fed. โ
Example:
$ firejail --net=eth0 --mac=00:11:22:33:44:55 /usr/bin/firefox
--machine-idโ spoofs the id number in the/etc/machine-idfile โ a fresh random id gets generated inside the sandbox. ๐ญ But bestie, note that this breaks audio support, so enable it when sound is not required.
Example:
$ firejail --machine-id
--memory-deny-write-executeโ installs a seccomp filter to block attempts to create memory mappings that are both writable and executable, to change mappings to be executable, or to create executable shared memory. The filter examines the arguments ofmmap,mmap2,mprotect,pkey_mprotect,memfd_createandshmatsystem calls, and returns errorEPERMto the process if necessary (or kills it, or logs the attempt โ see--seccomp-error-actionbelow). ๐ก๏ธ
Note: shmat is not implemented as a system call on some platforms including i386, and it cannot be handled by seccomp-bpf. So on those, this bit simply can't happen. ๐
--mkdir=dirnameโ creates a directory in user home. Parent directories are created as needed. Very build-your-own-adventure. ๐
Example:
$ firejail --mkdir=~/work/project
--mkfile=filenameโ creates an empty file in user home. Blank canvas, main character energy. ๐
Example:
$ firejail --mkfile=~/work/project/readme
--mtu=numberโ assigns an MTU value to the last network interface defined by a--netoption. Tuning, but make it fashion. โจ
Example:
$ firejail --net=eth0 --mtu=1492
--name=nameโ sets the sandbox name. Several options, such as--joinand--shutdown, can use this name to identify a sandbox. ๐ท๏ธ Important rules, though:- The name cannot contain only digits, because that's treated as a PID in the other options โ like in
--join. - For valid names, see the NAME VALIDATION section.
- If the name you supplied is already in use by another sandbox, Firejail will assign a new name as
name-PID, where PID is the process ID of the sandbox. This functionality can be disabled at run time in/etc/firejail/firejail.config, by setting the"name-change"flag to"no".
- The name cannot contain only digits, because that's treated as a PID in the other options โ like in
Example:
$ firejail --name=browser /usr/bin/firefox &
$ firejail --name=browser --private /usr/bin/firefox --no-remote &
$ firejail --list
1198:netblue:browser:firejail --name=browser /usr/bin/firefox
1312:netblue:browser-1312:firejail --name=browser --private /usr/bin/firefox --no-remote
--net=bridge_interfaceโ spins up a new network namespace and connects it to this bridge interface. Unless you specify it with--ipand--defaultgw, an IP address and a default gateway get assigned automatically to the sandbox. The IP address is verified using ARP before assignment, and the address configured as default gateway is the bridge device IP address. You can stack up to four--netoptions. Four! ๐
Example:
$ sudo brctl addbr br0
$ sudo ifconfig br0 10.10.20.1/24
$ sudo brctl addbr br1
$ sudo ifconfig br1 10.10.30.1/24
$ firejail --net=br0 --net=br1
--net=ethernet_interface|wireless_interfaceโ same idea, new network namespace, but this time connected to an ethernet or wireless interface using the standard Linuxmacvlan|ipvlandriver. Unless specified with--ipand--defaultgw, an IP address and a default gateway are assigned automatically to the sandbox. The IP address is verified using ARP before assignment. The address configured as default gateway is the default gateway of the host. Up to four--netoptions can be specified. ๐ And a lore drop: support for the ipvlan driver was introduced in Linux kernel 3.19.
Example:
$ firejail --net=eth0 --ip=192.168.1.80 --dns=8.8.8.8 /usr/bin/firefox
$ firejail --net=wlan0 /usr/bin/firefox
--net=noneโ okay so this one gives you a whole new network namespace with nothing in it. The only interface chilling in there is a fresh loopback (lo). Perfect for denying network access to programs that genuinely don't need it โ like, why does your calculator want wifi bestie ๐
Example:
$ firejail --net=none /usr/bin/vlc
Heads up ๐--net=nonecan crash the application on some platforms. If that happens to you, swap it for--protocol=unixโ same energy, less chaos.
--net=tap_interfaceโ new network namespace, and we're hooking it up to this ethernet tap interface using the standard Linux macvlan driver. Slay ๐ But listen: if the tap interface isn't configured, the sandbox will not try to configure the interface inside the sandbox. That's your job, bestie โ use--ip,--netmaskand--defaultgwto specify the configuration.
Example:
$ firejail --net=tap0 --ip=10.10.20.80 --netmask=255.255.255.0
--defaultgw=10.10.20.1 /usr/bin/firefox
--net.print=name|pidโ when a new network namespace is enabled, this prints the network interface configuration for the sandbox you name (by name or PID). It's giving receipts โจ Example:
$ firejail --net.print=browser
Switching to pid 1853, the first child process inside the sandbox
Interface MAC IP Mask Status
lo 127.0.0.1 255.0.0.0 UP
eth0-1852 5e:fb:8e:27:29:26 192.168.1.186 255.255.255.0 UP
--netfilterโ turns on a default firewall if a new network namespace is created inside the sandbox. Lowkey important: this option has no effect for sandboxes using the system network namespace. Periodt.
The default firewall is optimized for regular desktop applications โ no incoming connections are accepted:
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# allow ping
-A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
-A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
-A INPUT -p icmp --icmp-type echo-request -j ACCEPT
# drop STUN (WebRTC) requests
-A OUTPUT -p udp --dport 3478 -j DROP
-A OUTPUT -p udp --dport 3479 -j DROP
-A OUTPUT -p tcp --dport 3478 -j DROP
-A OUTPUT -p tcp --dport 3479 -j DROP
COMMIT
Example:
$ firejail --net=eth0 --netfilter /usr/bin/firefox
--netfilter=filenameโ enable the firewall specified by filename, again only if a new network namespace is created inside the sandbox. (Say it with me: no effect for sandboxes using the system network namespace ๐ซถ)
Use the regular iptables-save/iptables-restore format for the filter file. These examples live in /etc/firejail:
webserver.net is a webserver firewall that allows access only to TCP ports 80 and 443. Example:
$ firejail --netfilter=/etc/firejail/webserver.net --net=eth0 \
/etc/init.d/apache2 start
nolocal.net/nolocal6.net is a desktop client firewall that disables access to the local network. Example:
$ firejail --netfilter=/etc/firejail/nolocal.net \
--net=eth0 /usr/bin/firefox
--netfilter=filename,arg1,arg2,arg3 ...โ the template version of the previous one, icon behavior honestly ๐$ARG1,$ARG2,$ARG3โฆ in the firewall script get replaced witharg1,arg2,arg3โฆ passed on the command line. Up to 16 arguments are supported. Example:
$ firejail --net=eth0 --ip=192.168.1.105 \
--netfilter=/etc/firejail/tcpserver.net,5001 server-program
--netfilter.print=name|pidโ prints the firewall installed in the sandbox specified by name or PID. Look at it go โจ Example:
$ firejail --name=browser --net=eth0 --netfilter /usr/bin/firefox &
$ firejail --netfilter.print=browser
--netfilter6=filenameโ the IPv6 sibling ๐ enables the IPv6 firewall specified by filename if a new network namespace is created inside the sandbox. (Yep โ no effect for sandboxes using the system network namespace.) Use the regulariptables-save/iptables-restoreformat for the filter file.--netfilter6.print=name|pidโ prints the IPv6 firewall installed in the sandbox specified by name or PID. Example:
$ firejail --name=browser --net=eth0 --netfilter /usr/bin/firefox &
$ firejail --netfilter6.print=browser
--netlockโ okay so picture this: several types of programs (email clients, multiplayer games, etc.) only talk to a very small number of IP addresses. But the best example is tor browser โ it only talks to a guard node, plus two or three more on standby in case the main one fails. During startup, the browser contacts all of them, and after that it keeps talking to the main oneโฆ for weeks ๐ญ
Use the network locking feature to build and deploy a custom network firewall in your sandbox. The firewall allows only the traffic to the IP addresses detected during the program startup. Traffic to any other address is quietly dropped. By default the network monitoring time is one minute.
A network namespace (--net=eth0) is required for this feature to work. No namespace, no vibes ๐
Example:
$ firejail --net=eth0 --netlock \
--private=~/tor-browser_en-US ./start-tor-browser.desktop
--netmask=addressโ use this when you want to assign an IP address in a new namespace and the parent interface specified by--netis not configured. You also gotta add an IP address and a default gateway address. By default the new namespace interface comes without IP address and default gateway configured. Example:
$ sudo /sbin/brctl addbr br0
$ sudo /sbin/ifconfig br0 up
$ firejail --ip=10.10.20.67 --netmask=255.255.255.0
--defaultgw=10.10.20.1
--netns=nameโ run the program in a named, persistent network namespace. These can be created and configured using"ip netns". Persistent bestie stays around ๐ฆ--netstatsโ monitors network namespace statistics, see the MONITORING section for more details.
Example:
$ firejail --netstats
PID User RX(KB/s) TX(KB/s) Command
1294 netblue 53.355 1.473 firejail --net=eth0
/usr/bin/firefox
7383 netblue 9.045 0.112 firejail --net=eth0
/usr/bin/transmission
--nettrace[=name|pid]โ monitors received TCP, UDP, and ICMP traffic ๐ฅ The sandbox can be specified by name or pid. Only networked sandboxes created with--netare supported. And ngl this one's only available when running the sandbox as root.
Without a name/pid, Firejail will monitor the main system network namespace.
Example:
$ sudo firejail --nettrace
93 KB/s address:port (protocol) network
14 B/s ** 104.24.8.4:443(QUIC) Cloudflare
80 KB/s ***************** 192.187.97.90:443(TLS) BitChute
1 B/s 149.56.228.45:443(DoH) Canada
(D)isplay, (S)ave, (C)lear, e(X)it
If /usr/bin/geoiplookup is installed (the geoip-bin package in Debian), the country the traffic originates from gets added to the trace. We also use the static IP map in /usr/lib/firejail/static-ip-map to print the domain names for some of the more common websites and cloud platforms. And no cap โ no external services are contacted for reverse IP lookup ๐
--nice=valueโ sets the nice value for all processes running inside the sandbox. Only root may specify a negative value ๐
Example:
$ firejail --nice=2 /usr/bin/firefox
--no3dโ disables 3D hardware acceleration. Your GPU is on a break bestie ๐
Example:
$ firejail --no3d /usr/bin/firefox
--noautopulse(deprecated) โ see--keep-config-pulse. That's it, that's the whole option.--noblacklist=dirname_or_filenameโ disables blacklist for this directory or file. Un-blacklisting, the rebel era ๐ธ
Note that blacklist entries containing${PATH}can not currently be partially disabled for individual expanded paths. Only the whole unexpanded path including${PATH}can be disabled, which then applies to all expansions. This limitation does not apply to expansions of other variables or wildcards. For details, see#6360.
Example:
$ firejail
$ nc dict.org 2628
bash: /bin/nc: Permission denied
$ exit
$ firejail --noblacklist=/bin/nc
bash: /bin/nc: Permission denied
$ exit
$ firejail --noblacklist='${PATH}/nc'
$ nc dict.org 2628
220 pan.alephnull.com dictd 1.12.1/rf on Linux 3.14-1-amd64
--nodbus(deprecated) โ disables D-Bus access (both system and session buses). Equivalent to--dbus-system=none --dbus-user=none. Old but iconic ๐
Example:
$ firejail --nodbus --net=none
--nodvdโ disables DVD and audio CD devices. No disc, no drama.
Example:
$ firejail --nodvd
--noexec=dirname_or_filenameโ remounts the directory or filenoexec,nodevandnosuid. File globbing is supported, see the FILE GLOBBING section for more details.
Example:
$ firejail --noexec=/tmp
/etc and /var are noexec by default if the sandbox was started as a regular user โจ
--nogroupsโ disables supplementary groups. Without this option, supplementary groups are enabled for the user starting the sandbox. For root user, supplementary groups are always disabled.
Note: by default all regular user groups are removed with the exception of the current user. This can be changed using the --allusers command option.
Example:
$ id
uid=1000(netblue) gid=1000(netblue)
groups=1000(netblue),24(cdrom),25(floppy),27(sudo),29(audio)
$ firejail --nogroups
Parent pid 8704, child pid 8705
Child process initialized
$ id
uid=1000(netblue) gid=1000(netblue) groups=1000(netblue)
$
--noinputโ disables input devices. Keyboard and mouse are officially uninvited ๐ซ
Example:
$ firejail --noinput
--nonewprivsโ sets theNO_NEW_PRIVSprctl ๐ก๏ธ. What that means in bestie terms: child processes literally cannot gain new privileges throughexecve(2). So if something tries to call a suid binary (or one of those sneaky files with file capabilities), the privilege level does not go up. Blocked. Periodt. This one is on by default whenever the seccomp filter is activated, so you're already slaying ๐ .--noprintersโ printers? gone. disabled. we don't know her ๐จ๏ธ๐.--noprofileโ do not use a security profile. just raw vibes, no profile.
Example:
$ firejail
Reading profile /etc/firejail/default.profile
Parent pid 8553, child pid 8554
Child process initialized
[...]
$ firejail --noprofile
Parent pid 8553, child pid 8554
Child process initialized
[...]
--norootโ installs a user namespace with a single user: the current user. the root user straight up does not exist in the new namespace ๐ค. Requires Linux kernel version 3.8 or newer. Heads up though โ this option is not supported for--chrootand--appimageconfigurations, or for sandboxes started as root ๐ซ.
Example:
$ firejail --noroot
Parent pid 8553, child pid 8554
Child process initialized
$ ping google.com
ping: icmp open socket: Operation not permitted
$
--nosoundโ disable the sound system ๐. silence, but make it cute.
Example:
$ firejail --nosound /usr/bin/firefox
--notpmโ (deprecated) ignored, kept around for compatibility only. TPM devices are now blocked by default anyway, see--keep-dev-tpm๐.--notvโ disable DVB (Digital Video Broadcasting) TV devices ๐บโจ.
Example:
$ firejail --notv /usr/bin/vlc
--nou2fโ disable U2F devices ๐.
Example:
$ firejail --nou2f
--novideoโ disable video devices ๐น๐.--nowhitelist=dirname_or_filenameโ disable the whitelist for this specific directory or file. one tiny exception, no cap.--oom=valueโ configures the kernel's OutOfMemory-killer score for this sandbox ๐. acceptable score values are between0and1000for regular users, and-1000to1000for root. want the full lore on the OOM kernel feature? seeman choom.
Example:
$ firejail --oom=300 /usr/bin/firefox
--output=logfileโ stdout logging and log rotation ๐ฅ. copies stdout to logfile, and keeps the size of the file under500KBusing log rotation. five files with prefixes.1to.5are used in rotation.
Example:
$ firejail --output=sandboxlog /bin/bash
[...]
$ ls -l sandboxlog*
-rw-r--r-- 1 netblue netblue 333890 Jun 2 07:48 sandboxlog
-rw-r--r-- 1 netblue netblue 511488 Jun 2 07:48 sandboxlog.1
-rw-r--r-- 1 netblue netblue 511488 Jun 2 07:48 sandboxlog.2
-rw-r--r-- 1 netblue netblue 511488 Jun 2 07:48 sandboxlog.3
-rw-r--r-- 1 netblue netblue 511488 Jun 2 07:48 sandboxlog.4
-rw-r--r-- 1 netblue netblue 511488 Jun 2 07:48 sandboxlog.5
--output-stderr=logfileโ same energy as--output, except stderr is also stored ๐ซถ.--privateโ mounts a brand new/rootand/home/userdirectory inside temporary filesystems ๐ง. every single modification is discarded when the sandbox closes. literally a clean slate every time, iconic.
Example:
$ firejail --private /usr/bin/firefox
--private=directoryโ use directory as the user home ๐ . note that--privateand--private=directorycannot be used together โ pick one, bestie.
Example:
$ firejail --private=/home/netblue/firefox-home /usr/bin/firefox
๐ Bug: even with this enabled, some firejail commands (such asmkdir,mkfileandprivate-cache) will still operate on the original home directory. Workaround: disable the incompatible commands, such as by using"ignore mkdir"and"ignore mkfile". for details, see#903.
--private-bin=file,fileโ builds a whole new/binin a temporary filesystem and copies the programs in the list into it ๐ธ. the files in the list must be expressed as relative to the/bin,/sbin,/usr/bin,/usr/sbin, or/usr/local/bindirectories. if no listed files are found, the/bindirectory will be empty ๐ญ. the same directory is also bind-mounted over/sbin,/usr/bin,/usr/sbinand/usr/local/bin. all modifications are discarded when the sandbox is closed. multipleprivate-bincommands are allowed and they accumulate. file globbing is supported, see FILE GLOBBING section for more details.
Example:
$ firejail --private-bin=bash,cat,ls,sed
Parent pid 20841, child pid 20842
Child process initialized
$ ls /bin
bash cat ls sed
--private-cacheโ mounts an empty temporary filesystem on top of the.cachedirectory in user home ๐. all modifications are discarded when the sandbox is closed.
Example:
$ firejail --private-cache /usr/bin/openbox
--private-cwdโ sets the working directory inside the jail to the home directory, and failing that, the root directory ๐. does not impact the working directory of profile include paths.
Example:
$ pwd
/tmp
$ firejail --private-cwd
$ pwd
/home/user
--private-cwd=directoryโ set the working directory inside the jail to directory ๐๏ธ. a full directory path is required. symbolic links are not allowed ๐ซ. does not impact the working directory of profile include paths.
Example:
$ pwd
/tmp
$ firejail --private-cwd=/opt
$ pwd
/opt
--private-devโ creates a new/devdirectory โจ. only these devices are available:disc,dri,dvb,full,hidraw,log,null,ptmx,pts,random,shm,snd,tty,urandom,usb,videoandzero. want even more restrictions? use the options--no3d,--nodvd,--nosound,--notv,--nou2fand--novideo๐ .
Example:
$ firejail --private-dev
Parent pid 9887, child pid 9888
Child process initialized
$ ls /dev
cdrom cdrw dri dvd dvdrw full log null ptmx pts random
shm snd sr0 tty urandom zero
$
--private-etc,--private-etc=@group,file,directoryโ the files installed by--private-etcare copies of the original system files from the/etcdirectory ๐ง. by default, the command brings in a skeleton of files and directories used by most console tools:
$ firejail --private-etc /usr/bin/dig debian.org
for X11/GTK/QT/Gnome/KDE programs, add the @x11 group as a parameter. Example:
$ firejail --private-etc=@x11,gcrypt,python* /usr/bin/gimp
so gcrypt and the /etc/python* directories are not part of the generic @x11 group. file globbing is supported โจ.
for games, add the @games group:
$ firejail --private-etc=@games,@x11 /usr/bin/warzone2100
sound and networking files are included automatically, unless --nosound or --net=none are specified. files for encrypted TLS/SSL protocol live in the @tls-ca group ๐.
$ firejail --private-etc=@tls-ca,wgetrc /usr/bin/wget
https://debian.org
๐ก Note: the easiest way to extract the list of/etcfiles accessed by your program is by using thestraceutility.
Example:
$ strace -f --trace=%file /usr/bin/transmission-qt 2>&1 | grep
etc
$ firejail --allow-debuggers
--profile=/etc/firejail/transmission-qt.profile strace -f
--trace=%file /usr/bin/transmission-qt 2>&1 | grep etc
see also --allow-debuggers and --trace ๐.
--private-opt=file,directoryโ builds a new/optin a temporary filesystem and copies the files and directories in the list ๐๏ธ. the files and directories in the list must be expressed as relative to the/optdirectory, and must not contain the/character (e.g.,/opt/foomust be expressed asfoo, but/opt/foo/barโ expressed asfoo/barโ is disallowed ๐ซ). if no listed file is found, the/optdirectory will be empty. all modifications are discarded when the sandbox is closed.
Example:
$ firejail --private-opt=firefox /opt/firefox/firefox
โ ๏ธ Note: program installations in/opttend to be relatively large, andprivate-optcopies the entire path(s) into RAM, which may significantly increase RAM usage and breakfile-copy-limitinfirejail.config๐. therefore, in general it's recommended to use"whitelist /opt/PATH"instead of"private-opt PATH". for details, see#5307.
--private-srv=file,directoryโ builds a new/srvin a temporary filesystem and copies the files and directories in the list ๐. the files and directories in the list must be expressed as relative to the/srvdirectory, and must not contain the/character (e.g.,/srv/foomust be expressed asfoo, but/srv/foo/barโ expressed assrv/barโ is disallowed). if no listed file is found, the/srvdirectory will be empty. all modifications are discarded when the sandbox is closed.
Example:
# firejail --private-srv=www /etc/init.d/apache2 start
--private-tmpโ mounts an empty temporary filesystem on top of the/tmpdirectory, whitelisting X11 and PulseAudio sockets ๐งโจ.
Example:
$ firejail --private-tmp
$ ls -al /tmp
drwxrwxrwt 4 nobody nogroup 80 Apr 30 11:46 .
drwxr-xr-x 30 nobody nogroup 4096 Apr 26 22:18 ..
drwx------ 2 nobody nogroup 4096 Apr 30 10:52 pulse-PKdhtXMmr18n
drwxrwxrwt 2 nobody nogroup 4096 Apr 30 10:52 .X11-unix
--profile=filename|appnameโ loads a custom security profile from filename, or uses the name of a specific application ๐๐.
if the command line option --profile is not provided, Firejail will attempt to extract the appname from the target program filename. it will then search the ~/.config/firejail directory for a suitable profile, followed by a search in /etc/firejail/directory.
Example:
$ firejail /usr/bin/firefox
Reading profile /home/netblue/.config/firejail/firefox.profile
Reading profile /etc/firejail/firefox.profile
Reading profile /etc/firejail/firefox-common.profile
[...]
when using a filename, please include a full path or a relative path ๐ซถ.
$ firejail --profile=./firefox.profile /usr/bin/firefox
Reading profile ./firefox.profile
Reading profile /etc/firejail/firefox.profile
Reading profile /etc/firejail/firefox-common.profile
[...]
And lowkey the --profile=appname form is that girl when you're messing with appimages:
$ firejail --appimage --profile=firefox firefox-nightly-148.0.r20260103-x86_64.AppImage
Reading profile /home/netblue/.config/firejail/firefox.profile
Reading profile /etc/firejail/firefox.profile
Reading profile /etc/firejail/firefox-common.profile
[...]
See man 5 firejail-profile for the whole profile file syntax tea โ, and for the profile resolution lore (like, how does it pick which file, bestie) see https://github.com/netblue30/firejail/wiki/Creating-Profiles.
--profile.print=name|pidโ prints the name of the profile file for the sandbox you point at with name or PID. Like a little name tag for your sandbox ๐ท๏ธ
Example:
$ firejail --profile.print=browser
/etc/firejail/firefox.profile
--protocol=protocol,protocol,protocolโ turns on the protocol filter, periodt. This filter is seccomp-based and it checks the first argument passed to thesocketsystem call. The recognized values are:unix,inet,inet6,netlink,packet, andbluetooth. Heads up: this option is not supported on i386 architecture ๐. You can stack multiple--protocolcommands and they accumulate.
Example:
$ firejail --protocol=unix,inet,inet6 /usr/bin/firefox
--protocol.print=name|pidโ prints the protocol filter for the sandbox identified by name or PID.
Example:
$ firejail --name=mybrowser /usr/bin/firefox &
$ firejail --protocol.print=mybrowser
unix,inet,inet6,netlink
Example:
$ firejail --list
3272:netblue::firejail --private /usr/bin/firefox
$ firejail --protocol.print=3272
unix,inet,inet6,netlink
--put=name|pid src-filename dest-filenameโ drops a file into the sandbox container ๐. More deets live in the FILE TRANSFER section, iykyk.--quietโ silences Firejail's output. Shhh ๐คซ
You can get the exact same energy by setting the environment variable FIREJAIL_QUIET to yes.
--read-only=dirname_or_filenameโ locks a directory or file to read-only ๐. File globbing is supported โ check the FILE GLOBBING section for the details.
Example:
$ firejail --read-only=~/.mozilla /usr/bin/firefox
--read-write=dirname_or_filenameโ makes a directory or file read-write again โ๏ธ. Only files or directories that belong to the current user are allowed for this one, no cap. File globbing is supported, see FILE GLOBBING.
Example:
$ mkdir ~/test
$ touch ~/test/a
$ firejail --read-only=~/test --read-write=~/test/a
--restrict-namespacesโ installs a seccomp filter that blocks any attempt to create newcgroup,ipc,net,mount,pid,time,userorutsnamespaces. No new namespace era for you ๐ซ
Example:
$ firejail --restrict-namespaces
--restrict-namespaces=cgroup,ipc,net,mnt,pid,time,user,utsโ same vibe but picky: installs a seccomp filter that blocks attempts to create any of the namespaces you actually listed. The filter peeks at the arguments of theclone,unshareandsetnssystem calls, and returns errorEPERMto the process (or kills it, or logs the attempt โ see--seccomp-error-actionbelow) when it needs to. Important caveat bestie: the filter can't examine the arguments ofclone3system calls, and it always responds to those with errorENOSYS.
Example:
$ firejail --restrict-namespaces=user,net
--rlimit-as=numberโ sets the maximum size of the process's virtual memory (address space) in bytes. You can useK(ibibyte),M(ebibyte) orG(ibibyte) as a suffix, like"100M"(which is literally equivalent to 104857600 bytes).--rlimit-cpu=numberโ caps, in seconds, how much CPU time each sandboxed process is allowed to eat. Hit the limit and the processes get killed ๐.
Fr fr though: the CPU limit is a limit on CPU seconds, not elapsed/wall-clock time. CPU seconds is basically how many seconds the CPU has actually been in use, so it doesn't necessarily line up with the elapsed time you feel. The Linux kernel keeps track of CPU seconds for each process independently.
--rlimit-fsize=numberโ sets the maximum file size that a process can create. Same suffix deal:K(ibibyte),M(ebibyte) orG(ibibyte), like"100M"(which is equivalent to 104857600 bytes).--rlimit-nofile=numberโ sets the max number of files a process can have open at once ๐.--rlimit-nproc=numberโ sets the max number of processes that can be created for the real user ID of the calling process.--rlimit-sigpending=numberโ sets the max number of pending signals a process can have queued up ๐ถ.--rmenv=nameโ removes an environment variable inside the new sandbox ๐งน.
Example:
$ firejail --rmenv=DBUS_SESSION_BUS_ADDRESS
--scanโ ARP-scan all the networks from inside a network namespace. This makes it possible to detect macvlan kernel device drivers running on the current host ๐ต๏ธโโ๏ธ.
Example:
$ firejail --net=eth0 --scan
--seccompโ enables the seccomp filter and blacklists the syscalls in the default list, which is@default-nodebuggersunless--allow-debuggersis specified โ in which case it's@default. Iconic security behavior, honestly ๐
So you can build useful seccomp filters without losing your mind, these system call groups are defined: @aio, @basic-io, @chown, @clock, @cpu-emulation, @debug, @default, @default-nodebuggers, @default-keep, @file-system, @io-event, @ipc, @keyring, @memfd, @memlock, @module, @mount, @network-io, @obsolete, @privileged, @process, @program-keep, @raw-io, @reboot, @resources, @sandbox, @setuid, @swap, @sync, @system-service and @timer. More info about the groups lives in /usr/share/doc/firejail/syscalls.txt, and also go look at --debug-syscall-groups.
The default list can be customized โ see --seccomp= for the description โจ. It can also be customized globally in the /etc/firejail/firejail.config file.
System architecture is strictly imposed only if the flag --seccomp.block-secondary is used. The filter gets applied at run time only if the correct architecture was detected. For the I386 and AMD64 case, both 32-bit and 64-bit filters are installed.
Firejail will print seccomp violations to the audit log if the kernel was compiled with audit support (the CONFIG_AUDIT flag).
Example:
$ firejail --seccomp
--seccomp=syscall,@group,!syscall2โ enables the seccomp filter, blacklists the default list and the syscalls or syscall groups you name in the command, but does not blacklistsyscall2(that!is a hard no ๐ โโ๏ธ). On a 64 bit architecture, you can install an additional filter for 32 bit system calls with--seccomp.32.
Example:
$ firejail --seccomp=utime,utimensat,utimes /usr/bin/firefox
$ firejail --seccomp=@clock,mkdir,unlinkat /usr/bin/transmission-gtk
$ firejail '--seccomp=@ipc,!pipe,!pipe2' audacious
You can also name syscalls by their number โ just slap a $ prefix on it, so for example "$165" corresponds to "mount" on the x86_64 architecture. You can find the syscall numbers and names for --seccomp by using --debug-syscalls and --debug-syscalls32 for --seccomp.32.
Instead of dropping the syscall by returning EPERM, you can return a different error number using the syscall:errno syntax ๐ฏ. This can also be changed globally with --seccomp-error-action or in the /etc/firejail/firejail.config file. You can also straight-up kill the process using the syscall:kill syntax, or log the attempt without blocking the syscall using syscall:log.
Example:
$ firejail --seccomp=unlinkat:ENOENT,utimensat,utimes
Parent pid 10662, child pid 10663
Child process initialized
$ touch testfile
$ ls testfile
testfile
$ rm testfile
rm: cannot remove `testfile': No such file or directory
If the blocked system calls would also block Firejail from operating (oops), they're handled by adding a preloaded library that performs the seccomp system calls later. But โ warning bestie โ this is incompatible with 32 bit seccomp filters โ ๏ธ.
Example:
$ firejail --noprofile --seccomp=execve sh
Parent pid 32751, child pid 32752
Post-exec seccomp protector enabled
list in: execve, check list: @default-keep prelist: (null), postlist: execve
Child process initialized in 46.44 ms
$ ls
Operation not permitted
--seccomp.block-secondaryโ enables the seccomp filter and filters system call architectures so that only the native architecture is allowed ๐. For example, on amd64,i386andx32system calls are blocked, and so is changing the execution domain with thepersonality(2)system call.--seccomp.drop=syscall,@groupโ enables the seccomp filter and blacklists the syscalls or the syscall groups you name in the command. On a 64 bit architecture, you can install an additional filter for 32 bit system calls with--seccomp.32.drop.
Example:
$ firejail --seccomp.drop=utime,utimensat,utimes,@clock
Instead of dropping the syscall by returning EPERM, you can return another error number using the syscall:errno syntax ๐
. This can also be changed globally with --seccomp-error-action or in the /etc/firejail/firejail.config file. You can kill the process too with the syscall:kill syntax, or log the attempt without blocking the syscall with syscall:log.
Example:
$ firejail --seccomp.drop=unlinkat:ENOENT,utimensat,utimes
Parent pid 10662, child pid 10663
Child process initialized
$ touch testfile
$ ls testfile
testfile
$ rm testfile
rm: cannot remove `testfile': No such file or directory
--seccomp.keep=syscall,@group,!syscall2โ okay bestie, this one switches the seccomp filter ON โจ โ it blacklists every syscall you didn't list, plussyscall2. The syscalls Firejail itself needs (group@default-keep:prctl,execve,execveat) get handled by the preload library ๐ซถ. On a 64-bit architecture you can stack an extra filter for 32-bit system calls using--seccomp.32.keep.
Example, because vibes need receipts:
$ firejail --seccomp.keep=poll,select,[...]
/usr/bin/transmission-gtk
--seccomp.print=name|pidโ prints out the seccomp filter for the sandbox you name (or point at with a PID). It's giving raw BPF realness ๐
$ firejail --name=browser /usr/bin/firefox &
$ firejail --seccomp.print=browser
line OP JT JF K
=================================
0000: 20 00 00 00000004 ld data.architecture
0001: 15 01 00 c000003e jeq ARCH_64 0003 (false 0002)
0002: 06 00 00 7fff0000 ret ALLOW
0003: 20 00 00 00000000 ld data.syscall-number
0004: 35 01 00 40000000 jge X32_ABI true:0006 (false 0005)
0005: 35 01 00 00000000 jge read 0007 (false 0006)
0006: 06 00 00 00050001 ret ERRNO(1)
0007: 15 41 00 0000009a jeq modify_ldt 0049 (false 0008)
0008: 15 40 00 000000d4 jeq lookup_dcookie 0049 (false 0009)
0009: 15 3f 00 0000012a jeq perf_event_open 0049 (false 000a)
000a: 15 3e 00 00000137 jeq process_vm_writev 0049 (false 000b)
000b: 15 3d 00 0000009c jeq _sysctl 0049 (false 000c)
000c: 15 3c 00 000000b7 jeq afs_syscall 0049 (false 000d)
000d: 15 3b 00 000000ae jeq create_module 0049 (false 000e)
000e: 15 3a 00 000000b1 jeq get_kernel_syms 0049 (false 000f)
000f: 15 39 00 000000b5 jeq getpmsg 0049 (false 0010)
0010: 15 38 00 000000b6 jeq putpmsg 0049 (false 0011)
0011: 15 37 00 000000b2 jeq query_module 0049 (false 0012)
0012: 15 36 00 000000b9 jeq security 0049 (false 0013)
0013: 15 35 00 0000008b jeq sysfs 0049 (false 0014)
0014: 15 34 00 000000b8 jeq tuxcall 0049 (false 0015)
0015: 15 33 00 00000086 jeq uselib 0049 (false 0016)
0016: 15 32 00 00000088 jeq ustat 0049 (false 0017)
0017: 15 31 00 000000ec jeq vserver 0049 (false 0018)
0018: 15 30 00 0000009f jeq adjtimex 0049 (false 0019)
0019: 15 2f 00 00000131 jeq clock_adjtime 0049 (false 001a)
001a: 15 2e 00 000000e3 jeq clock_settime 0049 (false 001b)
001b: 15 2d 00 000000a4 jeq settimeofday 0049 (false 001c)
001c: 15 2c 00 000000b0 jeq delete_module 0049 (false 001d)
001d: 15 2b 00 00000139 jeq finit_module 0049 (false 001e)
001e: 15 2a 00 000000af jeq init_module 0049 (false 001f)
001f: 15 29 00 000000ad jeq ioperm 0049 (false 0020)
0020: 15 28 00 000000ac jeq iopl 0049 (false 0021)
0021: 15 27 00 000000f6 jeq kexec_load 0049 (false 0022)
0022: 15 26 00 00000140 jeq kexec_file_load 0049 (false 0023)
0023: 15 25 00 000000a9 jeq reboot 0049 (false 0024)
0024: 15 24 00 000000a7 jeq swapon 0049 (false 0025)
0025: 15 23 00 000000a8 jeq swapoff 0049 (false 0026)
0026: 15 22 00 000000a3 jeq acct 0049 (false 0027)
0027: 15 21 00 00000141 jeq bpf 0049 (false 0028)
0028: 15 20 00 000000a1 jeq chroot 0049 (false 0029)
0029: 15 1f 00 000000a5 jeq mount 0049 (false 002a)
002a: 15 1e 00 000000b4 jeq nfsservctl 0049 (false 002b)
002b: 15 1d 00 0000009b jeq pivot_root 0049 (false 002c)
002c: 15 1c 00 000000ab jeq setdomainname 0049 (false 002d)
002d: 15 1b 00 000000aa jeq sethostname 0049 (false 002e)
002e: 15 1a 00 000000a6 jeq umount2 0049 (false 002f)
002f: 15 19 00 00000099 jeq vhangup 0049 (false 0030)
0030: 15 18 00 000000ee jeq set_mempolicy 0049 (false 0031)
0031: 15 17 00 00000100 jeq migrate_pages 0049 (false 0032)
0032: 15 16 00 00000117 jeq move_pages 0049 (false 0033)
0033: 15 15 00 000000ed jeq mbind 0049 (false 0034)
0034: 15 14 00 00000130 jeq open_by_handle_at 0049 (false 0035)
0035: 15 13 00 0000012f jeq name_to_handle_at 0049 (false 0036)
0036: 15 12 00 000000fb jeq ioprio_set 0049 (false 0037)
0037: 15 11 00 00000067 jeq syslog 0049 (false 0038)
0038: 15 10 00 0000012c jeq fanotify_init 0049 (false 0039)
0039: 15 0f 00 00000138 jeq kcmp 0049 (false 003a)
003a: 15 0e 00 000000f8 jeq add_key 0049 (false 003b)
003b: 15 0d 00 000000f9 jeq request_key 0049 (false 003c)
003c: 15 0c 00 000000fa jeq keyctl 0049 (false 003d)
003d: 15 0b 00 000000ce jeq io_setup 0049 (false 003e)
003e: 15 0a 00 000000cf jeq io_destroy 0049 (false 003f)
003f: 15 09 00 000000d0 jeq io_getevents 0049 (false 0040)
0040: 15 08 00 000000d1 jeq io_submit 0049 (false 0041)
0041: 15 07 00 000000d2 jeq io_cancel 0049 (false 0042)
0042: 15 06 00 000000d8 jeq remap_file_pages 0049 (false 0043)
0043: 15 05 00 00000116 jeq vmsplice 0049 (false 0044)
0044: 15 04 00 00000087 jeq personality 0049 (false 0045)
0045: 15 03 00 00000143 jeq userfaultfd 0049 (false 0046)
0046: 15 02 00 00000065 jeq ptrace 0049 (false 0047)
0047: 15 01 00 00000136 jeq process_vm_readv 0049 (false 0048)
0048: 06 00 00 7fff0000 ret ALLOW
0049: 06 00 01 00000000 ret KILL
$
--seccomp-error-action= kill | ERRNO | logโ so by default, when a seccomp filter blocks a system call, the process getsEPERMas its error ๐ค. With--seccomp-error-action=erroryou can hand back a different error number instead โ thinkENOSYSorEACCES. You can also just kill the process (the way versions<0.9.63of Firejail did it) with the--seccomp-error-action=killsyntax, or log the attempt using--seccomp-error-action=log.
Real talk: not killing the process weakens Firejail slightly when it's trying to contain an intrusion โ but it can also let you keep tighter filters when the only other option is allowing a system call. Trade-offs, bestie ๐
--shutdown=name|pidโ shuts down the sandbox you point at by name or PID ๐ bye felicia.
$ firejail --name=mygame --caps.drop=all /usr/bin/warzone2100 &
$ firejail --shutdown=mygame
And with a PID:
$ firejail --list
3272:netblue::firejail --private /usr/bin/firefox
$ firejail --shutdown=3272
--snitrace[=name|pid]โ monitors Server Name Indication (TLS/SNI) ๐โจ. You can point it at a sandbox by name or pid. Only networked sandboxes created with--netare supported โ and this option is only available when you're running the sandbox as root.
If you don't give it a name/pid, Firejail just monitors the main system network namespace. Main character energy fr fr ๐
$ sudo firejail --snitrace
07:49:51 23.185.0.3 linux.com
07:49:51 23.185.0.3 www.linux.com
07:50:05 192.0.73.2 secure.gravatar.com
07:52:35 172.67.68.93 www.howtoforge.com
07:52:37 13.225.103.59 sf.ezoiccdn.com
07:52:42 142.250.176.3 www.gstatic.com
07:53:03 173.236.250.32 www.linuxlinks.com
07:53:05 192.0.77.37 c0.wp.com
07:53:08 192.0.78.32 jetpack.wordpress.com
07:53:09 192.0.77.32 s0.wp.com
07:53:09 192.0.77.2 i0.wp.com
07:53:10 192.0.77.2 i0.wp.com
07:53:11 192.0.73.2 1.gravatar.com
--tabโ turns on shell tab completion inside sandboxes that use private or whitelisted home directories ๐ because typing full paths is not the vibe.
$ firejail --private --tab
--timeout=hh:mm:ssโ kills the sandbox automatically once that much time has elapsed โฐ๐. Time goes in hours/minutes/seconds format.
$ firejail --timeout=01:30:00 /usr/bin/firefox
--tmpfs=dirnameโ mounts a writable tmpfs filesystem on the directorydirnameโจ. Directories outside the user's home, or ones not owned by the user, are not allowed โ sandboxes running as root are exempt from those restrictions ๐. File globbing is supported, so peep the FILE GLOBBING section for the deets.
$ firejail --tmpfs=~/.local/share
--topโ monitors the most CPU-intensive sandboxes ๐ฅต๐ฅ, see the MONITORING section for more.
$ firejail --top
--trace[=filename]โ tracesopen,accessandconnectsystem calls ๐ต๏ธโโ๏ธโจ. Give it afilenameand the trace output gets logged there; leave it out and it goes to the console.
$ firejail --trace /usr/bin/wget -q www.debian.org
Reading profile /etc/firejail/wget.profile
3:wget:fopen64 /etc/wgetrc:0x5c8e8ce6c0
3:wget:fopen /etc/hosts:0x5c8e8cfb70
3:wget:socket AF_INET SOCK_DGRAM IPPROTO_IP:3
3:wget:connect 3 8.8.8.8 port 53:0
3:wget:socket AF_INET SOCK_STREAM IPPROTO_IP:3
3:wget:connect 3 130.89.148.14 port 80:0
3:wget:fopen64 index.html:0x5c8e8d1a60
parent is shutting down, bye...
See also --allow-debuggers and --private-etc. iykyk ๐
--treeโ prints a tree of all sandboxed processes ๐ณโจ, see the MONITORING section for the full picture.
$ firejail --tree
11903:netblue:firejail /usr/bin/iceweasel
11904:netblue:iceweasel
11957:netblue:/usr/lib/iceweasel/plugin-container
11969:netblue:firejail --net=eth0 /usr/bin/transmission-gtk
11970:netblue:transmission-gtk
--unhide-pid1โ so pid 1 is always present inside a Firejail sandbox, but by restricting access to the/prockernel interface, general tools likepscan't view or access this process ๐. The--unhide-pid1option disables that functionality. Example:
$ firejail --name=test ### by default pid 1 is not visible
[...]
Child process initialized in 59.41 ms
$ ps a
PID TTY STAT TIME COMMAND
4 ? S 0:00 /bin/bash
5 ? R+ 0:00 ps a
$ exit
Parent is shutting down, byeโฆ
$ firejail --name=test --unhide-pid1 ### pid 1 is visible
[...]
Child process initialized in 58.29 ms
$ ps a
PID TTY STAT TIME COMMAND
1 ? S 0:00 firejail --name=test --unhide-pid1
4 ? S 0:00 /bin/bash
6 ? R+ 0:00 ps a
$ exit
Parent is shutting down, byeโฆ
--versionโ prints the program version and the compile-time support list, then dips out. Straight to the point, no cap.
$ firejail --version
firejail version 0.9.81
Compile time support:
- always force nonewprivs support is disabled
- AppArmor support is enabled
- AppImage support is enabled
- chroot support is disabled
- D-BUS proxy support is enabled
- file transfer support is enabled
- Landlock support is enabled
- networking support is enabled
- output logging is enabled
- SELinux support is disabled
- user namespace support is enabled
- X11 sandboxing support is enabled
- Xorg security extension and xvfb support is enabled
--veth-name=nameโ picks the name for the interface that's plugged into the bridge for--net=bridge_interfacecommands, instead of the default name it'd normally use. Name your little network baby whatever you want ๐
$ firejail --net=br0 --veth-name=if0
--whitelist=dirname_or_filenameโ whitelist a directory or a file, bestie. Firejail mounts a temporary file system on top of the top directory. And in firejail-speak, "top directory" means: if the whitelisted file's path is, like,/etc/somedir/somefile, then the top directory is/etc. Every other top directory โ/opt,/usr, all of them โ hasn't changed, so every file in them is still accessible, unless you also whitelist a file or directory inside them. That's why sometimes it's genuinely beneficial to useblacklisttogether withwhitelist, if you're using them for different top directories. Combo move โจ
The whitelisted files get mount-binded inside. Modifications to whitelisted files are persistent; literally everything else in the same top directory gets discarded when the sandbox closes. Gone. Ghosted. ๐
The top directory can be most directories in /, but there are some special cases. The /proc and /sys top directories aren't allowed, but /sys/module is. Also /run/user/$UID, $HOME and all directories in /usr are treated as a top directory.
Symbolic link handling, listen up: whitelisting a path that's a symbolic link will also whitelist the path it points to. So like, if ~/foo is whitelisted and it points to ~/bar, then ~/bar gets whitelisted too. Restrictions though: with the exception of the user home directory, both the link and the real file should be in the same top directory. And for symbolic links in the user home directory, both the link and the real file should be owned by the user.
File globbing is supported โ go check the FILE GLOBBING section for the deets.
$ firejail --noprofile --whitelist=~/.mozilla
$ firejail --whitelist=/tmp/.X11-unix --whitelist=/dev/null
$ firejail --whitelist="/home/username/My Virtual Machines"
$ firejail --whitelist=/home/username/My\ Virtual\ Machines
$ firejail --whitelist=~/work* --whitelist=/var/backups*
--writable-etcโ mounts the/etcdirectory read-write. Yeah, actually writable. Be normal about it ๐
$ sudo firejail --writable-etc
--writable-run-userโ disables the default blacklisting of/run/user/$UID/systemdand/run/user/$UID/gnupg.
$ sudo firejail --writable-run-user
--writable-varโ mounts the/vardirectory read-write.
$ sudo firejail --writable-var
--writable-var-logโ uses the real/var/logdirectory, not a clone. Because by default a tmpfs is mounted on top of the/var/logdirectory, and a skeleton filesystem is created based on the original/var/log. So this is the "give me the actual logs" button ๐ซถ
$ sudo firejail --writable-var-log
--x11โ sandboxes the app using the Xephyr X11 server. The sandbox stops screenshot and keylogger apps started inside the sandbox from reaching clients running outside it. Main character security behaviour, honestly ๐
The default window size is 800x600. You can change that in the /etc/firejail/firejail.config file.
Note: a network namespace needs to be instantiated in order to deny access to the X11 abstract Unix domain socket. So yeah, that's a whole thing.
Xephyr is developed by the Xorg project. On Debian platforms it's installed with the command sudo apt-get install xserver-xephyr. Heads up though: this feature is not available when running as root.
$ firejail --x11 --net=eth0 /usr/bin/firefox
You can also run a display server inside the sandbox, which is lowkey iconic:
$ firejail --x11 --net=eth0 /usr/bin/openbox
A security profile for openbox is provided. Slay.
--x11=noneโ blacklists the/tmp/.X11-unixdirectory,${HOME}/.Xauthorityand the file specified in the${XAUTHORITY}environment variable. Removes theDISPLAYandXAUTHORITYenvironment variables. And it stops with an error message if the X11 abstract socket would be accessible in the jail. No X11 for you, periodt.--xephyr-extra-params=OPTIONSโ sets extra parameters for the Xephyr server command, for the Xephyr X11 server. This setting overwrites the default set in/etc/firejail/firejail.config, but only for the current sandbox. RunXephyr -helpto get the list of available options ๐ฆ
$ firejail --net=eth0 --x11 --xephyr-extra-params="-title
firefox" /usr/bin/firefox
--xephyr-screen=WIDTHxHEIGHTโ sets the screen size for the Xephyr X11 server. This setting overwrites the default set in/etc/firejail/firejail.configfor the current sandbox. Runxrandrto get a list of supported resolutions on your computer ๐ธ
$ firejail --net=eth0 --x11 --xephyr-screen=640x480
/usr/bin/firefox
๐ก๏ธ APPARMOR
AppArmor support is disabled by default at compile time. Use the --enable-apparmor configuration option to enable it, okay?
$ ./configure --prefix=/usr --enable-apparmor
During software install, a generic AppArmor profile file, firejail-default, is placed in the /etc/apparmor.d directory. Any local customizations have to go in /etc/apparmor.d/local/firejail-local. The profile needs to be loaded into the kernel by reloading apparmor.service, rebooting the system, or running the following command as root:
# apparmor_parser -r /etc/apparmor.d/firejail-default
The installed profile is supplemental for the main firejail functions and, among other things, does the following:
- Disable
ptrace. Withptraceit's possible to inspect and hijack running programs. Usually this is needed only for debugging. You should have no problems running Chromium or Firefox. This feature is available only on Ubuntu kernels. - Whitelist write access to several files under
/run,/procand/sys. - Allow running programs only from well-known system paths, such as
/bin,/sbin,/usr/binetc. Those paths are available as read-only. Running programs and scripts from user home or other directories writable by the user is not allowed. - Prevent using non-standard network sockets. Only
unix,inet,inet6,netlink,rawandpacketare allowed. - Deny access to known sensitive paths like
.snapshots.
To enable AppArmor confinement on top of your current Firejail security features, pass the --apparmor flag to the Firejail command line. You can also include the apparmor command in a Firejail profile file ๐
$ firejail --apparmor /usr/bin/firefox
๐ฅ๏ธ DESKTOP INTEGRATION
Okay so this is the part that's genuinely magic: a symbolic link to /usr/bin/firejail under the name of a program will start that program in a Firejail sandbox. The symlink should be placed in the first $PATH position. On most systems, a good place is the /usr/local/bin directory โจ
Make a firefox symlink to /usr/bin/firejail:
$ sudo ln -s /usr/bin/firejail /usr/local/bin/firefox
Verify $PATH:
$ which -a firefox
/usr/local/bin/firefox
/usr/bin/firefox
Starting firefox in this moment automatically invokes โfirejail /usr/bin/firefoxโ.
This works for clicking on desktop environment icons, menus, etc. Use firejail --tree to verify the program is sandboxed ๐
$ firejail --tree
1189:netblue:firejail /usr/bin/firefox
1190:netblue:firejail /usr/bin/firefox
1220:netblue:/bin/sh -c "/usr/lib/firefox/firefox"
1221:netblue:/usr/lib/firefox/firefox
We provide a tool that automates all this integration โ please see firecfg(1) for more details, bestie ๐ซถ
๐ FILE GLOBBING
Globbing is the operation that expands a wildcard pattern into the list of pathnames matching the pattern. This pattern is matched at firejail start, and is NOT UPDATED at runtime. So like, files that match a blacklist but were created after firejail started will still be accessible within the jail. The matching is defined by:
?matches any character*matches any string[denotes a range of characters
The globbing feature is implemented using the glibc glob command. For more info on the wildcard syntax see man 7 glob.
The following command line options are supported: --blacklist, --private-bin, --noexec, --read-only, --read-write, --tmpfs, and --whitelist.
Examples:
$ firejail --private-bin=sh,bash,python*
$ firejail --blacklist=~/dir[1234]
$ firejail --read-only=~/dir[1-4]
โจ FILE TRANSFER โจ
Okay bestie, this whole section is about peeking inside a sandbox's filesystem container and moving files back and forth between the container and the host. It's giving "window shopping but for your own sandbox" ๐
--cat=name|pid filenameโ writes the content of a container file to standard out. The container gets picked by name or PID. And ooh, cute detail: if standard out is a terminal, all ASCII control characters except new line and horizontal tab get replaced. So no weird escape-code chaos on your screen ๐ซถ--get=name|pid filenameโ grabs the container file and stores it on the host in the current working directory. Container is specified by name or PID.--ls=name|pid dir_or_filenameโ lists container files. Container is specified by name or PID.--put=name|pid src-filename dest-filenameโ puts src-filename into the sandbox container. Container is specified by name or PID.
๐ธ Examples โจ
$ firejail --name=mybrowser --private /usr/bin/firefox
$ firejail --ls=mybrowser ~/Downloads
drwxr-xr-x netblue netblue 4096 .
drwxr-xr-x netblue netblue 4096 ..
-rw-r--r-- netblue netblue 7847 x11-x305.png
-rw-r--r-- netblue netblue 6800 x11-x642.png
$ firejail --get=mybrowser ~/Downloads/x11-x305.png
$ firejail --put=mybrowser x11-x305.png ~/Downloads/x11-x305.png
$ firejail --cat=mybrowser ~/.bashrc
๐ฆ LANDLOCK ๐ฆ
โ ๏ธ Warning, and I mean it: Landlock support in firejail is considered experimental and unstable. The contents oflandlock-common.incare likely to change, and the feature is still being expanded upon in the Linux kernel. Also note that its functionality overlaps with existing firejail features, such as the blacklist, read-only and read-write commands. Its filesystem access rules can currently only restrict direct access to paths; it is not able to make only select paths appear in the sandbox such as with the whitelist and private-etc commands (see alsounveil(2)on OpenBSD). Lastly, note that depending on the Linux kernel version, Landlock may not protect all of the relevant syscalls (see the kernel's Landlock documentation for details). Therefore, it is recommended to treat Landlock as an extra layer of protection, to be used together with other firejail features (rather than as a bulletproof mechanism by itself). No cap, it's a bonus layer, not the whole outfit ๐
So here's the lore: Landlock is a Linux security module first introduced in version 5.13 of the Linux kernel. It allows unprivileged processes to restrict their access to the filesystem. Once imposed, these restrictions can never be removed, and all child processes created by a Landlock-restricted process inherit these restrictions. Firejail supports Landlock as an additional sandboxing feature. It can be used to ensure that a sandboxed application can only access files and directories that it was explicitly allowed to access. Firejail supports populating the ruleset with both a basic set of rules (see landlock-common.inc) and with a custom set of rules. Slay ๐
๐ Important notes ๐
- Currently only Landlock ABI version 1 is supported.
- If
lsm=is used in the kernel command line, it should containlandlock(such aslsm=apparmor,landlock), or else it will be disabled. - A process can install a Landlock ruleset only if it has either
CAP_SYS_ADMINin its effective capability set, or the "No New Privileges" restriction enabled. Because of this, enabling the Landlock feature will also cause Firejail to enable the "No New Privileges" restriction, regardless of the profile or the--nonewprivscommand line option. - Access to the
/etcdirectory is automatically allowed. To override this, use the--writable-etccommand line option. You can also use the--private-etcoption to restrict access to the/etcdirectory.
To enable Landlock self-restriction on top of your current Firejail security features, pass --landlock.enforce flag to the Firejail command line. Without it, the other Landlock commands have no effect โ like, zero, they're just standing there being decorative ๐ Example:
$ firejail --landlock.enforce --landlock.fs.read=/media /usr/bin/mc
To disable Landlock self-restriction, use --ignore=landlock.enforce.
๐ MONITORING ๐
Option --list prints a list of all sandboxes. The format for each process entry is as follows:
PID:USER:Sandbox Name:Command
Option --tree prints the tree of processes running in the sandbox. The format for each process entry is as follows:
PID:USER:Sandbox Name:Command
Option --top is similar to the UNIX top command, however it applies only to sandboxes.
Option --netstats prints network statistics for active sandboxes installing new network namespaces.
Listed below are the available fields (columns) in alphabetical order for --top and --netstats options:
๐ The columns ๐
Command : Command used to start the sandbox.
CPU% : CPU usage, the sandbox share of the elapsed CPU time since the last screen update
PID : Unique process ID for the task controlling the sandbox.
Prcs : Number of processes running in sandbox, including the controlling process.
RES : Resident Memory Size (KiB), sandbox non-swapped physical memory. It is a sum of the RES values for all processes running in the sandbox.
RX(KB/s) : Network receive speed.
Sandbox Name : The name of the sandbox, if any.
SHR : Shared Memory Size (KiB), it reflects memory shared with other processes. It is a sum of the SHR values for all processes running in the sandbox, including the controlling process.
TX(KB/s) : Network transmit speed.
Uptime : Sandbox running time in hours:minutes:seconds format.
USER : The owner of the sandbox.
๐ NAME VALIDATION ๐
For simplicity, the same name validation is used for multiple options. Rules, and yes there are rules babe:
The name must be 1-253 characters long. The name can only contain ASCII letters, digits and the special characters -._ (that is, the name cannot contain spaces or control characters). The name cannot contain only digits. The first and last characters must be an ASCII letter or digit and the name may contain special characters in the middle. So mybrowser? iconic. 12345? not it. _nope_? also not it ๐ญ
๐ GLOBAL CONFIG FILE ๐
firejail.config is the global configuration file, and resides in /etc/firejail directory. Most major Firejail features can be enabled or disabled. Uncomment the line and switch the yes/no flag. Examples:
# restricted-network no : Enable or disable restricted network support, default disabled. If enabled, Firejail grants access to --interface, --net=ethXXX and --netfilter features only to root user. Regular users are only allowed --net=none.
Note: When restricted-network is disabled on a multiuser system, Firejail allows the user to bypass the firewall installed by the system administrator. Some distributions such as Debian and Ubuntu ship with restricted-network yes in the configuration file. So like, heads up ๐
# browser-disable-u2f yes : Disable U2F in browsers, default enabled.
Note: Universal Two-Factor (U2F) devices are used as a password store for online accounts. These devices usually come in a form of a USB key.
# browser-allow-drm no : Allow DRM execution in browsers, default disabled.
# force-nonewprivs no : Force use of nonewprivs on all programs, default disabled.
Note: nonewprivs is a Linux kernel feature that prevents programs from rising privileges. It is also a strong mitigation against exploits in Firejail. However, some programs like chromium, wireshark, or even ping might not work.
# seccomp-error-action EPERM : Seccomp error action, kill, log or errno (EPERM, ENOSYS etc). By default seccomp prevents the program from running the syscall and returns an error.
Note: ChangeEPERMtoKILLif you want the program to exit immediately.
๐ฅ EXAMPLES ๐ฅ
firejail
Sandbox a regular shell session.
firejail /usr/bin/firefox
Start Mozilla Firefox.
firejail --debug /usr/bin/firefox
Debug Firefox sandbox.
firejail --private /usr/bin/firefox
Start Firefox with a new, empty home directory.
firejail --net=none /usr/bin/vlc
Start VLC in an unconnected network namespace.
firejail --net=eth0 /usr/bin/firefox
Start Firefox in a new network namespace. An IP address is assigned automatically.
firejail --net=br0 --ip=10.10.20.5 --net=br1 --net=br2
Start a shell session in a new network namespace and connect it to br0, br1, and br2 host bridge devices. IP addresses are assigned automatically for the interfaces connected to br1 and br2.
firejail --list
List all sandboxed processes.
โญ LICENSE โญ
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
Homepage: https://firejail.wordpress.com
๐ซถ SEE ALSO ๐ซถ
firemon(1), firecfg(1), firejail-profile(5), firejail-login(5), firejail-users(5), jailcheck(1)
https://github.com/netblue30/firejail/wiki, https://github.com/netblue30/firejail
okay that's the whole page bestie, you're officially a firejail scholar ๐โจ go forth and sandbox responsibly ๐ This lil beauty is 0.9.82.2, dated Nov 2026, and it answers to the name FIREJAIL(1) โ periodt ๐ฆ๐
๐ฆ where this page comes from
- arch rolling: firejail 0.9.82.2-1 ยท GPL-2.0-only
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms