warded director: snap-provided docker breaks inside cli-guard's namespace jail #540

Closed
opened 2026-07-03 02:38:21 +00:00 by coilyco-ops · 0 comments
Member

Symptom

warded director on kai-server dies at the surface launch:

error: unknown command "pull", see 'snap help'.
ward agent surface --driver claude: image pull failed (exit status 64); trying the local image
...
error: unknown flag `name'
exit status 64

Both snap-format errors. Every docker call in the surface path (image pull, run --name ...) breaks identically.

Root cause

On kai-server docker is snap-provided: /snap/bin/docker -> /usr/bin/snap. snap is a multiplexer keyed on argv[0]'s basename.

ward routes every subprocess (docker included) through cli-guard's namespace jail (the brew gate-reentry sandbox). Inside the jail's private mount namespace the /snap/bin/docker wrapper is masked and snap cannot resolve the docker app, so it falls back to running as ITSELF: snap pull ... / snap run --name ... -> usage error, exit 64.

Verified through the pinned cli-guard@v0.65.0 shell.Runner:

  • WITH the jail: docker version --format ... -> error: unknown flag \format'` (exit 64).
  • WITHOUT the jail (Sandbox=nil): -> 29.3.1, real docker.

docker spawns containers, not host brew, so it never needs the gate-reentry jail. Only brew is a wrapped tool (wardSandboxTools).

Fix (ward)

Route every ward docker exec/capture through a helper that suspends the sandbox for the call. Object-level unblock.

Meta-fix (cli-guard, follow-up)

cli-guard's jail collapses a snap-multiplexer symlink to /usr/bin/snap via EvalSymlinks and execs it, discarding the tool identity. Any snap-provided wrapped tool breaks the same way. installToolShim should preserve snap-multiplexer dispatch (stash /snap/bin/<tool>, keep argv[0] basename). Tracked separately upstream.

## Symptom `warded director` on kai-server dies at the surface launch: ``` error: unknown command "pull", see 'snap help'. ward agent surface --driver claude: image pull failed (exit status 64); trying the local image ... error: unknown flag `name' exit status 64 ``` Both `snap`-format errors. Every `docker` call in the surface path (image `pull`, `run --name ...`) breaks identically. ## Root cause On kai-server `docker` is snap-provided: `/snap/bin/docker -> /usr/bin/snap`. snap is a multiplexer keyed on `argv[0]`'s basename. ward routes every subprocess (docker included) through cli-guard's namespace jail (the brew gate-reentry sandbox). Inside the jail's private mount namespace the `/snap/bin/docker` wrapper is masked and snap cannot resolve the docker app, so it falls back to running as ITSELF: `snap pull ...` / `snap run --name ...` -> usage error, exit 64. Verified through the pinned `cli-guard@v0.65.0` `shell.Runner`: - WITH the jail: `docker version --format ...` -> `error: unknown flag \`format'` (exit 64). - WITHOUT the jail (Sandbox=nil): -> `29.3.1`, real docker. docker spawns containers, not host brew, so it never needs the gate-reentry jail. Only `brew` is a wrapped tool (`wardSandboxTools`). ## Fix (ward) Route every ward docker exec/capture through a helper that suspends the sandbox for the call. Object-level unblock. ## Meta-fix (cli-guard, follow-up) cli-guard's jail collapses a snap-multiplexer symlink to `/usr/bin/snap` via `EvalSymlinks` and execs it, discarding the tool identity. Any snap-provided wrapped tool breaks the same way. `installToolShim` should preserve snap-multiplexer dispatch (stash `/snap/bin/<tool>`, keep `argv[0]` basename). Tracked separately upstream.
Sign in to join this conversation.
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
coilyco-flight-deck/ward#540
No description provided.