Bubblewrap/Examples - ArchWiki

Jump to content

# Bubblewrap/Examples

1 language

- 日本語

From ArchWiki
< Bubblewrap

## dhcpcd

Create a simple dhcpcd sandbox:

- Determine available kernel namespaces

    $ ls /proc/self/ns
    cgroup  ipc  mnt  net  pid  uts

Note: The absence of `user` indicates that the kernel has been built with `CONFIG_USER_NS=n` or is user namespace restricted.

- Bind as read-write the entire host `/` directory to `/` in the sandbox
- Mount a new devtmpfs filesystem to `/dev` in the sandbox
- Create new IPC and control group namespaces
- Create a new UTS namespace and set `dhcpcd` as the hostname

    # /usr/bin/bwrap --bind / / --dev /dev --unshare-ipc --unshare-cgroup --unshare-uts --hostname dhcpcd /usr/bin/dhcpcd -q -b

## Unbound

Create a more granular and complex Unbound sandbox:

- Bind as read-only the system `/usr` directory to `/usr` in the sandbox
- Create a symbolic link from the system `/usr/lib` directory to `/lib64` in the sandbox
- Bind as read-only the system `/etc` directory to `/etc` in the sandbox
- Create empty `/var` and `/run` directories within the sandbox
- Mount a new devtmpfs filesystem to `/dev` in the sandbox
- Create new IPC and PID and control group namespaces
- Create a new UTS namespace and set `unbound` as the hostname

    # /usr/bin/bwrap --ro-bind /usr /usr --symlink usr/lib /lib64 --ro-bind /etc /etc --dir /var --dir /run --dev /dev --unshare-ipc --unshare-pid --unshare-cgroup --unshare-uts --hostname unbound /usr/bin/unbound -d

Tip: See systemd#Editing provided units to enable the bubblewrapping of systemd unit files including `unbound.service`

## MuPDF

The factual accuracy of this article or section is disputed.

Reason: Forwarding the X11 socket may lead to a sandbox escape (Discuss in Talk:Bubblewrap/Examples)

The power and flexibility of bwrap is best revealed when used to create an environment within a shell wrapper:

- Bind as read-only the host `/usr/bin` directory to `/usr/bin` in the sandbox
- Bind as read-only the host `/usr/lib` directory to `/usr/lib` in the sandbox
- Create a symbolic link from the system `/usr/lib` directory to `/lib64` in the sandbox
- Create a tmpfs filesystem overlaying `/usr/lib/gcc` in the sandbox
  - This effectively blacklists the contents of `/usr/lib/gcc` from appearing in the sandbox
- Create a new tmpfs filesystem as the `$HOME` directory in the sandbox
- Bind as read-only an `.Xauthority` file and Documents directory into the sandbox
  - This effectively whitelists the `.Xauthority` file and Documents directory with recursion
- Create a new tmpfs filesystem as the `/tmp` directory in the sandbox
- Whitelist the X11 socket by binding it into the sandbox as read-only
- Clone and create private containers for all namespaces supported by the running kernel
  - If the kernel does not support non-privileged user namespaces, skip its creation and continue
- Do not place network components into a private namespace
  - This allows for network access to follow URI hyperlinks

    #!/bin/sh
    #~/bwrap/mupdf.sh
    (exec bwrap \
    --ro-bind /usr/bin /usr/bin \
    --ro-bind /usr/lib /usr/lib \
    --symlink usr/lib /lib64 \
    --tmpfs /usr/lib/gcc \
    --tmpfs $HOME \
    --ro-bind $HOME/.Xauthority $HOME/.Xauthority \
    --ro-bind $HOME/Documents $HOME/Documents \
    --tmpfs /tmp \
    --ro-bind /tmp/.X11-unix/X0 /tmp/.X11-unix/X0 \
     --unshare-all \
    --share-net \
    /usr/bin/mupdf "$@")

Tip: Execute a shell wrapper substituting the existing executable with /usr/bin/sh to debug and verify the contents and filesystem structure of the sandbox.

    $ bwrap \
    --ro-bind /usr/bin /usr/bin \
    --ro-bind /usr/lib /usr/lib \
    --symlink usr/lib /lib64 \
    --tmpfs /usr/lib/gcc \
    --tmpfs $HOME \
    --ro-bind $HOME/.Xauthority $HOME/.Xauthority \
    --ro-bind $HOME/Desktop $HOME/Desktop \
    --tmpfs /tmp \
    --ro-bind /tmp/.X11-unix/X0 /tmp/.X11-unix/X0 \
    --unshare-all \
    --share-net \
     /usr/bin/sh
    bash-4.4$ ls -AF
    .Xauthority  Documents/

