feat(image): ship bubblewrap and socat #48

Merged
claudiomaradonna merged 3 commits from feat/bubblewrap into master 2026-10-17 09:55:42 +02:00
Collaborator

Why

Tools inside an azkaban client container, such as Claude Code's own
sandbox or a script that wraps a command, had no way to isolate
folders: the images ship no bwrap, and Claude Code's sandbox also
needs socat. User namespaces already work in the containers, so only
the tools were missing.

What changed

  • Every client image now ships Ubuntu's bubblewrap and socat,
    installed in the base stage. Inside a container on Linux, a tool can
    bind folders read-only or writable, hide others, and unshare the
    network and process namespaces with bwrap.
  • The real-image smoke gate checks this in each image, run the way the
    launcher runs it: a bwrap jail with the container's /proc bound in
    must let a write to its scratch folder land and refuse a write to the
    home folder, and socat must run.
  • The README's new Nested sandboxes section covers what works, the
    refused fresh /proc mount, the sandbox.enableWeakerNestedSandbox
    setting Claude Code's sandbox needs here, and the limit set by the
    unfixed CVE-2026-87766 in Ubuntu 26.04's bwrap.
    docs/adding-a-client.md lists the new per-image check.

Non-goals: the launcher's container flags stay as they are, Codex's
sandbox stays off under its entrypoint, and macOS is unverified.

How to verify

  • make smoke-images on a host with real rootless Podman: each image
    passes the new bwrap probe and the run ends with "all three image
    targets passed".
  • In a launched client container: bwrap --ro-bind / / --dev-bind /dev /dev --bind /proc /proc --bind "$PWD" "$PWD" --unshare-all -- touch "$HOME/x" fails, while touching a file under $PWD works.
  • Already run on the tip:
    make lint && .agents/hooks/shellcheck.sh repo && make test passes.
    Each new or extended test fails on master's code. Not run:
    make smoke-images, since no real rootless Podman was available.

Considerations

The bwrap probe has not yet run against a real image, so the smoke gate
on real Podman is the first proof that bwrap works under the launcher's
flags on your hosts.

## Why Tools inside an azkaban client container, such as Claude Code's own sandbox or a script that wraps a command, had no way to isolate folders: the images ship no `bwrap`, and Claude Code's sandbox also needs `socat`. User namespaces already work in the containers, so only the tools were missing. ## What changed - Every client image now ships Ubuntu's `bubblewrap` and `socat`, installed in the base stage. Inside a container on Linux, a tool can bind folders read-only or writable, hide others, and unshare the network and process namespaces with `bwrap`. - The real-image smoke gate checks this in each image, run the way the launcher runs it: a bwrap jail with the container's `/proc` bound in must let a write to its scratch folder land and refuse a write to the home folder, and `socat` must run. - The README's new Nested sandboxes section covers what works, the refused fresh `/proc` mount, the `sandbox.enableWeakerNestedSandbox` setting Claude Code's sandbox needs here, and the limit set by the unfixed CVE-2026-87766 in Ubuntu 26.04's `bwrap`. `docs/adding-a-client.md` lists the new per-image check. Non-goals: the launcher's container flags stay as they are, Codex's sandbox stays off under its entrypoint, and macOS is unverified. ## How to verify - `make smoke-images` on a host with real rootless Podman: each image passes the new bwrap probe and the run ends with "all three image targets passed". - In a launched client container: `bwrap --ro-bind / / --dev-bind /dev /dev --bind /proc /proc --bind "$PWD" "$PWD" --unshare-all -- touch "$HOME/x"` fails, while touching a file under `$PWD` works. - Already run on the tip: `make lint && .agents/hooks/shellcheck.sh repo && make test` passes. Each new or extended test fails on master's code. Not run: `make smoke-images`, since no real rootless Podman was available. ## Considerations The bwrap probe has not yet run against a real image, so the smoke gate on real Podman is the first proof that bwrap works under the launcher's flags on your hosts.
Tools inside a client container, such as Claude Code's own sandbox,
need bwrap to isolate folders, and Claude Code's sandbox also needs
socat. User namespaces already work in the containers, so the base
stage now installs both from Ubuntu's archive.
The real-image gate now runs a bwrap jail as the launcher runs each
image, with the container's /proc bound in, and requires a write to a
bound scratch folder to land while a write to the home folder fails,
and socat to run. The guide to adding a client lists the new check.
Say that the images carry bubblewrap and socat, what a bwrap jail can
do inside a client container, that a fresh /proc mount is refused, and
which setting Claude Code's sandbox needs there.
motoko force-pushed feat/bubblewrap from 85855d47c9 to ddbe99d89c 2026-10-17 09:54:50 +02:00 Compare
claudiomaradonna deleted branch feat/bubblewrap 2026-10-17 09:55:46 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
claudiomaradonna/azkaban!48
No description provided.