Skip to content

Console sandbox drift

Symptom

A Claude Code session on Console fails to write /etc/systemd/system/..., run systemctl --user, or call loginctl enable-linger — but a different Claude session on the same VM, same user, can do all three. EROFS on /etc. "No medium found" on the user DBUS bus.

Root cause

forge-remote-bridge.service ships with ProtectSystem=strict + ReadWritePaths=/home/justinwieb/forge .... systemd creates a private mount namespace for the unit, with /etc bind-mounted read-only. Tmux servers spawned by the bridge inherit that namespace; tmux daemonizes (reparents to PID 1) but the namespace persists for as long as any attached process lives. Every Claude session that attaches to those tmux sockets (/spawn, /resume, remote-bridge-driven, coordinator brain spawn_remote_session) inherits the trapped namespace.

forge-tmux-anchor.service has no sandbox directives, so its tmux is in the host namespace (/proc/1/ns/mnt) and its Claudes can write /etc.

Diagnostic

readlink /proc/self/ns/mnt        # this session's mount ns
readlink /proc/1/ns/mnt           # host ns
# If they differ -> trapped.
grep ' /etc ' /proc/self/mountinfo  # 'ro,relatime' confirms

Why claude's sandbox setting doesn't help

~/.claude/settings.json has sandbox.enabled:false. That controls a Claude-Code-side sandbox; the trap here is systemd-side and happens before claude exec.

Why earlier loosen-spawn.conf didn't help

It set ProtectSystem=full. Per systemd: full still bind-mounts /etc read-only. Required value is no, plus ReadWritePaths= cleared (any non-empty ReadWritePaths= alone forces a private mount namespace).

Fix

forge/infra/systemd/forge-remote-bridge.service.d/loosen-spawn.confProtectSystem=no, ProtectHome=no, ReadWritePaths=, NoNewPrivileges=false. Install with sudo install, daemon-reload, restart bridge, kill stale tmux servers. Theatrical-only loss; bridge already runs --dangerously-skip-permissions + full sudo.

Eval check candidate

Pre-commit / nightly: assert readlink /proc/self/ns/mnt == readlink /proc/1/ns/mnt for the running coordinator + remote-bridge processes. Fail loud if drift returns.

See also

  • memory/handoffs/console-sandbox-drift-2026-05-04.md — incident timeline and apply steps
  • feedback_no_permission_deny_lists.md — sandboxing in this fleet is intentionally light