User:Sakaki/Sakaki's EFI Install Guide/Sandboxing the Firefox Browser with Firejail

What is the most vulnerable application on your desktop? For most users, it is the web browser, since &mdash; in the picturesque phrase of Nick Congleton &mdash; it is "a large and complex piece of software with the ability to execute code, and it accesses the open Internet and executes just about everything that it comes into contact with". Whilst selective-execution plug-ins such as NoScript can (and should  ) be used to mitigate this risk, they cannot entirely remove it.

Furthermore &mdash; hardening tools such as AppArmor notwithstanding &mdash; the very design of the X11 display server underpinning most Linux desktops means that a compromised application can easily log all keystrokes, capture images of the screen, and even inject  key and mouse events into any other application running on the same display &mdash; and that's just when running as the regular user, without privilege escalation. As such, the consequence of even a modest compromise of the web browser on your system can be devastating.

Fortunately however, with just a little effort, it is possible to effectively 'sandbox' graphical applications, so that:
 * they use their own isolated X11 server, with no access to, or visibility of, the "host" desktop, thereby inhibiting keylogging and similar attacks; and
 * they run inside a Linux 'container', thereby inhibiting many other categories of process-level exploit.

Accordingly, in this mini-guide, I will be running through the process of X11-sandboxing the popular, open-source Firefox web browser on your target PC, using the powerful Firejail utility (and Xephyr X11 server-in-a-window). The approach described may easily be generalized to other browsers (or indeed applications, for example, mail clients etc.), and will work for both and  users.

The screenshot below shows an X11-sandboxed Firefox browser in use:



Note that when deployed in this manner, remains fully functional (so e.g., HTML5 videos on YouTube still work, as shown above), but runs in a highly 'locked-down' environment (aka 'sandbox'), wherein:
 * the parent "desktop" X11 server is not accessible; its sockets (including its abstract UNIX domain socket) are masked through the use of file and network kernel namespaces, thereby e.g., preventing keylogging etc.;
 * the range of permitted system calls is greatly restricted, via a comprehensive filter, and any attempt to call one of the restricted functions causes immediate termination of the process;
 * is also used to restrict the permitted socket protocols (to only, , and );
 * all Linux capabilities are explicitly dropped, as an additional barrier against privilege escalation;
 * via filesystem protection, only a small subset of your machine's full directory structure is visible, critical files are set read-only, many programs are masked, and only a tightly defined subset of your home directory files can be accessed;
 * a local network stack is used, with packet forwarding to your main network arranged outside the sandbox, so the application cannot capture or monitor other network traffic;
 * via a PID namespace, only processes local to the sandbox are visible within it; and
 * (optionally) via a user namespace, within the sandbox no root account is even present.

