Skip to content

fix(trial): confine the escape surface — environment, host sockets, /proc, IPC, session, and the shell's authority - #807

Merged
rodrigoteamx merged 1 commit into
mainfrom
fix/confine-escape-surface
Oct 14, 2026
Merged

rodrigoteamx merged 1 commit into
mainfrom
fix/confine-escape-surface

Conversation

@rodrigoteamx

Copy link
Copy Markdown
Contributor

Confines the trial/leg escape surface so agent-authored code running under bubblewrap can no longer read authority or credentials it was never granted. Each leg only ADDS refusals; the published confinement's denials all still hold, and no legitimate leg breaks (a trial still runs, non-authority files stay readable, off-list sockets stay reachable, /proc/self stays readable, terminal/MCP keep confining).

  • Environment (TrialRunner::environmentFloor): --clearenv + an exact allowlist (PATH HOME TMPDIR LANG LC_ALL MILPA_TRIAL). Confined code no longer reads the launcher's MILPA_AGENT_BASIC_AUTH or any third-party *_KEY/*_TOKEN via getenv.
  • Host sockets (maskArgs/hostSocketPaths): the path AF_UNIX sockets whose connect is authority on the host are overlaid with /dev/null — Docker, the ssh-agent (launcher SSH_AUTH_SOCK read before --clearenv, plus the gnome-keyring gcr/ssh and keyring/ssh defaults), dbus (system + session), systemd/private, wayland/X11 (by glob), pipewire, pulse. Masked only when the user could open it (is_writable), so a root-only socket is left alone and a connect to the masked path is refused (ECONNREFUSED).
  • /proc (--proc /proc): a private procfs so other processes' command lines are no longer readable.
  • IPC + session (NAMESPACES): --unshare-ipc (own SysV/POSIX-shm namespace) and --new-session (no controlling TTY).
  • Non-bearer state (SecretFiles::NON_BEARER_STATE): the enrollment ledger, token-hash store, capabilities declaration and the agent session log are masked from confined code (the bearer stores already were).
  • The shell's authority (Console/Application::pantallaDelShell): the coa shell form now runs an operation with the session token's ToolContext, as the terminal does, so a finite principal's authoring op is confined instead of running in the house as the local wildcard.

Reviewed independently with execution of the escape surface (0/0/0). The socket and env allowlists are hand-maintained; a non-standard DOCKER_HOST or an ssh-agent outside the default must be added to the list at deployment.

… conditional /proc, IPC, session, and the shell's authority

/proc is masked in a normal container, where bwrap cannot mount a fresh procfs and forcing it fails the whole confinement — no trial booted in the :dev image. TrialRunner now probes once whether a procfs mounts under the confining shape and adds --proc /proc only when it can; in a container the container's own pid namespace already hides the host's processes, so the end holds without the flag.
@rodrigoteamx
rodrigoteamx force-pushed the fix/confine-escape-surface branch from 53a7021 to 0c186e1 Compare October 14, 2026 03:13
@rodrigoteamx
rodrigoteamx merged commit cb6e728 into main Oct 14, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant