Running Firefox As An Isolated Linux User

A few years back, I decided that the risks of running some Internet-connected programs on my workstation containing personal data was a bigger risk than necessary. After discussing this topic with several colleagues, the general consensus was that I'm too paranoid.

Consider that implementation bugs (i.e. software vulnerabilities) and trojans in user-level applications (normally) have access to all data owned by the executing user. To me, running a web browser with the same user that has full access (whether by accident, malice, or design) to my personal information is simply unreasonable.

Unfortunately, information about acheiving this level of isolation was not readily available. This article pieces together the several components required to run Firefox under a completely isolated user. I have adapted this script to work with irssi, Pidgin, and Claws, so the solution is fairly reusable.

Steps

The following steps assume a good understanding of the Linux command line interface. Please read the following steps prior to beginning. If any step is incorrect or unclear, please contact me.

Should you follow any of these steps, ensure you first read the considerations, below, and take all precautions (especially backups) to prevent the loss of your data.

  1. Create a firefox user and group.

    sudo /usr/sbin/useradd firefox -d /var/lib/firefox
    

    Alternatively, you may choose to put the firefox user directory in /home.

  2. Add the newly created firefox group as a sub-group to your primary user, yourusername. This allows easier file access (downloads, for example).

    sudo /usr/sbin/usermod -a -G firefox yourusername
    
  3. If desired, move or copy your existing Firefox profile to the newly created firefox user's home directory. If you skip this step, a new, clean profile will be created on first run.

    sudo mv /home/yourusername/.mozilla/firefox /var/lib/firefox
    sudo chown -R firefox:firefox $_/.mozilla/firefox
    
  4. Create a new shell script, ~/bin/firefox.sh (or possibly /usr/local/bin/firefox.sh). This script will be used in place of the real Firefox binary.

    cat > ~/bin/firefox.sh <<EOF
    #!/bin/bash
    
    export DISPLAY=:0.0
    
    sudo -u firefox -H /usr/bin/firefox $*
    EOF
    
    chmod 750 ~/bin/firefox.sh
    
  5. Grant your primayr user, yourusername, permission to run /usr/bin/firefox with your firefox user by appending the following line to /etc/sudoers (preferrably using /usr/sbin/visudo):

    yourusername       ALL=(firefox)           NOPASSWD:/usr/bin/firefox
    

    Check if sudo is configured to require a TTY. If so, you'll need to change it. Please ensure you understand what this change does and ensure it's within your risk tolerance:

    Defaults:yourusername    !requiretty
    
  6. Grant the user, firefox on localhost access to your X session. You only need to run this once per session, so you may with to put it in an X11 init script.

    /usr/bin/xhost +SI:localuser:firefox
    
  7. Finally, launch your new script as you regularly would.

    ~/bin/firefox
    

    You may choose to softlink firefox.sh as simply firefox. However, if you do this, ensure that your softlink shows up in your PATH before /usr/bin/firefox.

Considerations

There are a few things you'll need to keep in mind with this approach. Security and convenience are often opposite factors. When security increases, convenience often decreases. Finding the best trade between these two is a risk decision that only you can make.

Malice

This solution isn't fool-proof. Processes run as another user (specifically a super user) can still access your data. A trojaned application, crafty adversary, or a privilege-escalation vulnerability could thwart this technique.

File Access

Recall that the main purpose of this exercise was to protect your personal data from user-space executables. Of course, firefox now can't (or shouldn't be able to) access yourusername's home directory or files. Uploading files becomes difficult. Assuming you've understood this article to this point, I assume you can figure out a way around this. I use the /tmp mountpoint as a temporary shared directory (be sure noexec and nosuid are set).

Audio

To my understanding, most Linux distributions now use PulseAudio as the default supported audio mixer. PulseAudio uses a per-user daemon and output. I found no simple solution to merging the audio output of multiple users (consider YouTube videos). Funneling the sound to one user also broke when the daemon was restarted or another system user launched the same application (eg. when claws-mail launches firefox).

Initially, I had configured PulseAudio to act a system-wide mixer. Though this worked, eventual changes to Fedora (in the form of SELinux policies) had broken this functionality. Unfortunately, I didn't have the time to investigate. If I recall correctly, the Fedora bug was rejected as unsupported, in any case.

Alternatively, removing PulseAudio in favour of ALSA and OSS has been working well for several years.

Shared Live Data

Using xhost is more-or-less a blanket statement: you allow all access to your X11 session to a given user on a given host. When using a single-seat computer, as most workstations and laptops are, limiting access to specific users on localhost is likely sufficient. Even a multi-seat system of local, trusted users (roommates, spouses, etc.), shell access to a system user won't typically be required.

Still, if you grant the system users, firefox and clawsmail, for example, access to your X display, the two system users can access any shared X data: clipboard, application display, audio, etc. Realize, too, that all this X11 data stream is unencrypted. This approach doesn't attempt to solve either of these issues, and I'm not certain it could. This fits within my risk tolerance.

Alternatives

Though I have not tried, using X11Forwarding through SSH (possibly in combination with forced commands) may be another, simpler, alternative that further reduces the consequences listed above. If you try this, please let me know the outcome using the feedback form.