Perhaps the most important rule to consider when building a bubblewrapped filesystem is that commands are executed in the order they appear. From the MuPDF example above:

- A tmpfs system is created followed by the bind mounting of an `.Xauthority` file and a Documents directory:

    --tmpfs $HOME \
    --ro-bind $HOME/.Xauthority $HOME/.Xauthority \
    --ro-bind $HOME/Documents $HOME/Documents \

    bash-4.4$ ls -a
    .  ..  .Xauthority  Desktop

- A tmpfs filesystem is created after the bind mounting of `.Xauthority` and overlays it so that only the Documents directory is visible within the sandbox:

    --ro-bind $HOME/.Xauthority $HOME/.Xauthority \
    --tmpfs $HOME \
    --ro-bind $HOME/Desktop $HOME/Desktop \

    bash-4.4$ ls -a
    .  ..  Desktop

## p7zip

Applications which have not yet been patched against known vulnerabilities constitute prime candidates for bubblewrapping:

- Bind as read-only the host `/usr/bin/7za` executable path to the sandbox
- Create a symbolic link from the system `/usr/lib` directory to `/lib64` in the sandbox
- Blacklist the sandboxed contents of `/usr/lib/modules` and `/usr/lib/systemd` with tmpfs overlays
- Mount a new devtmpfs filesystem to `/dev` in the sandbox
- Bind as read-write the host `/sandbox` directory to the `/sandbox` directory in the sandbox
  - 7za will only run in the host `/sandbox` directory and/or its subdirectories when called from the shell wrapper
- Create new cgroup/IPC/network/PID/UTS namespaces for the application and its processes
  - If the kernel does not support non-privileged user namespaces, skip its creation and continue
  - Creation of a new network namespace prevents the sandbox from obtaining network access
- Add a custom or an arbitrary hostname to the sandbox such as `p7zip`
- Unset the `XAUTHORITY` environment variable to hide the location of the X11 connection cookie
  - 7za does not need to connect to an X11 display server to function properly
- Start a new terminal session to prevent keyboard input from escaping the sandbox

    #!/bin/sh
    #~/bwrap/pz7ip.sh
    (exec bwrap \
    --ro-bind /usr/bin/7za /usr/bin/7za \
    --symlink usr/lib /lib64 \
    --tmpfs /usr/lib/modules \
    --tmpfs /usr/lib/systemd \
    --dev /dev \
    --bind /sandbox /sandbox \
    --unshare-all \
    --hostname p7zip \
    --unsetenv XAUTHORITY \
    --new-session \
    /usr/bin/7za "$@")

Note: /usr/bin/sh and /usr/bin/ls must reside in the executable path in order to traverse and verify the sandbox filesystem.

    bwrap \
    --ro-bind /usr/bin/7za /usr/bin/7za \
    --ro-bind /usr/bin/ls /usr/bin/ls \
    --ro-bind /usr/bin/sh /usr/bin/sh \
    --symlink usr/lib /lib64 \
    --tmpfs /usr/lib/modules \
    --tmpfs /usr/lib/systemd \
    --dev /dev \
    --bind /sandbox /sandbox \
    --unshare-all \
    --hostname p7zip \
    --unsetenv XAUTHORITY \
    --new-session \
    /usr/bin/sh
    bash: no job control in this shell
    bash-4.4$ ls -AF
    dev/  lib64@  usr/
    bash-4.4$ ls -l /usr/lib/modules
    total 0
    bash-4.4$ ls -l /usr/lib/systemd
    total 0
    bash-4.4$ ls -AF /dev
    console  full  null  ptmx@  pts/  random  shm/  stderr@  stdin@  stdout@  tty  urandom  zero
    bash-4.4$ ls -A /usr/bin
    7za  ls  sh

## Firefox

Network facing applications with large surface attack areas are also ideal candidates to be bubblewrapped:

