On Linux, smolvm's TSI allowlist DB patch crashes boot, so
force_allowlist is a no-op. This left the agent VM with full
host loopback access — a security regression from the macOS
behavior.
Fix: install guest-side iptables rules in _init_vm that ACCEPT
traffic to the bottle's allocated loopback alias (proxy_host/32)
and DROP all other 127.0.0.0/8 destinations. The agent runs as
non-root (node) and cannot flush the rules.
- Add iptables to claude and codex agent Dockerfiles
- Use DROP (not REJECT) — libkrun kernel lacks the REJECT module
- Skip on macOS where force_allowlist handles it natively
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three fixes for Linux smolvm support:
1. Skip force_allowlist DB patch on Linux — patching allowed_cidrs
into smolvm's state DB crashes TSI boot on Linux. Per-bottle CIDR
isolation is not enforced on Linux until smolvm fixes the
--allow-cidr + TSI interaction (known limitation).
2. Patch /etc/git-gate/ references in the staged entrypoint to
/bot-bottle-data/git-gate/ so git-daemon finds its hooks and
access-hook at the new consolidated mount path.
3. Drop explicit --net-backend tsi — the default on this smolvm
build is already TSI; explicitly requesting it is incompatible
with -p port mappings on Linux.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
libkrun limits total mounts + port-mappings to 5. With all three
sidecar daemons active (egress, git-gate, supervise), the prior
layout used 3 mounts + 3 ports = 6, causing the VM to crash at boot
with krun_start_enter returned -22.
Merge the egress confdir and git-gate scripts into a single staging
directory mounted at /bot-bottle-data/ with egress/ and git-gate/
subdirectories, reducing to 2 mounts + 3 ports = 5. Also clean up
leftover VMs before creating new ones to handle interrupted teardowns.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two issues caused krun_start_enter -22 (VM boot crash):
1. git-gate entrypoint missing at boot: sidecar_init.py starts all
daemons (including git-gate) immediately as PID 1. The entrypoint
was copied in via machine_cp which only runs after machine_start
returns — too late. virtiofs also can't mount files at root (/).
Fix: bake a static /git-gate-entrypoint.sh wrapper into the
Dockerfile.sidecars image that delegates to /etc/git-gate/entrypoint.sh.
For smolmachines, stage per-bottle scripts with correct in-VM names
under the git-gate state dir and virtiofs-mount to /etc/git-gate/ at
VM creation time. docker/macOS backends are unchanged (their file
bind-mount/docker cp still overrides the static wrapper).
2. Egress confdir mounted read-only: egress_entrypoint.sh writes
combined-trust.pem to confdir under set -e; mitmproxy also needs
to write its per-host cert cache there. Both fail fatally on a
read-only virtiofs mount.
Fix: change the egress confdir virtiofs mount to writable.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>