#!/bin/sh # sandbox-run: run command in a secure OS sandbox set -eu command -v bwrap >/dev/null || { command bwrap; echo 'Error: Missing /usr/bin/bwrap (apt install bubblewrap?)'; } # Support symlinks e.g. ./local/bin/npm -> /usr/bin/sandbox-run bin="$0" if [ "${bin##*/}" != 'sandbox-run' ]; then IFS=: for d in ${PATH:-/usr/local/bin:/usr/bin:/bin}; do p="$d/${0##*/}" [ "$0" != "$p" ] && [ -x "$p" ] && bin="$p" && break || true done unset IFS else if [ "$#" -eq 0 ] then echo "Usage: ${0##*/} ARG..."; exit 1 else bin="$(command -v "$1")"; shift fi fi uid="$(id -u)" cwd="$(pwd)" # Quote args with spaces. Do this here before overriding "$@" format_args () { for arg in "$bin" "$@"; do case "$arg" in $cwd/*) printf "%s " "${cwd##*/}/${arg#"$cwd/"}" ;; *\ *) printf "'%s' " "$arg" ;; *) printf "%s " "$arg" ;; esac; done } formatted_cmdline="$(format_args "$@")" warn () { echo "sandbox-run: $*" >&2; } lf=' ' split_args_by_lf () { printf '%s' "$1" | case "$1" in *$lf*) cat ;; *) tr ' ' '\n' ;; esac; } # RO-bind select paths paths=' /etc/alternatives /etc/resolv.conf /etc/ssl /etc/hosts /etc/pki /etc/pkcs11 /etc/ld.so.cache /etc/ld.so.conf.d /etc/localtime /etc/os-release /etc/timezone /lib /lib64 /run/dbus/system_bus_socket /usr ' # ld.so.conf.d: https://containertoolbx.org/doc/#ldconfig8 RW_paths=' /etc/ld.so.conf.d ' # Support BWRAP_ARGS passed to the process as well as via .env file prev_BWRAP_ARGS="${BWRAP_ARGS:-}" # Init env from dotenv file # shellcheck disable=SC2046 [ ! -e "$cwd/.env" ] || { . "$cwd/.env"; export $(grep -Pzo '(?m)^\w*(?==)' "$cwd/.env" | tr '\0' '\n'); } paths="$(split_args_by_lf "${SANDBOX_RO_BIND:-}" | tr ',' '\n') $paths" # Add paths from SANDBOX_RO_BIND IFS="$lf" # Split args only on newline # shellcheck disable=SC2046 set -- $(split_args_by_lf "${BWRAP_ARGS:-}") $(split_args_by_lf "${prev_BWRAP_ARGS:-}") "$bin" "$@" unset IFS home="$cwd/.sandbox-home" mkdir -p "$home/tmp" # Pass our own redacted copy of env # Expose all vars passed exclusively to this process (i.e. not its parent) IFS=$(printf '\037') for var in $(env -0 | grep -Ez -e '^('\ 'USER|LOGNAME|UID|PATH|TERM|HOSTNAME|'\ 'LANGUAGE|LANG|LC_.*?|TZ|'\ 'https?_proxy|HTTPS?_PROXY|'\ 'CC|CFLAGS|CXXFLAGS|CPPFLAGS|LDFLAGS|LDLIBS|MAKEFLAGS)=' \ -e "^($(env -0 | cut -z -d= -f1 | grep -Ezv "^($(cut -z -d= -f1