Skip to content

sandbox-utils/sandbox-run

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

sandbox-run: run command in a secure OS sandbox

Build status Language: shell / Bash Source lines of code Script size Issues Sponsors

Problem statement

Running other people's programs is insecure. Rogue dependencies* 🎯 or hacked library code 🏴‍☠️ (et cet. ⚠️) can wreak havoc, including access all your private parts** ‼️—think all current user's credentials and more personal bits like:

  • ~/.ssh,
  • ~/.pki/nssdb/,
  • ~/.mozilla/firefox/<profile>/key4.db,
  • ~/.mozilla/firefox/<profile>/formhistory.sqlite ...

✱ Running any Electron app relies on impeccability of hundreds or thousands of dependencies, NodeJS and Chromium to say the least! 😬

Solution

Run scary software in separate secure containers:

podman run -it -v .:/src -e PATH=/src debian:stable-slim scary-binary

or you can simply sandbox-run scary-binary which uses bubblewrap** (of Flatpak fame) under the hood.

Installation

There are no dependencies other than a POSIX shell with its standard set of utilities and bubblewrap. The installation process, as well as the script runtime, should behave similarly on all relevant compute platforms, including GNU/Linux and even Windos/WSL. 🤞

# Install the few, unlikely to be missing dependencies, e.g.
sudo apt install coreutils binutils bubblewrap

# Download the script and put it somewhere on PATH
curl -vL 'https://bit.ly/sandbox-run' | sudo tee /usr/local/bin/sandbox-run
sudo chmod +x /usr/local/bin/sandbox-run  # Mark executable

sandbox-run
# Usage: sandbox-run ARG...
sandbox-run ls /

Usage

Whenever you want to run a scary executable, simply run:

sandbox-run scary-app args

to run scary-app in a secure sandbox.

Extra Bubblewrap arguments

You can also pass additional bubblewrap arguments to individual process invocations via $BWRAP_ARGS environment variable. E.g.:

BWRAP_ARGS='--bind /opt /opt' \
    python -c 'import os; print(os.listdir("/opt"))'

For details, see bubblewrap --help or man 1 bwrap.

Note, .env file at project root is respected, and sourced for the sandbox environment.

See more specific examples below.

Filesystem mounts

The current working directory is mounted with read-write permissions**, while everything else is mounted read-only. In addition:

  • "$PWD/.sandbox-home" is bind-mounted as "$HOME",

To mount extra endpoints, use BWRAP_ARGS= with switches --bind or --bind-ro. Anything else not explicitly mounted by an extra CLI switch is lost upon container termination.

Linux Seccomp

See bwrap switches --seccomp FD and --add-seccomp-fd FD.

Runtime monitoring

If environment variable VERBOSE= is set to a non-empty value, the full bwrap command line is emitted to stderr before execution.

You can list bubblewraped processes using the command lsns or the following shell function:

list_bwrap () { lsns -u -W | { IFS= read header; echo "$header"; grep bwrap; }; }

list_bwrap  # Function call

You can run sandbox-run bash to spawn interactive shell inside the sandbox.

Environment variables

  • BWRAP_ARGS=– Extra arguments passed to bwrap process; space or line-delimited (if arguments such as paths themselves contain spaces).
  • VERBOSE=– Print full exec bwrap command line right before execution.

Debugging

To see what's failing, run the sandbox with something like strace -f -e '%file,%process' ....

Examples

To pass extra environment variables, other than those filtered by default, use bwrap --setenv, e.g.:

BWRAP_ARGS='--setenv OPENAI_API_KEY c4f3b4b3'  sandbox-run my-ai-prog
# or pass via .env (dotenv) file

To run the sandboxed process as superuser (while still retaining all the security functionality of the container sandbox), e.g. to open privileged ports, use args:

BWRAP_ARGS='--uid 0 --cap-add cap_net_bind_service' sandbox-run python -m http.server 80

To run GUI (X11) apps, some prior success was achieved using e.g.:

BWRAP_ARGS='--bind /tmp/.X11-unix/X0 /tmp/.X11-unix/X8 --setenv DISPLAY :8' \
    sandbox-run python -m tkinter

See more examples on the ArchWiki.

Contributing

You see a mistake—you fix it. Thanks!

Viable alternatives

See a few alternatives discussed over at sandbox-venv.