(Don't worry if some of the above terms are unfamiliar; they will be more fully explained shortly).

Furthermore, unlike a 'full' virtualisation environment (such as e.g., Xen, VirtualBox or QEMU), Firejail sandboxes do not each run their own copy of a full-blown operating system &mdash; they simply live in a resource-isolated environment created by standard facilities of your system's existing Linux kernel. As such, despite the high level of protection offered, the overhead of running a Firejail sandbox is extremely low. Furthermore, there are no background server processes required, nor are there any out-of-tree kernel modules or similar to maintain.

The process we will be going through is as follows:
 * reviewing some (optional, but useful) introductory background material;
 * ensuring that you have the necessary (GNOME 3 + X11, or GNOME 3 + Wayland) baseline system available;
 * installing the required software, which will entail:
 * rebuilding your kernel with the necessary options enabled;
 * installing the browser (if you do not already have it);
 * rebuilding with Xephyr support, and installing some X11 utilities;
 * installing the package (and some supporting utilities);
 * installing the window manager, for use inside ;
 * configuring your X11 sandbox, viz.:
 * setting up a persistent bridge, to which the sandbox can connect;
 * setting up a routing firewall (via ), to forward sandbox traffic from the bridge to your main network interface;
 * setting up an "autostart" service script, to enable window resizing and (configurable) clipboard sharing;
 * modifying 's configuration file (to specify some settings);
 * creating an file, for 'tweaks' to 's default  security profile;
 * setting up a file, to allow the sandboxed browser to be launched graphically;
 * testing your new X11-sandboxed browser;
 * some tips for day-to-day use will also be provided here;
 * as will some brief troubleshooting hints.

If you are ready, let's go!

Introduction
We'll begin with a simple demonstration that 'vanilla' X11 does not provide any isolation between applications running within the same desktop (X server ), as even many experienced Linux users are unaware this is the case. Then, we'll discuss how it is possible to isolate X11 processes, through the use of a separate, "nested" X server (in our case, ) running within an appropriate sandbox, and we'll conclude by running through some of 's sandboxing features in a little more detail.

Demonstrating the X11 Vulnerability
As just mentioned, by default X11 does not provide any GUI isolation between running applications. That means, inter alia, that any application granted access to your display (on an X11-based desktop, such as GNOME ) can read and inject keystrokes into any other (even if their underlying processes have different s), take snapshots of the desktop or individual windows, and even move and resize windows at will. This holds true even if standard process-level sandboxing (for example, via a framework such as SELinux) is in use, and as such can nullify any other security precautions taken on a system.

You can easily demonstrate this yourself. Log into your GNOME desktop as your regular user (this will be in what follows, but obviously, adapt for your particular case). That done, open a terminal window, become root, and install the necessary software:

These are small programs and will not take long to download or install. Next, from the root prompt, start a text editor session:

A text editor window will open. Now, since this process is running as the root, and using a file location that is inaccessible to regular users, you might reasonably believe it to be secure... but as we will shortly see, it is not.

Next, before typing anything in the window, open another terminal window (as your regular, unprivileged user) and issue:

A list of pointer and keyboard devices known to your X11 server will be displayed. Note the of the keyboard device (there may be more than one, in which case, note them all, and then try the last-listed  first, in what follows). Then issue:

If does not immediately output a   message as above (caused by you letting go of the  key, which you pushed down to execute the   command in the first place), then you have specified the wrong  value &mdash; in that case, press  to quit, then try the command above again with a different  (from the original set of candidates you gleaned via ).

Once it is working, mouse back into the (root) window again, and start typing. Notice how your keystrokes are reflected by the  program, even though it is not running as root:



When done, click on the terminal window in which is running, and press  to quit it. Then, leaving the window open for now, issue:

These commands, again running only as the standard user (not root), will silently take a full desktop screenshot (including the window with the notional secret password text) and save it to.

You can check it worked with the ('eye-of-gnome') image tool, if you like:

Close out the viewer and (standard user) terminal window when done, then also close out the  window (there's no need to save the  file, we were just using it for illustration). Finally, type followed by  again in the root terminal window, to close it.

As you can appreciate from the above, running X11 represents quite a significant security risk, particularly with applications like web browsers, which routinely execute large quantities of arbitrary, unchecked code during everyday use.

Sandboxing with Firejail: A Brief, High-Level Tour
As we are going to be using to sandbox the  web browser on your machine, in this section, we'll briefly discuss the isolation technologies it offers (actual installation and usage instructions will be given thereafter; click here if you with to jump directly to that section).

In its simplest form, you can sandbox an application simply by prefixing its command line with  (run as your regular user; the  program itself is SUID). So, for example,  would run the  text editor on the file, inside a sandbox. As discussed below, there are various protection mechanisms can employ, and these are automatically specified on a per-application basis through the use of a profile configuration file. When a program is launched under, it will automatically try to load the matching security profile  (for our example, this would be ). If no such file exists, the (fairly restrictive) is used instead (unless the sandbox has been started by the root user, in which case  is used).

We'll now briefly discuss the main categories of protection offered by. Note that you won't actually need to run any of the examples here on your own machine &mdash; just read through them, they are presented simply to familiarize you with the concepts involved. (Also, we have not yet configured your machine correctly to run ; but of course, once we have, you can come back and try these out for yourself, if you like.)

Graphical Isolation via Xephyr
The first point to note is that allows a graphical program to be started within its own, dedicated X11 server (via the use of its   option). In what follows, we will use Xephyr &mdash; a full X11 server that outputs to a (resizeable) window on a pre-existing 'host' X display.

The below screenshot shows an terminal, launched on a  X11 server, using  from the command line:



As can be seen, in the window (running on the 'outer' X11 server) there are three X11 UNIX sockets visible within the filesystem, at,  and. The first of these,, is root and connects to the  login manager's X11 server. The second,, connects to the X11 server hosting the GNOME desktop itself (so e.g., running  in the  session would return  ); it is the 'outer' (aka 'host') X11 server in this case. And the third, here, is connected to the X11 server (so e.g. running   in the  would return  ); it is the 'inner' or 'nested' X11 server in this example.

Although &mdash; courtesy of 's default filesystem protection &mdash; within the context (i.e., running on the  server) only  is visible at the directory level (compare the outputs of   in the two terminals above), this is not sufficient for graphical isolation, as the   output shows. The funny looking paths starting with '@' are UNIX abstract domain sockets, which are filesystem independent, and make it possible for e.g. even a baseline -sandboxed program to capture input from the 'outer' desktop, unless other precautions are taken.

To get around this issue, and properly isolate the 'host' X11 server's sockets, we need to run Firejailed programs within their own network namespace (discussed shortly). By default, will support this natively if you use a wired Ethernet interface on your machine; for example, in the below screenshot, there is an Ethernet adaptor available on, so we can simply add   to the  command line, which solves the problem:



Unfortunately however, this simple approach will not work for a WiFi interface (which on many laptop machines represents the primary, and often only, means of network connectivity) (we'll discuss the reason why shortly). As such, in the main text, we will provide a slightly different solution (using a bridge and routing firewall) which will work for with both wired and wireless interfaces.

One other point to note from the above screenshots: if you look carefully, you'll see that the window itself (not to be confused with the  frame, which is entitled  ) has no title bar or other window decorations, and is not resizeable. Nor is it possible to dynamically open other windows 'inside' the frame. To work around these issues (which would be unacceptable when using a browser) we will run the window manager on  when deploying  ( is a very capable yet lightweight window manager; it will do what we want 'out of the box', but can also be extensively customized, should you require this).

Permitted Syscall Management via Seccomp-BPF
The next isolation technique utilized by is Seccomp-BPF (which stands for secure computing - Berkeley packet filter). This is a Linux kernel facility, via which the system calls available to a given userland process (and its descendants) may be restricted for safety. It works by intercepting syscall requests and matching their syscall number and argument list via a pre-specified BPF program (in this case, supplied by ) The BPF program's rules specify the subsequent action to take if a match occurs (for example: allow the call, return an error code, kill the calling process etc.)

Most profiles (including the default profile and  profile) specify a fairly restrictive  filter set, which, at the time of writing, blocks the following syscalls:, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,  and.

The below screenshot shows an example of in use. In it, a call is attempted within an  process running inside  sandbox. Because this call is one of those restricted by default (see the list above), the binary is aborted and an error is written to the audit log,  (note that you need to have  turned on in your kernel, have  or  (as appropriate) compiled with the  USE flag, and have  running, to be able to see this log).



By default, both 32-bit and 64-bit filters are installed.

Privilege Management via Capabilities
As a third isolation technique, provides the ability to restrict the capabilities of a Linux process.

To briefly explain: historically UNIX implementations segregated processes into two simple groups, viz:
 * root-privileged processes, which bypass all kernel permission checks; and
 * unprivileged processes, which are subject to full ACL-based permission checking, based on the effective user and group IDs (/), and the supplementary group list.

That all changed with the introduction of capabilities, in Linux kernel 2.2. Capabilities split up the monolithic root privilege into smaller blocks (or sets) of permissions, which can be independently enabled or disabled on a per-thread basis (and as of kernel 2.6.24, may also be persistently associated with executable files, via extended attributes ).

By default, drops all all capabilities from the  process. Inter alia, this causes subsequent attempts by the process (or its children) to load kernel modules, escalate privileges, replace the kernel, restart the system etc. to be rejected.

The below screenshot shows an example of this in action. In it, a trivial program is first compiled (by root); this application simply attempts to set the ownership of a file (the pathname of which is given as its first argument) to  0  0. Of course, under Linux, such a program would normally fail unless also invoked by the root user. However, next, the capability is added to the executable's extended attributes via  (you can think of this as a sort of restricted SUID, allowing the program to carry out the  operation when invoked by any user (who needs only the right to execute it)).

Then, two windows are started. In the first (upper left) one, no profile is used, so the unprivileged user can successfully use the dangerous  program to make a newly created file  owned.



However, in the second (lower left) window, all capabilities are explicitly dropped (via the  option). In this case, the attempt to run fails, with an   error.

The 'no-capabilities' status for a process under Linux is inherited by all its children, and, once capabilities are dropped, there is no way to get them back (modulo any serious kernel security bugs; however, see also the note below for one 'gotcha' you need to guard against). As such, this facility represents a very important line of defence against exploits. At the time of writing, the capabilities dropped by 's profile are :, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,.

Resource Isolation via Linux Namespaces
We've mentioned a few types of Linux namespace in passing already, so now let's take a slightly more in-depth look at this important kernel technology, and how makes use of it to enhance security.

In essence, namespaces wrap global system resources, such that processes inside the namespace appear to have their own isolated copy of those resources. As such, they are a major enabler for containers, lightweight virtualisation, and sandboxing.

The Linux kernel currently provides seven major classes of namespace, viz.:


 * 1) UTS namespaces : probably the simplest, these just enable containers to have their own hostnames and domain names if desired. Firejail places all newly created sandboxes in their own UTS namespace by default; and you can e.g., use the   option to modify the properties of this.
 * 2) Mount namespaces : the first namespace type to be implemented in Linux (in 2002), these allow containers to have their own compartmentalized 'views' of the filesystem; somewhat like, but much more flexible and secure. For example, as  and  calls don't propagate across namespaces (unless explicitly requested), it is possible to use overlay filesystems, bind mounts and the like to make parts of a container's filesystem hidden, read-only, or "amnesiac" (changes are forgotten when the container is closed). Mount namespaces are also used by PID namespaces (see next point) to provide a custom view of the special  filesystem. Firejail makes extensive use of mount namespaces, for example, to facilitate file and directory ing and ing, to support the  (amnesiac home directory) option etc. All newly created Firejail sandboxes have their own mount namespace by default (discussed in more detail below).
 * 3) PID namespaces : these are used to isolate the process IDs within a container. PID numbers are remapped across a PID namespace boundary, and a process cannot see (and so, a fortiori, cannot kill etc.) processes outside its PID namespace (other than those in any child namespaces). Distinct tasks in different namespaces can have the same (numeric) PID. Firejail places all newly created sandboxes in their own PID namespace by default (within which the  process itself is PID 1).
 * 4) Network namespaces : these enable containers to have their own network devices, IP addresses, ARP and routing tables,  rules etc.: essentially an isolated network stack.  This makes them very useful for containerization (e.g. running multiple web servers), but also for sandboxing. Firejail does not place new sandboxes in their own network namespace by default, but can do so when the   parameter is passed. In the configuration described later in this tutorial, we shall make use of this facility, to ensure that the "outer" X11 abstract Unix socket (see above) is inaccessible within the  context.
 * 5) User namespaces : these allow containers to have their own user and group ID number spaces. It has been a somewhat controversial feature, because of the ability it provides for a regular, non-root user to set themselves up as root within a container, and then potentially exploit some (root-only) kernel facilities that are not yet properly namespace aware to launch an attack outside the container boundary. Firejail does not place new sandboxes in a user namespace by default, but will attempt to do so if e.g. the   option is enabled (as it is in the  profile, for example). Note that in the user namespaces created by, there is no root user present at all. If, however,  is turned off in the kernel for security (as it will be in Gentoo by default), this particular option will just no-op if specified; the overall effect on the sandbox security (and operation) in such a case is negligible.
 * 6) Control group namespaces : these allow containers to remap the control group of processes within them. It is a relatively new feature (Linux 4.6) and not currently used by Firejail (although it does make extensive use of the control groups feature itself (for example, to allow a sandboxed process to be resource-limited where desired)).
 * 7) IPC namespaces : these allow containers to isolate System V IPC objects and (since Linux 2.6.30) POSIX message queues. Firejail does not place new sandboxes in an IPC namespace by default, but will do so if the   option is passed. It is not used by default in the current  security profile.

