System-wide sandboxing framework - sandbox-app-launcher

Changing the seccomp filter to a whitelist definitely broke W^X somehow. I’ve no clue why it’s not working now.

1 Like

Nvm, I finally figured it out.

I’ve never been so happy to see my stuff breaking before.

1 Like
1 Like

madaidan via Whonix Forum:

You mean

10< <(getent passwd root ${app_user} nobody) \
11< <(getent group root ${app_user} nobody) \



Why are these an issue?

getent can fail such as on missing/broken /etc/passwd. Not clear if
subshell is covered by error handling, trap, probably not.

I don’t see any reason for a subshell.

varname="$(getent passwd root “${app_user}” nobody)"

It’s far cleaner than creating temp files.

No temp files required. Can be stored as a variable.

Would this be alright?

app_path="$(type -P "${app_name}" || true)"

Also, shouldn’t app_name be sanitized before setting app_path?

Yes, sanitize app_name before continuing anything else Then some error
case(s) cannot happen.

Why? I can’t find anything about that.

Indeed. I was wrong. Eval can be dangerous. Exec is OK.

The file path should be gotten via $PATH and not supplied.

That would break any scripts / programs which hardcode /path/to/program
which is very common. Absolute path support is very desirable.

Or should sandbox-app-launcher be limited to applications which are run
directly by the user?

I guess we can’t really sandbox /bin/cat as this is used by a ton of
scripts / programs. The realistic target for sandboxing is the “high
level” (abstraction wise, what the user knows) program?

Those are easily fixed with --ro-bind-try.


1 Like

Can Tor Browser be confined?

madaidan via Whonix Forum:

Unrelated, but should /var/log be accessible in the sandbox? Most important logs are root only anyhow due to filesystem permissions. /var/log is currently accessible but I’m not sure if we should remove it or make it a permission.

I guess for now high level applications are confined. These have no
business in /var/log. Can try without and see how that works.

1 Like
1 Like

bubblewrap cannot run applications that require root or the protection would be zero?

sandboxed-tor-browser (now deprecated) was using bubblewrap. The old source code might still be useful. The design documentation is probably still useful.



Yes. The current implementation of the sandbox does little to nothing to defend against Firefox doing evil things to or via the X socket.

If you want to attempt to mitigate this, the best options are:

Run 0.0.8-dev or newer, where "something, but not likely enough" is done to defend against some of the easier evil.
Use a nested X11 implementation like Xephyr or Xpra.
Sit there and pray that Wayland will fix everything. 

The ideal solution at current time is probably to probably do all three.

An advanced configuration option for setting the DISPLAY that Firefox will use is provided to enable easier nested X11 usage.

(Thanks to “Jann Horn of Google Project Zero” for pointing out that the documentation doesn’t make it obvious that such things are beyond the threat model.)

Nested X11 will probably have broken clipboard? Maybe xclipsync could solve that but that’s just piling up hacks. Could you please try to solve use XFCE with Wayland first? That would fix the issue at the root.


How do I get sound to work?

WARNING: This is likely unsafe against sophisticated adversaries.

As it stands right now, if PulseAudio is enabled in the sandbox, Firefox will get direct access to the host system’s socket. There are likely non-trivial ways to use this to read files from the host filesystem.

(Thanks to “Jann Horn of Google Project Zero” for pointing out that this is a possibility.)

If you don’t care about this possibility, assuming your system is running PulseAudio ( pulseaudio --check -v ), enable it via the sandbox config. PulseAudio is required due to the sandbox container not having direct access to hardware, and there being basically nothing better despite the potential escape vectors.

For what it’s worth, un-sandboxed Tor Browser also requires PulseAudio as of version 7.0, due to it being made a requirement for Firefox (See: ​https://bugzilla.mozilla.org/show_bug.cgi?id=1247056)

Some ideas for investigation…

Ask upstream?

Are containers any option? Init (systemd or …) can boot super fast inside a systemd-nspawn container.

https://people.kernel.org/brauner/runtimes-and-the-curse-of-the-privileged-container makes the argument that privileged containers (which doesn’t have a solid definition as he points out) cannot be made secure if root is running inside these.

Might be possible to run systemd-nspawn unprivileged. Kept some notes here, maybe it’s possible to run non-root applications securely in systemd-nspawn, maybe it could be combined with bubblewrap:


Or maybe it’s not needed. bublewrap might be able to run init too.

use bubblewrap as an unprivileged user to run systemd images

1 Like

Another issue with folder /shared is that it’s non-persistent by default in Qubes TemplateBased AppVMs since that is in the root image and [simplified] only /home is in private image. In other words, applications that would usually have their appdata persist since they write into the home folder will loose their data when using sandbox-app-launcher and writing to /shared. I would be worked around (bind-dirs using bind mounts) but that’s just more hacks to pile up.

Maybe /home/sandbox-app-launcher-appdata/shared and then make /shared a symlink to /home/sandbox-app-launcher-appdata/shared?

Creating symlink can be done using Debian packaging. Example:


file debian/sandbox-app-launcher.links

/home/sandbox-app-launcher-appdata/shared /shared

should do.

1 Like

It’s tricky due to the way it’s layed out but yes, it can be confined.

We shouldn’t expose root to apps at all.

I’m not good with DE stuff. I don’t think I’ll be able to solve it.

Containers wouldn’t give any benefit. They use the same technologies (chroot, namespaces, seccomp, capabilities etc.) so it’d be redundant.

That would be a great idea.

1 Like

PulseAudio is a big issue. It wasn’t created with access control in mind.


The PulseAudio socket shouldn’t be available in the sandbox anyway. I’m fine with keeping it that way but it might break some audio stuff (I don’t use PulseAudio so idk).

1 Like
1 Like
1 Like

Just tested it (sandbox-app-launcher bash is good for testing) and this is true:

pactl list

Connection failure: Connection refused
pa_context_connect() failed: Connection refused

Works fine outside of the sandbox.

1 Like

How would that be stored as a file descriptor?

Bubblewrap is failing with:

passwd="$(getent passwd root “${app_user}” nobody)"
group="$(getent group root “${app_user}” nobody)"
10< <${passwd}
11< <${group}
1 Like
1 Like

Similar syntax as this:

  12< ${seccomp_filter} \

  10< <(getent passwd root ${app_user} nobody) \


  10< "$varname" \


  10< "${varname}" \

That doesn’t work. It fails with an error:

nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin   11< root:x:0:   12< /var/cache/sandbox-app-launcher-autogenerated/seccomp-filter.bpf      /var/cache/sandbox-app-launcher-autogenerated/symlinks/bash : line 1: root:x:0:0:root:/root:/bin/bash: Permission denied
1 Like

Could be because of the double quotes / spaces / newline issue. The bash
-c part needs to be fixed first.

1 Like

That might be good since less complexity is always nice but not necessary since I just figured it out https://github.com/Whonix/sandbox-app-launcher/pull/28

The dbus-launch program from the dbus-x11 package can easily setup a D-Bus session bus for the user.

This way, processes in the same sandbox can communicate to each other via D-Bus but they can’t communicate with processes outside of the sandbox.

1 Like
[Imprint] [Privacy Policy] [Cookie Policy] [Terms of Use] [E-Sign Consent] [DMCA] [Contributors] [Investors] [Priority Support] [Professional Support]