- Transmission included in the sandbox to launch with magnet and torrent links
- Example wrap supports audio (PulseAudio) and printing (CUPS/Avahi) under GNOME (Wayland)
  - Paths in `~/.config/transmission/settings.json` should reflect the `--setenv HOME` variable
- Full paths are used to allow for keyboard bindings in environments which do not support variable expansion.
- WebRenderer and hardware (accelerated) compositing support included

     bwrap \
    --symlink usr/lib /lib \
    --symlink usr/lib64 /lib64 \
    --symlink usr/bin /bin \
    --symlink usr/bin /sbin \
    --ro-bind /usr/lib /usr/lib \
    --ro-bind /usr/lib64 /usr/lib64 \
    --ro-bind /usr/bin /usr/bin \
    --ro-bind /usr/lib/firefox /usr/lib/firefox \
    --ro-bind /usr/share/applications /usr/share/applications \
    --ro-bind /usr/share/gtk-3.0 /usr/share/gtk-3.0 \
    --ro-bind /usr/share/fontconfig /usr/share/fontconfig \
    --ro-bind /usr/share/icu /usr/share/icu \
    --ro-bind /usr/share/drirc.d /usr/share/drirc.d \
    --ro-bind /usr/share/fonts /usr/share/fonts \
    --ro-bind /usr/share/glib-2.0 /usr/share/glib-2.0 \
    --ro-bind /usr/share/glvnd /usr/share/glvnd \
    --ro-bind /usr/share/icons /usr/share/icons \
    --ro-bind /usr/share/libdrm /usr/share/libdrm \
    --ro-bind /usr/share/mime /usr/share/mime \
    --ro-bind /usr/share/X11/xkb /usr/share/X11/xkb \
    --ro-bind /usr/share/icons /usr/share/icons \
    --ro-bind /usr/share/mime /usr/share/mime \
    --ro-bind /etc/fonts /etc/fonts \
    --ro-bind /etc/resolv.conf /etc/resolv.conf \
    --ro-bind /usr/share/ca-certificates /usr/share/ca-certificates \
    --ro-bind /etc/ssl /etc/ssl \
    --ro-bind /etc/ca-certificates /etc/ca-certificates \
    --dir "$XDG_RUNTIME_DIR" \
    --ro-bind "$XDG_RUNTIME_DIR/pulse" "$XDG_RUNTIME_DIR/pulse" \
    --ro-bind "$XDG_RUNTIME_DIR/wayland-1" "$XDG_RUNTIME_DIR/wayland-1" \
    --dev /dev \
    --dev-bind /dev/dri /dev/dri \
    --ro-bind /sys/dev/char /sys/dev/char \
    --ro-bind /sys/devices/pci0000:00 /sys/devices/pci0000:00 \
    --proc /proc \
    --tmpfs /tmp \
    --bind /home/example/.mozilla /home/example/.mozilla \
    --bind /home/example/.config/transmission /home/example/.config/transmission \
    --bind /home/example/Downloads /home/example/Downloads \
    --setenv HOME /home/example \
    --setenv GTK_THEME Adwaita:dark \
    --setenv MOZ_ENABLE_WAYLAND 1 \
    --setenv PATH /usr/bin \
    --hostname RESTRICTED \
    --unshare-all \
    --share-net \
    --die-with-parent \
    --new-session \
    /usr/bin/firefox

### Enhancing privacy

- Further restrictions can be made by removing specific entries
  - Remove the following entry to remove audio support:

    --ro-bind "$XDG_RUNTIME_DIR/pulse" "$XDG_RUNTIME_DIR/pulse" \

- `/sandbox` represents an arbitrary location defined by the user to hold desired profile information
  - This allows for the use of a sanitized profile copied into `/sandbox` via a script/cron job or manually e.g.

    $ cp -pR ~/.mozilla /sandbox/

The location can be a network share, a USB mount, or a local filesystem or ramfs/tmpfs location

- Set `/home/r` to obscure the actual `/home/example`
- Set new user ID and group ID values

Note: Ensure that the selected UID and GID does not conflict with existing values listed in `/etc/passwd` and `/etc/groups`.

    bwrap \
    ....
    --bind /sandbox/.mozilla /home/r/.mozilla \
    --bind /sandbox/Downloads /home/r/Downloads \
    ...
    --setenv HOME /home/r \
    ...
    --uid 200 --gid 400 \
    ...
    /usr/bin/firefox --no-remote --private-window

## Chromium