There are two very important isolation features that relies on the existence of Linux namespaces to implement, so let's discuss those next.

Comms Isolation via Network Namespaces
First, leverages network namespaces to provide comms isolation &mdash; ensuring that sandboxed applications cannot snoop on other network traffic, set up listening server ports, launch mail spam attacks etc., even if compromised. As shown earlier, if you have a wired Ethernet adaptor, you only need pass the   option to use this feature. In such a case, the sandbox is connected to the network via a device ; it has an address within the local network's netmask range, but runs in its own network namespace, with fully distinct distinct TCP/IP stack, routing table, MAC etc. (see above).

The screenshot below shows an example of this in action:



Notice how the host system's IP address (in this case, ) and the sandbox's  IP address (here, ) are on the same  network segment (the netmask being 24 bits, i.e., ). In fact, they are both bound to the same underlying network adaptor &mdash; the very purpose of being to allow a single physical interface to have multiple MAC and IP addresses using virtual  sub-interfaces. Since each sub-interface is connected directly to the underlying network, clients of a interface can still perform DHCP requests etc.

This is a convenient approach, but unfortunately it won't work with WiFi adaptors, because all access points (APs) will reject frames from a MAC address that did not originally authenticate with them. As such, an attempt to setup a second connection on a sub-interface of a  adaptor would cause any other (existing) connection (on the same physical adaptor, but with a different MAC) to be immediately torn down, thereby dropping the wireless connection.

To get around this issue we must instead use a routed setup. Under this approach (which we will leverage more fully later in the implementation section of this mini-guide), the sandbox is connected (via a inter-namespace tunnel ) to a Linux bridge, and traffic is then routed between the bridge and the default network gateway interface by netfilter rules configured in the 'outer' context. In this way, any valid network connection &mdash; whether wired or wireless &mdash; can be used to (indirectly) provide network connectivity to processes in the sandbox.

The screenshot below shows a simple routed sandbox connection in action:



In this example, a bridge is first set up outside the sandbox, and assigned a network address and netmask (here,  and, respectively). IP forwarding is turned on in the kernel, and the Wikipedia:Iptables / Wikipedia:Netfilter firewall reset to a permissive state (with all inputs, outputs and forwarding between interfaces allowed).

Then a rule is configured in the firewall (still in the 'host' context &mdash; the sandbox actually maintains its own, distinct netfilter ruleset (due to having its own network namespace), but this is not modified here).

The effect of this rule is to dynamically translate packets originating from the source network (here, the bridge, i.e., anything on the segment) so they appear to come from the IP address of the  interface (here, this happens to be, but by using  (as opposed to ) we remove the need to cite the address explicitly in the  rule, which is useful where e.g., DHCP is used on the default gateway interface, making the required address dynamic). The firewall also automatically activates state-matching logic to reverse the process for any reply packets. Normal traffic from the 'host' context (i.e., related to applications running outside the sandbox) is still sent and received directly (here, through ) as usual.

After that, an is started inside a  sandbox as the regular user, with the   parameter.

