diff --git a/image/build.sh b/image/build.sh index ab6252e..2478b34 100755 --- a/image/build.sh +++ b/image/build.sh @@ -218,7 +218,7 @@ in_image() { stat_in_image "$1" | grep -q '^Inode:'; } # /sbin/init is what this image is: a userland whose first process is systemd, and what a # boot with `init=/sbin/init` lands on. /bin/sh is what `spin-machine boot --init /bin/sh` runs. -for f in /sbin/init /bin/sh /bin/bash /usr/bin/docker /usr/local/bin/task; do +for f in /sbin/init /bin/sh /bin/bash /usr/bin/docker /usr/local/bin/task /usr/bin/bwrap /usr/bin/socat /usr/bin/rg; do in_image "$f" || { echo "ERROR: the image has no $f" >&2; exit 1; } done diff --git a/image/mkosi.conf b/image/mkosi.conf index 35b2bff..75a29f3 100644 --- a/image/mkosi.conf +++ b/image/mkosi.conf @@ -116,6 +116,16 @@ Packages= less strace btop + # What the coding agents a workspace runs sandbox their commands with: Codex's Linux + # sandbox and Claude Code's (sandbox-runtime) are both bwrap plus seccomp, and neither + # uses Landlock (#221, checked in their source 2026-11-12). Codex carries a bwrap of its + # own; sandbox-runtime refuses to start without bwrap and socat on PATH, socat being its + # network proxy out of the sandbox. ripgrep is how it finds the .git/hooks and editor + # configs below the working directory to mount read-only: without rg the scan fails, it + # logs at debug level, and the command runs without those denies. + bubblewrap + socat + ripgrep # file, because scripts branch on what it says and a `command not found` in that # position reads as the archive being wrong rather than the tool being absent. file