A simple chromium sandbox on wayland and with pipewire:

    bwrap \
        --symlink usr/lib /lib \
        --symlink usr/lib64 /lib64 \
        --symlink usr/bin /bin \
        --symlink usr/bin /sbin \
        --ro-bind /usr/lib /usr/lib \
        --ro-bind /usr/lib64 /usr/lib64 \
        --ro-bind /usr/bin /usr/bin \
        --ro-bind /etc /etc \
        --ro-bind /usr/lib/chromium /usr/lib/chromium \
        --ro-bind /usr/share /usr/share \
        --dev /dev \
        --dev-bind /dev/dri /dev/dri \
        --proc /proc \
        --ro-bind /sys/dev/char /sys/dev/char \
        --ro-bind /sys/devices /sys/devices \
        --ro-bind /run/dbus /run/dbus \
        --dir "$XDG_RUNTIME_DIR" \
        --ro-bind "$XDG_RUNTIME_DIR/wayland-1" "$XDG_RUNTIME_DIR/wayland-1" \
        --ro-bind "$XDG_RUNTIME_DIR/pipewire-0" "$XDG_RUNTIME_DIR/pipewire-0" \
        --ro-bind "$XDG_RUNTIME_DIR/pulse" "$XDG_RUNTIME_DIR/pulse" \
        --tmpfs /tmp \
        --dir $HOME/.cache \
        --bind $HOME/.config/chromium $HOME/.config/chromium \
        --bind $HOME/Downloads $HOME/Downloads \
        /usr/bin/chromium --enable-features=UseOzonePlatform --ozone-platform=wayland

Warning: If you are using the linux-hardened kernel, you will not be able to use bubblewrap to sandbox chromium due to the `kernel.unprivileged_userns_clone` sysctl being set to 0. You can set it to 1, however, this is not recommended FS#36969.

One alternative solution is to have chromium use the namespace created by bubblewrap. This can be achieved through zypakAUR which is also used by flatpak to run electron based apps inside an additional namespace. Example code that demonstrates how to use zypak with chromium/electron can be found here

