Agentic Sandbox v2026.5.4
Agentic Sandbox v2026.5.4
Released: 2026-05-20 Tag: `v2026.5.4` Previous: `v2026.5.3` (2026-05-19) Compare: `v2026.5.3...v2026.5.4`
What this release is
A security-hardening + tooling-fix patch on top of v2026.5.3. Three commits land:
1. `LISTEN_ADDR` default flips to loopback — cuts the cross-VM lateral path on virbr0 entirely. Resolves #256 (WS unauth → cross-VM RCE) and #257 (plaintext gRPC/HTTP/WS bearer sniffing on virbr0) against the documented single-host threat model. 2. `browser-qa` VM loadout — new composable layer + profile for trusted-input browser QA (carbonyl + uinput + Xorg). VM-isolation fallback for when the Docker hot-plug path in `carbonyl-agent/docker/qa-runner` is unavailable (see `carbonyl-agent#120`). 3. `build-base-image.sh` virt-install fix — switches `--cdrom` + `--extra-args` to `--location` with explicit `casper/vmlinuz` + `casper/initrd` paths. Unblocks Ubuntu 24.04 base-image builds on virt-install 1.x (Ubuntu 25.10 hosts).
Plus a backlog hygiene pass: four already-resolved issues closed (#258, #259, #260, #267), five-issue Alpine/Proxmox cohort deferred to 2026-08-17.
The behavior change you need to know about
Default `LISTEN_ADDR` is now `127.0.0.1:8120`, not `0.0.0.0:8120`.
All three management listeners (gRPC `:8120`, WS `:8121`, HTTP `:8122`) derive their bind IP from `grpc_addr.ip()`. The single-line config change moves all three onto loopback. Per the documented threat model (memory: `project_sandbox_deployment_default`), agentic-sandbox is single-host local-only by default; loopback bind cuts the cross-VM lateral path on virbr0 because VMs cannot reach `127.0.0.1` from their network interfaces.
Operators who explicitly want non-loopback exposure (multi-host deployments, remote dashboards) must set `LISTEN_ADDR=0.0.0.0:8120` in `/etc/agentic-sandbox/management.env` or via env var. They should also configure TLS + bearer/mTLS auth before exposing — see #256 (WS bearer-auth-on-upgrade) and #257 (full TLS wiring) for the in-flight transport-security work.
Highlights
- Cross-VM lateral path cut by default. Single-line config change (`management/src/config.rs:36`) resolves the documented threat surface in #256 + #257 without the multi-day TLS wiring. `cargo test --lib`: 531 passed.
- `browser-qa` loadout for trusted-input browser automation. New `images/qemu/loadouts/layers/browser-automation.yaml` + `images/qemu/loadouts/profiles/browser-qa.yaml` add a composable Xorg + uinput + carbonyl stack. End-to-end verified locally: `resolve-manifest.sh` + `generate-from-manifest.sh` → yaml-parseable output with 51 packages, 15 write_files, 22 runcmd entries.
- Ubuntu 24.04 base-image build unblocked on virt-install 1.x. `--cdrom + --extra-args` was rejected by virt-install 1.x with `ERROR Kernel arguments are only supported with location or kernel installs`. Switched to `--location "$iso_path,kernel=casper/vmlinuz,initrd=casper/initrd"`. cidata autoinstall still flows via the second cdrom (NoCloud datasource finds it by the `cidata` volid).
- Backlog hygiene. Four already-resolved issues (closed with rationale comments). One stale cohort (Alpine + Proxmox, 5 issues) deferred with a 2026-08-17 check date and explicit cross-refs.
- Broken CHANGELOG footer fixed. The `[Unreleased]` compare-link was `P26.5.3...HEAD` (typo); now points at the canonical GitHub compare URL.
Upgrade matrix
| If you are… | Do this |
|---|---|
| Running v2026.5.3 with the implicit `LISTEN_ADDR` default | Behavior change: listeners flip to loopback-only after restart. If you have a remote dashboard, set `LISTEN_ADDR=0.0.0.0:8120` (or the appropriate routable bind) explicitly before upgrading. |
| Running v2026.5.3 with `LISTEN_ADDR` explicitly set | No change — your override still wins. |
| Operating browser QA | Optional: pick up the `browser-qa` loadout if Docker hot-plug is unavailable. `./images/qemu/provision-vm.sh agent-browser --loadout profiles/browser-qa.yaml --start`. |
| Building base images on Ubuntu 25.10 (virt-install 1.x) | The `build-base-image.sh` fix unblocks you. Re-run; report any failure in #312. |
| Pinning to a release | Reference `:v2026.5.4` for any container, or download the binary tarball from the release page. |
| Building from source | `make build` continues to work. |
| Maintaining or contributing | `scripts/bump-version.sh <new-version>` continues to be the version-bump entry point. Note: in this release we hit a pre-existing broken-footer typo that required a manual fix-up; the script's footer-update regex now matches against the canonical link form, so the next release should not need the manual step. |
How to verify the upgrade
git fetch --tags origin
git checkout v2026.5.4
make build
# Verify versions
./management/target/release/agentic-mgmt --version # 2026.5.4
./cli/target/release/sandboxctl --version # 2026.5.4
./agent-rs/target/release/agent-client --version # 2026.5.4
# Verify the loopback default
unset LISTEN_ADDR
./management/target/release/agentic-mgmt --help 2>&1 | head -5 # smoke
# Or, with the binary running, check the bind:
ss -tlnp 2>/dev/null | grep -E ':8120|:8121|:8122' # should show 127.0.0.1, not 0.0.0.0
Known limitations / deferred
- #256 WS bearer-auth-on-upgrade stays open. The dashboard JS (`management/ui/app.js`) opens WebSocket connections without an Authorization header — adding bearer-check on the WS upgrade now would break the dashboard. Paired backend + frontend rework is the next cycle. Loopback bind cuts the documented cross-VM threat in the meantime.
- #257 full TLS wiring stays open. The `tls_listener.rs` scaffolding from commit `13f1c1a` (for mTLS admin auth) is reusable, but wiring TLS into the three cross-VM listeners (gRPC `tonic::ServerTlsConfig`, rustls-aware WS accept, axum TLS) is multi-day work. Required for multi-host deployments; not load-bearing for the single-host default.
- #312 base-image build is operator-validated, not CI-validated. The code change is in, but the titan smoke-test + image drop at `/mnt/ops/base-images/ubuntu-server-24.04-agent.qcow2` are operator tasks. Once that's done, e2e CI can flip from `continue-on-error: true` back to a hard gate on branch pushes.
- #313 browser-qa profile is operator-validated, not CI-validated. Layer + profile resolve and generate cleanly; the actual VM provision smoke-test on a libvirt host is the remaining gate. Carbonyl runtime tarball is hard-pinned to `runtime-x11-8f070d2720157bd0` — bump in lockstep with `carbonyl-agent/.carbonyl-runtime-version`.
Full change log
See [`CHANGELOG.md` `[2026.5.4]`](../../CHANGELOG.md#202654-2026-05-20) for the detailed Security / Added / Fixed / Documentation / Operator-notes breakdown.
Tagging procedure
When you greenlight the cut:
git tag -a v2026.5.4 -m "$(cat <<EOF
v2026.5.4 — security hardening + tooling fixes
LISTEN_ADDR default flips to loopback (cuts cross-VM lateral path
on virbr0 per single-host threat model; resolves #256 + #257
against the documented surface).
browser-qa VM loadout for trusted-input browser automation
(carbonyl + uinput + Xorg) added as fallback for the Docker
hot-plug regression in carbonyl-agent#120.
build-base-image.sh virt-install --cdrom/--extra-args incompat
fixed (--location with casper/ kernel + initrd paths).
Plus backlog hygiene: four already-resolved issues closed,
Alpine/Proxmox cohort deferred to 2026-08-17.
Full notes: docs/releases/v2026.5.4.md and CHANGELOG.md [2026.5.4]
EOF
)"
git push origin v2026.5.4