Summary
Implement the mechanism defined in ADR-0030 (Host-Authoritative Sandbox Configuration): acq must not rely on guest-generated or guest-tamperable state to configure the sandbox. Because the in-sandbox agent has passwordless sudo, guest root-ownership is not a trust boundary against a prompt-injected agent. Every input acq trusts to make a configuration or lifecycle decision — data and code — must be host-resident and mounted read-only into the guest, or held on the host and injected at exec time.
This issue tracks the acq-side implementation and the staged migration of the existing /var/lib/acq/* markers off guest-writable paths. One PR, a commit per change below.
See docs/adr/0030-host-authoritative-sandbox-config.md (branch docs/adr-host-authoritative-config) for the principle, threat model, considered options (option 1 — mount kit code/data read-only and invoke code from the :ro path — selected), and the migration plan.
Background (why)
Today acq writes markers under the guest path /var/lib/acq/ via msb exec -u 0 and reads them back later to configure the sandbox. Four of them carry content acq acts on:
| Marker |
Read-back effect |
agent |
selects which binary the re-attach launches |
workspace |
sets the session working directory (-w) |
ssh-auth-sock |
sets -e SSH_AUTH_SOCK=… |
kit-env |
replays kit environment[] as -e NAME=value every session |
Reads are hardened against shell injection, but not against a sudo-capable guest setting a valid-but-malicious value. Four others (install-<cksum>, agent-installed-<agent>, agent-user-ready, oci-ready) are presence-only gates a guest can forge to suppress provisioning. Separately, acq's restart heal re-runs guest-resident kit startup code, which a sudo agent can tamper between restarts.
First external consumer: GSA-TTS/agentic-coding-patterns#423 ADR 0003 (neutral model-provider discovery) — its provider-facts channel needs the read-only mount this issue delivers.
Tasks (commit per change)
Constraints
- Preserve the current best-effort fail-soft behavior of the marker writes (
|| true): a state-dir hiccup must not turn a previously-survivable provision into a hard abort.
- No code execution on the host — acq reads static data from the pinned kit dir on the host; it does not execute kit-shipped code there.
- Do not remove passwordless sudo. This narrows what acq trusts, not what the agent can do in its sandbox.
- Add/extend bats coverage (offline stubbed) for the new host-config-dir +
:ro mount paths and for each migrated marker.
References
Summary
Implement the mechanism defined in ADR-0030 (Host-Authoritative Sandbox Configuration): acq must not rely on guest-generated or guest-tamperable state to configure the sandbox. Because the in-sandbox agent has passwordless sudo, guest root-ownership is not a trust boundary against a prompt-injected agent. Every input acq trusts to make a configuration or lifecycle decision — data and code — must be host-resident and mounted read-only into the guest, or held on the host and injected at exec time.
This issue tracks the acq-side implementation and the staged migration of the existing
/var/lib/acq/*markers off guest-writable paths. One PR, a commit per change below.See
docs/adr/0030-host-authoritative-sandbox-config.md(branchdocs/adr-host-authoritative-config) for the principle, threat model, considered options (option 1 — mount kit code/data read-only and invoke code from the:ropath — selected), and the migration plan.Background (why)
Today acq writes markers under the guest path
/var/lib/acq/viamsb exec -u 0and reads them back later to configure the sandbox. Four of them carry content acq acts on:agentworkspace-w)ssh-auth-sock-e SSH_AUTH_SOCK=…kit-envenvironment[]as-e NAME=valueevery sessionReads are hardened against shell injection, but not against a sudo-capable guest setting a valid-but-malicious value. Four others (
install-<cksum>,agent-installed-<agent>,agent-user-ready,oci-ready) are presence-only gates a guest can forge to suppress provisioning. Separately, acq's restart heal re-runs guest-resident kit startup code, which a sudo agent can tamper between restarts.First external consumer: GSA-TTS/agentic-coding-patterns#423 ADR 0003 (neutral model-provider discovery) — its provider-facts channel needs the read-only mount this issue delivers.
Tasks (commit per change)
:romount plumbing. Per-sandbox host config dir under${ACQ_STATE_DIR}/config/<backend>.<sandbox>.<sum>/(mirroring the existingclones//ports//provenance conventions inacq.backends/common.sh); mount it read-only into the guest at/var/lib/acq/host/on both backends (--volume host:guest:roon msb;:ropositional on sbx). Honor Windows host/guest path forms (ADR-0029).agent,workspace. acq authors these already — write to the host config dir; stop reading them back from the guest.ssh-auth-sock. acq already knows the value (its own constant) — hold host-side and inject at exec; stop reading it back.kit-env. acq already parses each kit'senvironment[]on the host at apply — persist the validated env to the host config dir and replay from there; stop reading the guest marker.install-*,agent-installed-*,agent-user-ready,oci-ready). Move to the host config dir so a guest cannot forge them to suppress provisioning.:roconfig dir and invoke it from there, so a restart executes the host-authoritative (pinned) copy, not a guest-tampered one.Constraints
|| true): a state-dir hiccup must not turn a previously-survivable provision into a hard abort.:romount paths and for each migrated marker.References
docs/adr/0030-host-authoritative-sandbox-config.md--script-pathreplay is inert; restart durability is acq's exec heal), ADR-0021 (ssh-auth-sock), ADR-0023 / ADR-0027 (:romounts), ADR-0029 (Windows path forms)GSA-TTS/agentic-coding-patternsADR 0003 / PR feat(acq): make --clone a neutral option, emulated on msb via a managed host-side scratch clone #423 (first consumer)