Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

sandbox-utils/sandbox-run

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
12 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 inherently 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 --rm -it -v "$PWD:$PWD" --net=host --workdir="$PWD" debian:stable-slim ./scary-binary

or you can simply sandbox-run scary-binary (e.g. sandbox-run npx @google/gemini-cli) which uses bubblewrap (of Flatpak fame) to spawn your native OS container under the hood, and, after downloading almost 500 MB ❗ of JavaScript sources, executes this untrusted third-party's Node/NPM package anonymously and securely, with its CWD in $PWD and new $HOME in $PWD/.sandbox-home.

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' \
    sandbox-run ./NVIDIA-Driver-Installer.run

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 required for a successful run (e.g. /usr) 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).
  • SANDBOX_RO_BIND=– List of additional path glob expressions to mount read-only inside the sandbox.
  • VERBOSE=– Print full exec bwrap command line right before execution.

Debugging

To see what's failing, run the sandbox with something like colorstrace -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!

Alternatives

See a few alternatives discussed over at sister project sandbox-venv.

Morty Proxy This is a proxified and sanitized view of the page, visit original site.