<!--
SPDX-FileCopyrightText: (c) 2026 Daniel Hast

SPDX-License-Identifier: Apache-2.0 OR MIT
-->

# bwrap-restricted

**bwrap-restricted** exposes a configurable, restricted subset of the interface
to Linux namespace functionality provided by [bubblewrap].

`bwrap-restricted` acts as a wrapper around the `bwrap` executable; it parses
the arguments to `bwrap`, scans them for forbidden options, and executes `bwrap`
with the given arguments only if no forbidden options are present. Additionally,
extra options can be inserted between the options and the command arguments.

[bubblewrap]: https://github.com/containers/bubblewrap

## Configuration

The configuration is read from a TOML file located at
`/etc/bwrap-restricted/config.toml`. There are three valid keys:

- `bwrap_path`: a string with the absolute path to the `bwrap` executable.
  Defaults to `/usr/bin/bwrap` if omitted.
- `forbidden_options`: a list of `bwrap` options that are forbidden and will
  cause `bwrap-restricted` to exit with an error if present. Defaults to an
  empty list if omitted.
- `extra_options`: a list of extra arguments that are inserted after the `bwrap`
  options and before the command arguments. Defaults to an empty list if omitted.

## Example

The following configuration file denies the ability to add capabilities in the
user namespace, forces all existing capabilities to be dropped, makes the
sandbox start in a new terminal session, and denies the ability to create nested
user namespaces:

```toml
forbidden_options = ["--cap-add"]
extra_options = ["--cap-drop", "ALL", "--new-session", "--disable-userns"]
```

Here are some examples with the above configuration:

```sh
# Running this command:
bwrap-restricted --ro-bind /usr /usr -- foo bar
# is equivalent to running:
/usr/bin/bwrap --ro-bind /usr /usr --cap-drop ALL --new-session --disable-userns -- foo bar

# This command is rejected with an error message:
bwrap-restricted --cap-add CAP_SYS_ADMIN -- foo bar

# --cap-drop is allowed, and the extra options are added afterward regardless:
bwrap-restricted --cap-drop CAP_SYS_ADMIN -- foo bar
# is equivalent to running:
/usr/bin/bwrap --cap-drop CAP_SYS_ADMIN --cap-drop ALL --new-session --disable-userns -- foo bar

# File descriptors passed to --args are scanned as well:
bwrap-restricted --args 4 foo bar
# will be rejected with an error message if the null-separated arguments in the
# file descriptor include the --cap-add option. Otherwise, it's equivalent to:
/usr/bin/bwrap --args 4 --cap-drop ALL --new-session --disable-userns foo bar
```

## Usage

If the system administrator wants to expose a restricted subset of user
namespace functionality to a given user or process, they can prevent directly
executing `bwrap` while allowing it to be executed via `bwrap-restricted`. For
example, on a system with SELinux, `bwrap-restricted` could be run in an SELinux
domain that's allowed to create user namespaces, while other domains are denied
permission to create user namespaces.

## Installation

An RPM spec is available in the `packaging` directory.

Alternatively, bwrap-restricted can be installed manually using Meson:

1. Clone this git repository.
2. Run `meson setup build -Dprefix=/usr` and `meson compile -C build` from the
   repository root.
3. Install the files by running `meson install -C build` as root.