- PipeWire: `--ro-bind "$XDG_RUNTIME_DIR/pipewire-0" "$XDG_RUNTIME_DIR/pipewire-0" \`
  - If you are not using pipewire, feel free to remove this line
- `--bind $HOME/.config/chromium $HOME/.config/chromium \` mounts your chromium configuration directory in the sandbox as readable and writable
- `--bind $HOME/Downloads $HOME/Downloads \` mounts your ~/Downloads directory in the sandbox as readable and writable
- This example can be further improved for more isolation.

## Skype for Linux

The factual accuracy of this article or section is disputed.

Reason: Forwarding the X11 and/or DBus sockets may lead to a sandbox escape (Discuss in Talk:Bubblewrap/Examples)

The following example provides these features:

- `env -i` ensures that all environment variables are unset.
- Network is shared with the host (`--share-net`), `/etc/resolv.conf` is bind-mounted.
- Xorg access: bind the `/tmp/.X11-unix/X0` socket, set `$DISPLAY`.
- D-Bus: bind the `$XDG_RUNTIME_DIR/bus` socket, set `$DBUS_SESSION_BUS_ADDRESS`.
- Audio: bind the PulseAudio socket.
- Video: dev-bind the `/dev/video0` device.

The directory on the host where you want to keep the Skype profile can be configured with `$HOST_PROFILE_PATH`.

    env -i bwrap \
        --ro-bind /usr /usr \
        --dir /home/r \
        --dir /tmp \
        --dir /var \
        --dir "$XDG_RUNTIME_DIR" \
        --proc /proc \
        --dev /dev \
        --symlink usr/lib /lib \
        --symlink usr/lib64 /lib64 \
        --symlink usr/bin /bin \
        --symlink usr/sbin /sbin \
        --symlink ../tmp /var/tmp \
        --bind "$HOST_PROFILE_PATH" /home/r/.config/skypeforlinux \
        --ro-bind /etc/resolv.conf /etc/resolv.conf \
        --ro-bind /tmp/.X11-unix/X0 /tmp/.X11-unix/X0 \
        --ro-bind "$XDG_RUNTIME_DIR/bus" "$XDG_RUNTIME_DIR/bus" \
        --ro-bind "$XDG_RUNTIME_DIR/pulse" "$XDG_RUNTIME_DIR/pulse" \
        --dev-bind /dev/video0 /dev/video0 \
        --chdir / \
        --unshare-all \
        --share-net \
        --hostname RESTRICTED \
        --die-with-parent \
        --new-session \
        --setenv PATH /usr/bin \
        --setenv HOME /home/r \
        --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \
        --setenv DISPLAY "$DISPLAY" \
        --setenv DBUS_SESSION_BUS_ADDRESS "unix:path=$XDG_RUNTIME_DIR/bus" \
        /usr/bin/skypeforlinux

## Steam

The factual accuracy of this article or section is disputed.

Reason: Forwarding the X11 and/or DBus sockets may lead to a sandbox escape (Discuss in Talk:Bubblewrap/Examples)

A simple Steam sandbox

    #!/usr/bin/bash
    set -e

    STEAM_HOME="$HOME/.local/share/steam_sandbox"
    RUN_USER="$XDG_RUNTIME_DIR"

    mkdir -p "$STEAM_HOME"

    _bind() {
    	_bind_arg=$1
    	shift
    	for _path in "$@"; do
    		args+=("$_bind_arg" "$_path" "$_path")
    	done
    }

    bind() {
    	_bind --bind-try "$@"
    }

    robind() {
    	_bind --ro-bind-try "$@"
    }

    devbind() {
    	_bind --dev-bind-try "$@"
    }

    args=(
    	--tmpfs /tmp
    	--proc /proc
    	--dev /dev
    	--dir /etc
    	--dir /var
    	--dir "$RUN_USER"
    	--bind "$STEAM_HOME" "$HOME"
    	--dir "$HOME"
    	--dir "$XDG_CONFIG_HOME"
    	--dir "$XDG_CACHE_HOME"
    	--dir "$XDG_DATA_HOME"
    	--dir "$XDG_STATE_HOME"
    	--symlink /usr/lib /lib
    	--symlink /usr/lib /lib64
    	--symlink /usr/bin /bin
    	--symlink /usr/bin /sbin
    	--symlink /run /var/run
    	--setenv XAUTHORITY "$XAUTHORITY"
    )

    robind \
    	/usr \
    	/etc \
    	/opt \
    	/sys \
    	/var/empty \
    	/var/lib/alsa \
    	/var/lib/dbus \
    	"$RUN_USER/systemd/resolve"

    devbind \
    	/dev/dri \
    	/dev/nvidia* \
    	/dev/input \
    	/dev/uinput

    # steam
    bind \
    	"$XAUTHORITY" \
    	"$HOME/.local/bin/proton" \
    	"$HOME/.pki" \
    	"$HOME/.steam" \
    	"$HOME/.steampath" \
    	"$HOME/.steampid" \
    	"$HOME/Downloads" \
    	"$RUN_USER"/.mutter-X* \
    	"$RUN_USER"/ICE* \
    	"$RUN_USER"/dbus* \
    	"$RUN_USER"/gnome* \
    	"$RUN_USER"/pipewire* \
    	"$RUN_USER"/pulse* \
    	"$RUN_USER"/wayland* \
    	"$RUN_USER/at-spi" \
    	"$RUN_USER/bus" \
    	"$RUN_USER/dconf" \
    	"$RUN_USER/systemd" \
    	"$XDG_CACHE_HOME/mesa_shader_cache" \
    	"$XDG_CACHE_HOME/nv" \
    	"$XDG_CACHE_HOME/nvidia" \
    	"$XDG_CACHE_HOME/radv_builtin_shaders64" \
    	"$XDG_CONFIG_HOME/Epic" \
    	"$XDG_CONFIG_HOME/Loop_Hero" \
    	"$XDG_CONFIG_HOME/MangoHud" \
    	"$XDG_CONFIG_HOME/ModTheSpire" \
    	"$XDG_CONFIG_HOME/RogueLegacy" \
    	"$XDG_CONFIG_HOME/RogueLegacyStorageContainer" \
    	"$XDG_CONFIG_HOME/cef_user_data" \
    	"$XDG_CONFIG_HOME/proton" \
    	"$XDG_CONFIG_HOME/pulse" \
    	"$XDG_CONFIG_HOME/unity3d" \
    	"$XDG_DATA_HOME/3909/PapersPlease" \
    	"$XDG_DATA_HOME/Colossal Order" \
    	"$XDG_DATA_HOME/Dredmor" \
    	"$XDG_DATA_HOME/FasterThanLight" \
    	"$XDG_DATA_HOME/HotlineMiami" \
    	"$XDG_DATA_HOME/IntoTheBreach" \
    	"$XDG_DATA_HOME/Paradox Interactive" \
    	"$XDG_DATA_HOME/PillarsOfEternity" \
    	"$XDG_DATA_HOME/RogueLegacy" \
    	"$XDG_DATA_HOME/RogueLegacyStorageContainer" \
    	"$XDG_DATA_HOME/Steam" \
    	"$XDG_DATA_HOME/SuperHexagon" \
    	"$XDG_DATA_HOME/Terraria" \
    	"$XDG_DATA_HOME/applications" \
    	"$XDG_DATA_HOME/aspyr-media" \
    	"$XDG_DATA_HOME/bohemiainteractive" \
    	"$XDG_DATA_HOME/cdprojektred" \
    	"$XDG_DATA_HOME/feral-interactive" \
    	"$XDG_DATA_HOME/frictionalgames" \
    	"$XDG_DATA_HOME/icons" \
    	"$XDG_DATA_HOME/proton" \
    	"$XDG_DATA_HOME/vpltd" \
    	"$XDG_DATA_HOME/vulkan" \
    	"/var/lib/bluetooth" \
    	/run/systemd \
    	/tmp/.ICE-unix \
    	/tmp/.X11-unix

    exec bwrap "${args[@]}" /usr/lib/steam/steam "$@"

## NPM, Node Version Manager (NVM), Maven Java

In order to be able to run npm in a project root you can use the following command.

It works in combination with Angular, Cypress and Maven Java. X11 and wayland are on top included because Cypress starts a GUI based on electron.

It allows full file access to the current directory where it is run from. Assuming you execute `npm install` in the current project root where npm needs to write to `node_modules`, `package.json`, etc. Also access to global npm install directory and nvm is allowed (`npm -g install ...`). Furthermore X11 with cypress is also able to run and even wayland apps.

Note: The bindings to the directories zsh, maven, etc might differ from your setup.

    bwrap_arguments=(
        # no zombies
        --die-with-parent

        # network required for dependencies
        --unshare-all
        --share-net

        # create environment for a properly running shell
        --tmpfs /
        --tmpfs /run
        --dir /tmp
        --dev /dev
        --proc /proc
        --ro-bind /bin /bin
        --ro-bind /sbin /sbin
        --ro-bind /usr /usr
        --ro-bind /etc /etc
        --ro-bind /lib /lib
        --ro-bind /lib64 /lib64
        --ro-bind /sys /sys
        --ro-bind /var /var

        # systemd-resolve for dns
        --ro-bind /run/systemd/resolve /run/systemd/resolve

        # git is used by npm to init repos, config necessary for email username
        --ro-bind $XDG_CONFIG_HOME/git/config $XDG_CONFIG_HOME/git/config

        # zsh has to look everywhere cool
        --ro-bind $XDG_CONFIG_HOME/zsh/.zshrc $XDG_CONFIG_HOME/zsh/.zshrc
        --ro-bind $XDG_CONFIG_HOME/zsh/.zshenv $XDG_CONFIG_HOME/zsh/.zshenv
        --ro-bind $HOME/.zshenv $HOME/.zshenv

        # Maven
        --ro-bind /opt/maven /opt/maven
        --ro-bind $HOME/.m2 $HOME/.m2

        # NPM
        --bind "$XDG_DATA_HOME/npm" "$XDG_DATA_HOME/npm"

        # cache is needed by many programs like npm, cypress, nvm, maven
        --bind "$XDG_CACHE_HOME" "$XDG_CACHE_HOME"

        # x11, needed for cypress
        --ro-bind "$XAUTHORITY" "$XAUTHORITY"

        # wayland, might be useful
        --ro-bind "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY"

        # current dir is assumed to be project dir and full access is allowed
        --bind "$(pwd)" "$(pwd)"
    )

    # run bwrap with the arguments specified above and with the command provided by the user: zsh, npm install, etc
    $ bwrap "${bwrap_arguments[@]}" "$@"

Categories:

- Sandboxing
- Kernel

Hidden category:

- Pages or sections flagged with Template:Accuracy