Running other people's programs is insecure.
Rogue dependencies*
🎯 or hacked library code
🏴☠️ (et cet.
~/.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! 😬
Run scary software in separate secure containers:
podman run -it -v .:/src -e PATH=/src debian:stable-slim scary-binaryor you can simply
sandbox-run scary-binary
which uses bubblewrap** (of
Flatpak fame) under the hood.
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 /Whenever you want to run a scary executable, simply run:
sandbox-run scary-app argsto run scary-app in a secure sandbox.
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.
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.
See bwrap switches --seccomp FD and --add-seccomp-fd FD.
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 callYou can run sandbox-run bash to spawn interactive shell inside the sandbox.
BWRAP_ARGS=– Extra arguments passed tobwrapprocess; space or line-delimited (if arguments such as paths themselves contain spaces).VERBOSE=– Print fullexec bwrapcommand line right before execution.
To see what's failing, run the sandbox with something like strace -f -e '%file,%process' ....
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) fileTo 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 80To 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 tkinterSee more examples on the ArchWiki.
You see a mistake—you fix it. Thanks!
See a few alternatives discussed over at
sandbox-venv.