GitHub - sandbox-utils/sandbox-run: πŸ”’πŸ§ Run command in a secure OS-native sandbox (0 deps) (original) (raw)

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:

✱ Running anyElectron apprelies 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 simplysandbox-run scary-binary(e.g. sandbox-run npx @google/gemini-cli) which uses bubblewrap (ofFlatpak 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 withits 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 evenWindos/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 fileat 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:

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 thecommand lsnsor 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

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 projectsandbox-venv.