As may be seen, this causes one endpoint of a virtual Ethernet tunnel (here labelled as ) to be created by  inside the sandbox; this works just like a regular network interface (so tools like  can use it, as shown). In the above example, an address of has been assigned to this  interface (leftmost blue box in the screenshot) ( chooses an address and validates it with ARP automatically &mdash; there's no need for a DHCP server etc.).

Outbound packets on are tunnelled to the matching element of the  pair which exists outside the sandbox (and which is attached to the  bridge by ; rightmost blue box).

From there, outbound packets are forwarded by the ('host' context) firewall to the default network gateway interface (here,, IP , the green box). During this process, the transiting packets' apparent source address is rewritten ( &rarr; ), as a result of the rule. Note that in this case, there is no reason why the default gateway could not be a WiFi interface, rather than an Ethernet one  &mdash; since, unlike the  approach, nothing in this configuration attempts to provision the gateway interface with more than one MAC.

Inbound reply packets, initially ingressing on the interface, essentially follow the above flow in reverse, eventually egressing on the  interface inside the sandbox.

As a result, we achieve the strong communications isolation required. As a side benefit, because each network namespace has its own set of abstract UNIX domain sockets, can make the 'outer' X11-server entirely inaccessible within the sandbox. Furthermore, it is easy to perform more fine-grained -based control of the sandbox's network activity if desired (for example, by adding a rule to block any outbound connections on port 25, as a protection against mail spam) and since this is done outside the sandbox, it would be invisible to (and unchangeable by) any application running inside it.

Filesystem Protection via Mount Namespaces
The second important isolation feature facilitated by Linux namespaces is filesystem protection &mdash; ensuring that sandboxed applications don't have access to private (or dangerous) libraries, files or directories, even if compromised. To do this, automatically builds a on-the-fly root filesystem for each sandbox, within which a large number of localized restrictions are applied (some by default, and others as specified via command-line option and/or security profiles). As mentioned above, the key enabling technology here is mount namespaces; these allow (for example) large numbers of local bind mounts to be made within the sandbox context only, in a way that is invisible to the 'host' (namespace) context.

This approach to sandbox construction is related to the venerable (which we used earlier in the install), but is distinct from it. In a, a sufficiently complete filesystem tree is created at (typically) some sub-location of the 'base' filing system, and then the syscall is used to make this sub-location the effective root path for the calling process (and its descendants). Commonly, special system directories such as, and  are bind mounted into the subtree, prior to the actual  call; any locations not spanned by the subtree or its mounts become invisible to the process (and descendants) after the.

By contrast, leaves the standard root directory in place, but switches to a new mount namespace, after which the 'inside-the-sandbox' view of the root filesystem is significantly altered via various (local)  operations. Since these changes do not (by default) propagate outside the mount namespace, the 'host' system's view of the root filesystem is unaffected.

By default, modifies the baseline root filesystem in the sandbox by bind-remounting, , , , , , ,  and  read-only. Only and  are writable.

This is then further modified by relevant directives in the active security profile (in our case, ) together with any command line options passed directly to itself. Firejail allows a number of protection strategies to be employed; these generally use some combination of Wikipedia:Tmpfs (memory-based temporary filesystem) mounts, bind-mounting 'dummy' files and directories over sensitive locations, and modified filesystem permissions to do their work.

For example, in the below screenshot, an is started within a  sandbox, using the default  security profile:



As may be seen, starting the sandbox does not change the mount table as visible from the 'outer' context; these remain relatively limited: 17 entries, of which 7 are mounts of, or bind-mounts of locations from,  filesystems. Within the sandbox, however, it is quite a different story &mdash; there are 200 mount table entries, of which 170 are marked as.

To better understand what is going on here, let's take a closer look at some of the filesystem-modification options that offers (this is not a comprehensive list):


 * When a file or directory is marked with this directive, bind mounts it (citing identical source and target paths) with the  flag set (as with all such operations, this bind mount is only visible in the sandbox context). Since the,  and  syscalls will generally be restricted by a  filter, and  dropped within the sandbox (see above discussion, here and here), there is no way for the sandboxed application (even if compromised) to undo this operation (true of all the below options).
 * As above, but the marked file or directory is bind-remounted with the, and  options set (see this previous discussion for an explanation of what these are).
 * When a file or directory is marked with this directive, bind mounts a empty, only-readable-by-root dummy file  or directory  as appropriate on top of the specified path. This 'occludes' the original filesystem element within the sandbox, making its contents inaccessible.
 * <span id="about_whitelisting"> Of course, one problem with blacklisting is that anything not explicitly excluded is still allowed, and so (particularly as systems change over time) it is easy for something sensitive to get missed. Further, the name of the blacklisted file or directory is still visible within the sandbox even when the contents are occluded, which may not always be acceptable. To address this, also offers whitelisting. When a file or directory is marked with this directive,  mounts a new  over the parent directory of the cited path (if it has not already done so due to a previous   directive), and then bind-mounts the specified file or directory inside (at its original location). This means that everything else in the parent directory (recursively), that is not whitelisted, becomes invisible inside the sandbox. Further, while changes to whitelisted files or directories persist when the sandbox is closed, any other changes disappear (since they were performed in a ). For example, if  was started with the options   and   (and no others), then it would create a new  and mount it over the user's home (the 'parent' path ) (with the same permissions and ownership as the original home directory had), and then bind-mount the original  and  directories inside this. Nothing else in the user's home directory would be visible.
 * This directive causes a to be mounted over the user's home (and another over ), with a minimal 'fresh' configuration in place. In that sense, it is similar in effect to the  whitelisting performed by the default  profile, but is even more extreme &mdash; only the original  file is bind mounted, and otherwise new skeleton contents are provided (e.g. ). As such, all changes will be discarded upon exit. In fact, the   option will override any home directory whitelisting, if specified together. This can be useful if you want to e.g., access a site using a 'vanilla' browser configuration (no custom add-ons etc.), but in an 'amnesiac' manner (for example, a banking or government site).
 * This directive causes a to be mounted over, with only the specified binaries copied over. The new  is then bind-mounted over , ,  and . This allows for a very restricted environment to be provided, similar to what one might setup in a old-school server.

Firejail provides a large number of other facilities that we have not discussed above. For example, you can use  to build a new  in a, with only the libraries necessary to run the application present (similar to  ). As another example, you can specify the use of a Docker-style overlay filesystem (,  and   options) to store all changes made to the filesystem inside a sandbox into an (potentially reusable) overlay. However, the above summary has hopefully given you a reasonable view of what can do; please refer to the relevant manpages  for further information.

That concludes our high-level tour of. We will now turn to consider its installation and use for sandboxing (at least as an initial application) the web browser.

Prerequisites
To proceed, you will require a target system running Gentoo Linux (either the stable or testing branch is fine), with:


 * a kernel that has at least the baseline configuration used on the Gentoo 'minimal install' media, with the necessary additional configuration changes made to enable an X11-based graphical desktop to run;
 * although most relatively modern kernels should work, given the threat model we are trying to protect against here, a version patched against the Meltdown and (so far as possible) Spectre vulnerabilities is highly recommended (see this page for a list of patched kernels, required microcode updates etc.);
 * additionally, and  should be set;
 * a working X11-based desktop (I assume GNOME 3 in what follows, but the instructions may be easily adapted for other desktops, for example Xfce4, with some minimal configuration changes);
 * a Wayland-based system is also usable, provided it uses the rootless XWayland X11 server to host unported applications such as (see note above);
 * the tool from the  overlay installed (as specified earlier in the tutorial).

For avoidance of doubt, if you have installed a GNOME-based Gentoo system using the other instructions included in this EFI Install Guide, your system is suitable (although in such a case, you may still wish to check that the version of your kernel contains the most recent Meltdown and Spectre patches, particularly if you are running on the stable branch).

Installing the Necessary Software
We'll begin by installing the necessary additional software on your machine.

<span id="kernel_config">Kernel
You will need to enable a number of additional kernel settings (and rebuild your kernel) in order to use successfully.

If you are using one, ensure that your boot USB key is inserted. Then, open a terminal window, become root, and issue:

Then, ensure that the following options are set (where an item is marked 'M' (make as module) in the below, it may also generally be built directly into the kernel if you prefer):

If you wish, you can also turn on user namespaces (see above for a brief discussion regarding the benefits and risks of so doing):

Once you have made the necessary changes, save the kernel configuration and wait for to complete compiling and installing the kernel. When it has completed, reboot your system, then follow the usual steps to unlock the LUKS partition and log in again (using GNOME) as your regular user.

Installing the Firefox Browser
With the kernel configured, we will next install the Firefox web browser.

Now, because, at the time of writing, Firefox will silently auto-download a Gecko Media Plugin binary blob on first use if the (default active) USE flag is set, I recommend you create an entry in  to unset this flag, before proceeding (of course, this step is optional; click here to skip it).

Open a terminal window, become root, and issue:

and append to that file:

Leave the rest of the file (if any contents pre-existed) as-is. Save, and exit.

<span id="actual_firefox_emerge">Then, to install itself, issue (still working as root):

This may take some time to complete, as is a large, complex package with many dependencies.

<span id="install_xephyr">Rebuilding your X11 Server with Xephyr Support
Once completed, the next step is to ensure your X11 server (which you originally installed earlier in the install (../Setting_up_the_GNOME_3_Desktop, ../Setting_up_the_GNOME_3_Desktop_under_OpenRC)) allows the use of the Xephyr X11 server-in-a-window.

Issue:

<span id="need_xpra">and append to that file:

Leave the rest of the file (if any contents pre-existed) as is. Save, and exit.

Now we can re-emerge the X-server itself. Issue:

<span id="install_xsel_xrandr">You should also the  and  packages at this time, as we will need them (for clipboard management and display rescaling, respectively) later. Issue:

These are both small programs, so the above should not take long.

<span id="install_xeyes">Lastly, install the tiny package (it provides an easy, visual way to check if an application's events are visible from another context, a useful diagnostic); and also install  (which can be used to get a list of all connected X11 applications). Issue:

<span id="install_firejail">Installing Firejail and Required Utilities
Next, we can install the program itself (together with a few other utility packages required for the setup described in this tutorial). However, before doing so, we need to alter its default USE flags, to enable inclusion of the code for X11 isolation.

To do so, still working as root, issue:

and append to that file:

Leave the rest of the file (if it was non-blank to begin with) as is. Save, and exit.

Now we are ready to install. Issue:

This may take some time to complete, as  (with X11 isolation active) pulls in  and its dependencies.

Next, since we will need the program to setup networking correctly, install the  package (which supplies this utility). Issue:

<span id="install_iptables">We'll also need the front-end to the kernel  facility. Issue:

The use of these additional programs was discussed earlier.

Finally, since it will be useful to have a simple terminal window available (at least initially) inside the sandboxed environment (and will not work there, by default), issue:

<span id="install_openbox">Installing the OpenBox Window Manager
Next, as discussed previously, we must install a window manager for use within the X11 server display. Here, we'll use, as it is relatively lightweight, but can still do everything we need 'out of the box' (feel free however to choose an alternative package, if desired).

To install, issue:

Congratulations, that's all the necessary software installed!

Configuration
Next, we will configure a baseline set of files and startup services to get your X11 sandboxed browser up and running. Although complete, the following is only meant as a starting point, so feel free to modify some or all of these files, as desired, once you have your sandboxed browser system working.

<span id="setup_bridge">Setting Up the Bridge
As discussed earlier, we need to ensure that we have a 'routing' firewall-and-bridge setup in your 'outer' ('host') context, to enable sandboxed to reach the public internet, even should your target PC be using a WiFi network interface.

We'll write a short script to construct (and, when instructed, tear down) the bridge part of this plumbing first. Issue:

<span id="bridge_script">and then enter the following text in that file:

Next, we need to ensure that our new script is run each time the system is started up; to do so, click here to jump to the (following) instructions for use with (the default), or click here to jump to the (following) instructions for use with, as appropriate.

<span id="setup_bridge_systemd">Creating a Persistent Bridge under systemd (Default)
To enable the script to be run each boot under, we need to write a simple unit file. To do so, issue:

and enter in that file:

This unit file does not need to be made executable (but should only be writeable by root).

Next, start the new service (so triggering the action, thereby running the  script with the "start" parameter, which in turn sets up the  bridge itself). Issue:

Check that the bridge has come up successfully; issue:

The exact details shown for the bridge (for example, its address) will of course depend on your machine specifics, but you should at least see the name and IPv4 address as above (unless you have modified either in the  script, of course).

Assuming that worked, enable the unit file, so the bridge gets setup on boot:

Congratulations, your persistent bridge setup is now complete! Continue reading at "Setting Up a Routing Firewall", below.

<span id="setup_bridge_openrc">Creating a Persistent Bridge under OpenRC
To run the script at system startup under, we need to write a simple init script. To do so, issue:

and enter in that file:

Next, start the new service (so triggering the function, thereby running the  script with the "start" parameter, which in turn sets up the  bridge itself). Issue:

Check that the bridge has come up successfully; issue:

The exact details shown for the bridge (for example, its address) will of course depend on your machine specifics, but you should at least see the name and IPv4 address as above (unless you have modified either in the  script, of course).

Assuming that worked, add the service to the default runlevel, so the bridge gets setup on boot:

Congratulations, your persistent bridge setup is now complete! Continue reading at "Setting Up a Routing Firewall", immediately below.

<span id="setup_firewall">Setting Up a Routing Firewall
With the bridge component of the plumbing disposed with, we can now turn our attention to creating the routing firewall. We'll use the userspace tool to configure the  kernel subsystem here, to enable packets originating from a  sandbox (which will be connected &mdash; across network namespaces &mdash; via a  tunnel to the host system's  bridge) to be forwarded with network address translation ('NAT') onward to your system's main gateway interface (related reply packets will be automatically handled too); see the earlier background material for a detailed discussion of this.

Issue:

and then enter the following text in that file:

Save, and exit.

The above script, will, when executed, first flush all existing rules from the kernel's  firewall (in the 'host' network namespace), and then set up a minimal firewall which s all output and forwarded packets, but s input packets unless they are  to an already  connection, or originate from the   interface.

In addition, to illustrate the kind of further filtering you can do, a rule is set up to block any attempt to connect to port 25 over TCP from the  bridge subnet. This is a basic precaution to prevent a compromised browser attempting to send mail spam. You can of course add more filters (and other firewall rules), as you see fit.

The last line in the script sets up a  (network address translation) rule, which looks for packets being sent out via your main network interface (i.e.,  &mdash; this is  by default in the above, but you will of course have modified this to match your system's default gateway), whose source  address lies in the bridge's subnet range (by default, ). When such packets are seen, the rule causes their source address to be rewritten (via the chain) to match that of, and state-tracking logic is simultaneously put in place to reverse the process for any reply packets.

<span id="enable_ipv4_forwarding">To enable the script to work, we need to turn on IPv4 forwarding in the kernel (and also ensure this happens every boot). To do so, issue:

and modify the lines in that file that currently read:

to the following:

Leave the rest of the file as-is. Save, and exit. Then, reload the configuration. Issue:

and check that the change has been taken up; issue:

<span id="test_firejail_firewall_script">If the result returned is, as above, all is well. Next, run the script we just created to setup our desired firewall configuration. Issue:

<span id="check_iptables_save">Next, check that the firewall rules have been properly installed. Issue:

The output will look somewhat different from the above of course (and the numeric packet counts, inside the square brackets, may be non-zero), but you should be able to verify that the same rules are present.

However, even assuming the output from looks fine, we are not yet done, because, as things stand, the  firewall will be reset the next time the system is booted.

To get around that, we need to save off the current configuration to file, and then enable a service that will reload this saved configuration automatically during startup. Fortunately, the requisite service already exists (provided as part of the package, which we installed earlier). So next, click here to jump to the (following) instructions if you are running (the default), or click here to jump to the (following) instructions if you are running.

<span id="setup_networking_systemd">Create Persistent Firewall State under systemd (Default)
Begin by saving off the persistent firewall state (and ensuring it is also saved afresh on each shutdown). Issue:

Then, enable the state-reloading service:

Congratulations, your persistent routing firewall is now setup! Now continue reading at "Setting Up Clipboard Sharing and Display Rescaling for Xephyr", below.

<span id="setup_networking_openrc">Create Networking Setup Script under OpenRC
Begin by saving off the persistent firewall state:

Then, start the service (which will automatically reload the saved firewall rules, and will additionally save the ruleset afresh on each shutdown), and ensure that it is automatically started at boot. Issue:

Congratulations, your persistent routing firewall is now setup! Now continue reading at "Setting Up Clipboard and Display Rescaling for Xephyr", immediately below.

<span id="setup_clipboard_sharing">Setting Up Clipboard Sharing and Display Rescaling for Xephyr
Next, we'll set up a background service script (to be run with regular user, not root, privileges), which will address two of the main usability shortcomings encountered when running a graphical application inside a nested X11-server, specifically:
 * copy and paste does not work between the and host clipboards; and
 * when the window is resized, only mouse clicks within the original window boundary are accepted.

The script provided runs a main loop once per second, which will:
 * sync any changes in the clipboard to the host's, if (and only if) the sentinel file  is present (using the  program, which we installed earlier);
 * sync any changes in the host's clipboard to the clipboard, if (and only if) the sentinel file  is present (ditto); and
 * propagate any changes in the outer window size to its display (using, which was also installed earlier).

Issue:

Then copy the following contents into that file (modifying as desired):

Save, and exit.

Now, open a fresh terminal window as your regular user (leaving the root terminal window open also).

<span id="create_clipboard_sentinel">Next, if (and only if) you would like your host system's clipboard to be automatically reflected to any running X11 sandbox (when changed), as your regular user issue (this step is optional):

Similarly, if (and only if) you would like the sandbox's clipboard to be automatically reflected to the host's (when changed), issue (again, this step is optional):

<span id="start_xephyr_helper">We can now try starting the script directly, to check that no immediate error is flagged. So, working as your regular user, issue:

If the script starts correctly and does not immediately terminate with an error, all is well. By default, it will produce no output. Stop it manually now, by pressing.

Next, we need to arrange that our script will be automatically started up in the background whenever your regular user logs in to GNOME. To do this, we'll create a simple XDG autostart file.

Still working as your regular user, issue:

and place the following text in that file:

Save, and exit.

With that done, manually start the desktop file now, to check that the script runs correctly. We'll temporarily (hard) link it in to the directory to allow this to be done easily from the command line (using the  utility). Still running as your regular user, issue:

<span id="check_xephyr_helper_running">Check that the script is running in the background successfully:

The actual process id ('pid') returned by will almost certainly differ on your machine; the important thing is that some pid is printed (if not, it indicates that something is most likely wrong with your  file &mdash; since you managed to run the  script directly from the command line earlier).

Assuming the script is now running in the background, congratulations, setup of your usability helper is now complete! It will now be automatically launched in the background whenever your regular user logs in to GNOME.

<span id="setup_firejail_config">Configuring Firejail
Our next task is to modify 's shipped configuration file slightly, to:
 * specify the initial size any window(s) should open at; and
 * indicate that we also want our window(s) to be resizeable.

Switching back to your root terminal again, issue:

<span id="modify_firejail_config">and modify the section of that file dealing with settings, adding the uncommented lines as below:

Leave the rest of the file as-is. Save, and exit.

You can of course modify the size from the above  to something more appropriate to your system (you can specify any size that will fit on your display). Generally speaking, given that you are likely to have multiple browser windows open within your window, an initial setup just a little smaller than your 'native' screen resolution may prove to be the most useable. You can easily come back to this setting to fine tune it later.

In any event, since you have stipulated that pass the  parameter to  above, and since we have arranged for the  script to be running in the background upon login, once the sandbox has been launched you can resize (and, if you like, maximize) the  window to suit your requirements, by click-dragging one of its handles with the mouse, as usual.

<span id="setup_local_firefox_config">Creating a (Supplementary) Local Firejail Security Profile for Firefox
Next, we'll create a supplementary ('') security configuration profile for use with. As discussed in the background reading section earlier, such a file will (if present) be sourced at the start of the main, and so is a good way to stipulate 'tweaks' to the shipped profile, without having to edit it directly.

The main change we need here is to allow access from within the sandbox to three window manager configuration files; these reside in a directory  that is normally masked by the home directory whitelisting (filesystem protection) strategy employed by the  profile.

As root, issue:

<span id="openbox_xml_files">and place the following text in that file:

Save, and exit.

Finally, switch back to your regular user terminal, and ensure that the relevant parent directory exists (there's no need to create the, or  files until and unless you explicitly need them, though):

<span id="setup_desktop_file">Creating a .desktop File for X11-Firejailed Firefox
The final configuration task is to create a file, to allow our X11-sandboxed  to be launched as a 'first class' application from the GNOME desktop (with a matching icon that can be docked in the 'Favourites' bar, etc.).

We'll first fetch a custom icon for the sandboxed browser, so it is easy to distinguish at a glance. The following (downloadable) icon by Frank Souza is free for non-commercial use; of course feel free to substitute your own (incidentally, the standard icon is available at, should you wish to use that instead).

Working still as your regular user, issue:

and enter the following text in that file:

Save, and exit.

As with the autostart file we set up earlier, most of the above keys should be self-explanatory (a full list may be found here). However, there are a few points worth clarifying:
 * As just described, we stipulate a custom, so that the protected application may easily be distinguished.
 * The stanza is fairly complex. We'll unpack that separately, below.
 * We specify that the application belongs to the  &mdash; this ensures that if multiple instances are launched, they are don't all show up as separate icons in the dock, and that the desktop window-switcher groups them all together.
 * We notify a sensible set of s the program can handle (to allow the desktop to suggest it when e.g. a file of matching type is double-clicked).

Let's now look at the stanza in more detail:
 * We use the program to launch  in a modified environment: specifically, we set  to specify the use of the (legacy, but always installed) X input method (you can replace this with another framework, such as fcitx, if you have it emerged). We need to do this, because otherwise IBus will be chosen by default, which unfortunately does not work with  when (as here) the network namespace feature is in use.
 * is invoked with the  option (to use a dedicated X11 server, as discussed earlier).
 * <span id="name_the_sandbox">The  option specifies the sandbox's name . This makes it easy to invoke  to perform operations on the running sandbox (from a regular-user command prompt on the 'host' desktop; see the  manpage for more details; some examples are also given later in this document). (Incidentally, there is no requirement that the sandbox name match that of the application, it can be anything you like. Unnamed sandboxes can still be operated on, by .)
 * The  option instructs  to create a new network namespace for the sandbox, then connect it via a  inter-namespace tunnel to the  bridge (again, as discussed earlier).
 * Since our underlying target program is actually, but we are starting as the 'top level' sandbox application, we explicitly specify the  profile (via  ), to prevent the (less-restrictive)  being auto-selected instead.
 * The final part of the invocation actually launches ; the remainder of the arguments are then passed along to it. Here, we use, so that when  runs, it in turn starts up , as desired (you can use the same pattern if creating other  files for different applications). Note that the   is expanded during the  file handling, to the URL that caused  to be invoked (most commonly, this will be empty).

With the file in place, congratulations, configuration of your X11-firejailed  is now complete!

<span id="testing_and_use">Testing and Use
In this section, we'll first run briefly through some tests with your new sandboxed browser (which will also be useful as a familiarization exercise). Following that, some brief miscellaneous tips and troubleshooting notes conclude the mini-guide.

<span id="basic_tests">Testing your X11-Sandboxed Firefox
To check that all the startup components are working as they should, first save any other work in progress, then log out and reboot your machine (following your standard procedure to enter the LUKS passphrase etc. when prompted). Next, log in again as your regular user to GNOME (using a standard X11 or Wayland session, as appropriate to your setup).

Having done so, make sure that your original is not running (if it is, close it), then click on the  label on the top-right of your screen (or press the  key), and type  into the search box. You should see both the new and original X11-sandboxed icons visible:

Right-click on the (new) icon, then select. Press, then click on the label again (or press the  key). You should see that your new icon is now present in the left-hand dock, at the bottom. You can drag it slightly out to the right while holding down the left mouse button, then up, to position it within the dock as desired (release the left mouse button when done):

Then, click on your new ("X11-Firejailed Firefox") icon in the dock. You should see that a window entitled "" opens (this is the frame, a standalone "desktop-in-a-window"), with the initial dimensions that you specified in, above. It will be filled (at least initially) with a black background colour. Then, a browser window should almost immediately open (automatically) inside this frame. The exact layout you see will obviously depend upon your setup, but should look something like the below:



You can now do some basic testing on your new setup.

To begin with, try browsing to a few sites as you would normally. Note that if you have used before on your target machine, then any previous bookmarks, browsing history etc., will be available inside the sandbox, because the necessary cache and configuration files locations are whitelisted in. Media playback and (existing, installed) add-ons should be functional too.

Try browsing to a site like YouTube, and verify that video (and audio) playback works without glitches, with a similar quality level to your 'host' desktop:



Next, try moving and resizing the window itself on your main desktop; you should also be able to maximize it if you like. Check that after any such resize, you can still click on (and, e.g., maximize etc.) windows within the  frame (this should be possible, due to our  script):



The window acts like a mini-desktop (thanks to ). Verify that you can open multiple browser windows inside the sandbox (click on the 'burger stack' menu in, then ); and check that these windows can be moved around, resized, maximized, closed etc. at will (note that you can of course still use multiple tabs per window, as well):

<span id="openbox_context_menu">Next, right-click on the (black) background area inside the window, to bring up an  context menu. Be aware that the menu displayed is simply the shipped default (you can modify it by creating if you like), and so many of the applications shown either won't be installed on your system, or will fail to start due to 's sandbox restrictions. Nevertheless, you should be able to run (a simple terminal emulator) and  (GNOME's file browser) via the menu, as shown below:

You can use these two applications to explore the limited filesystem visible within the sandbox &mdash; you should find that most of the existing directories in your are invisible. However, by default the is whitelisted, and so its contents are visible both inside and outside the sandbox. Check that you can download a file from into this directory (it is the default for ), and then open it on your 'host' desktop:



Next, verify that (most) other locations in your home directory are off-limits, by creating a file outside the sandbox, and another  inside it. Neither should be visible from the other context, as shown below:



Next, assuming you chose to create the sentinel files and  earlier, you should verify that clipboard sharing is working. Select some text in one of your browser windows inside the sandbox, and try pasting it into an application on your 'host' desktop as you normally would (the operation should succeed). Then, try it in the reverse direction (copying from an application on the 'host', and pasting into an application in the sandbox; this should also work):

This is a very useful facility, but if you leave it turned on (via the sentinel files) be wary of clipboard snooping or injection exploits, which may be launched from a compromised browser.

Finally, open an within the sandbox (via the  context menu as above), and therein issue (as your regular user). The program will try to intercept mouse events, and so move the 'eyes' to track your cursor. Next, use the move the cursor across and then out of the sandbox window. You should find that the 'eyes' track your cursor up to the edge of the frame, but no further (this is a quick, although not complete, way to check that X11 events outside the sandbox are indeed isolated from programs running within it):



That concludes the tests &mdash; if you have got this far, almost certainly your system's other sandboxing features are working correctly too (e.g., program blacklisting etc.), but, feel free to try these out for yourself, per the examples shown in the background reading section earlier (for example, you could try to to root inside the sandbox, to check that this is disallowed, etc.).

Assuming all the above tests were successful, then congratulations, you have successfully installed an X11-firejailed browser on your system! Use this for all your general web surfing going forward, and you'll benefit from significantly enhanced security against a range of possible browser-based exploits.

You can now continue reading below for a few additional usage tips, or alternatively, to rejoin the main guide, please click here or here.

If however you experienced some problems, then please refer instead to the "Troubleshooting" section (below).

Miscellaneous Hints and Tips
The following is a miscellaneous list of hints and tips that you may find useful. It should be regarded as a 'work in progress'; feel free to contribute! The points are listed in no particular order.


 * <span id="use_script_blocker">You should install a selective script blocker add-on such as NoScript or uMatrix in your browser as soon as practicable. The best defence against exploit code is not allowing it to run in the first place.
 * <span id="custom_user_dot_js">Also consider using this configuration file for, to harden the browser settings and make it more secure (there is also a less-locked-down "relaxed variant", which is very useable on a day-to-day basis).
 * <span id="use_firecfg">If you like, you can easily activate protection for all supported applications, by running (as root, or using ) the  utility. Once this has been done, clicking on the icon of a supported program (or launching it from the command line) will automatically start it within a sandbox. Note however that, by default, you won't get any X11 sandboxing of graphical applications launched this way (to do that, you need to set up an appropriate  file, patterned on the one we created for, earlier).
 * <span id="one_instance_only">If you attempt to launch a standard window (in the 'host' desktop) whilst the sandboxed version is open, it will fail, because by default the newly launched application will try to connect to the running instance, only to be barred due to 's protection (even if you use the  or  options). The solution is either to: a) close your  window while you use your host desktop browser, <span id="option_b">or b) start your new browser in 'amnesiac' mode (see below), or c) invoke  to open inside the existing sandbox context (which we have named "firefox"). As an example of c), you could issue (as your regular user): , to open the Gentoo homepage in a new window inside the sandbox ( frame).
 * <span id="one_sandboxed_instance_only">Similarly, if you try to launch two instances of the "X11-Firejailed Firefox" application, it will not work. You can open as many browser windows as you like inside the window however, and that (outer) window can be resized to be as large as you like.
 * <span id="amnesiac_browser">If you want to quickly launch a browser in 'vanilla' state (no plugins, history etc.; the option b) just discussed) you can do this by issuing (as your regular user) e.g., . This will open a browser window on your main desktop, and will work even if you have an X11-sandboxed version running. It is useful if you want to e.g. access a trusted site (for banking, say) but you don't completely trust the plugins etc. you use might employ for day-to-day browsing. The new browser instance will not be running in an X11 sandbox (so you have full copy/paste/drag/drop etc. available) but is started under, with an empty   and skeleton  directory, which will be discarded when the browser is closed &mdash; so the setup is reasonably 'amnesiac'.
 * There are useful variants of the above, such as starting with a copy of your directory in place, using separate (preserved) directories as 'home' in different contexts (such as for work use, home use) etc. Refer to the  manpage for further details.
 * <span id="list_sandboxes">You can get a list of all running sandboxes with, and a process tree for each sandbox with   (issued as your regular user via a terminal on the 'host' desktop).
 * <span id="join_sandbox">You can 'enter' the context of an existing sandbox from outside, by using 's  option. For example, if you have an "X11-Firejailed Firefox" window open, issuing:   from a terminal window on the 'host' desktop would will open a bash shell inside the sandbox (this is a useful alternative to ). The same approach can also be used to launch a graphical application inside an existing  sandbox, as above.
 * <span id="file_copy_commands">In addition to using the directory to pass files in and out of the sandbox, you can explicitly copy files in and out from a (regular user) command prompt on the host, using   and , respectively (the location of is the current working directory).
 * is a full-blown window manager with an extensive community. You can easily customize the background, startup applications, context menu contents and more, by editing its xml configuration files (see above).

There are many other capabilities of that I have not touched on in this guide, such as e.g. imposing resource limits on processes (bandwidth, CPU time etc.), auditing security profiles, integration with AppArmor and more. I highly recommend that you take a moment now to read the manpage and on-line documentation.

When you're ready to rejoin the main guide, please click here or here.

Troubleshooting
If you are having difficulty getting your X11-Firejailed Firefox running properly, the following troubleshooting hints may help (please note, this is by no means a comprehensive list).

A relatively common issue is that the newly created, X11-firejailed browser appears to start up OK, but then can't load web pages (has no network connectivity), so we'll discuss that first:
 * Before doing anything else, verify that you can successfully run (as the regular user) a 'vanilla' instance of (when no sandboxed instance is running) on your 'host' desktop, and use it to view web pages. If you can't, you have a fundamental system problem, outside the scope of this mini-guide &mdash; rectify that first, and then retry.
 * Assuming that does work, however, close your 'host' instance of, and then try running  from the command line, working as the regular user on a terminal launched from the 'host' desktop. This won't get you any X11 sandboxing or network isolation of course, but it should work (and allow browsing) &mdash; if not, it suggests that something is wrong with your  installation, most likely due to some missing kernel configuration options. Double check these (see above), recompile your kernel (and reboot) if necessary, and try again.
 * However, if the previous test worked, but you are still unable to connect to the web from a browser running inside a full sandbox, this suggests you have an issue with the bridge or  routing. First, make sure that your persistent bridge is available and has a valid IP address (for most users, this will be  and, respectively), by using  (or similar tool). If the bridge isn't listed, check that your  service is running (see above), and that the  script runs without error, if invoked standalone.
 * However, if your bridge is present, next check that forwarding is enabled in your kernel. Run  and check that the result is , if not, set up your  file correctly, then reload it (instructions here).
 * Moving on, if your bridge is up, and IPv4 forwarding is enabled, but you still have no connectivity, the most likely remaining suspect is the -based NAT routing, by means of which packets appearing on the bridge get sent out on your host's main network interface. Accordingly, check next that your  rules have been set up properly: run (as root)   and examine the output (see this earlier discussion). In particular, ensure that the interface listed in the  rule really is that of your main IP interface (the one through which your default gateway is reached; you can find this using , and looking for the entry marked ). If it is not (for example, the  output includes something like  , but your default interface as reported by   is something different, i.e., not ), fix this in the  script (as directed earlier), then invoke the  script once more (remember also to save off the new firewall rules if you are successful, and also make sure that you have the necessary rule-reloading service enabled, so any changes are persistent; see above (ff) for details).
 * If, having done all that, you still can't connect inside the sandbox, double check that the correct bridge name (by default, ) has been used (for the   parameter) in the  file. If not, fix it, close the sandbox window, and then launch the "X11-Firejailed Firefox" application again. You should be able to access the web now.
 * NB: if you elected to change either the default bridge name (from ) or the default bridge address / subnet (from earlier, make sure that these are used consistently inside the,  and  files).
 * If you still can't connect, the obvious answers are exhausted &mdash; I'm afraid you'll have to dig a bit deeper with terminal tools inside the sandbox, to diagnose your problem.

A few other (miscellaneous) issues are commonly encountered:
 * If you can successfully launch the sandboxed browser, and view web pages using it, but find that strange things happen when you resize the  window (for example, clicks seem to get ignored), then you need to ensure that your  script is running. Run   to check this (as noted earlier). If you find it isn't running, make sure you have set up the  file, and also check that you are able to run the helper directly without errors (as discussed earlier). Remember that an autostart entry needs to be set up for each user on the machine that wishes to run X11-sandboxed.
 * On Wayland systems, you may find that your (host) display server locks up when you try to resize any windows (particularly if you are using a multi-GPU system). If this happens to you, comment out the   line in  (discussed above), and try again.
 * If you are unable to copy and paste between the 'host' desktop and the sandbox (or vice versa), ensure in the first instance that the script is running, as just discussed. If it is, make sure you have also created (in the 'host' context, as your regular user) the files  and, as appropriate to your desired policy.
 * By default, 'middle-click' paste doesn't work between sandbox and host, although you can easily modify the script to enable this (see above). Drag and drop doesn't work either (making that work is possible too, but a little more tricky).
 * If the window comes up OK, and you can e.g. open an  within it, but  itself won't start, make sure that you don't have another  instance already running on your system (use   to check); if you find you do have another, shut it down first (as discussed above) (if you can see no window to close, use   to remove any lingering rogue processes that an earlier invocation of the browser may have left behind).

As mentioned, once you have tracked down the problem, refer to the appropriate section of the guide above to fix it, then proceed to test again. You can also try posting a request for help to forums.gentoo.org, or, if you believe what you are seeing is a bug, open an issue with the project.

Good luck! To rejoin the main guide, please click here or here.