Skip to content

S47 OpenShell containment

Design of S47, moved from the roadmap. Status: Planned; the dependency is approved (D-116, D-118).

One authored policy: Maia authors, OpenShell enforces.

LayerOwnsEdited by
Maia policyExecution Profile, roles, guards, approvals, holds, ConnectionsA person, through preview, confirmation and receipt
OpenShell policyFilesystem, network, process and provider rules for one sandboxNobody: the Node generates it per Session
Kernel boundaryContainer or MicroVM, Landlock, seccompOpenShell
  • The Node compiles each Session's Maia policy into one OpenShell policy and records its digest in the launch receipt. Only the Node holds gateway admin credentials. A live policy that differs from that digest, whether changed by file, OpenShell CLI or gateway API, is drift: the Node stops the Session and never adopts it.
  • OpenShell's policy advisor is disabled. A network rule an agent proposes becomes a new Maia approval kind (a protocol entry beside S4b's command, patch, tool call and question approvals); a person's approval reaches the running sandbox through OpenShell's network hot reload. Filesystem and process rules are fixed at creation (both per OpenShell 0.1.5 documentation), so changing them relaunches the Session.
  • Vendor approval prompts stay, as Maia approvals. A vendor OS sandbox may stay as an inner layer generated from the same Maia policy, never a second authored one, until S47b proves OpenShell alone enforces its rules: Codex read denials need bubblewrap today (D-110), and Claude Bash auto-approval depends on the SDK sandbox (autoAllowBashIfSandboxed).
  • API keys and the Session credential reach a worker through OpenShell providers, injected into requests to approved endpoints, not as plain environment values or files. The sandbox reaches the loopback-bound Node only through an approved endpoint. The container runtime socket never reaches a sandbox. S20 holds and Connection disables revoke provider attachments.

Sub-slices. S47a: a pinned gateway and CLI in the Node runtime (S10, RL3), loopback only, Node-minted gateway credentials, telemetry off (on by default per the OpenShell README), one Effect adapter over the official OpenShell SDK at a pinned version (D-118), the policy compiler with golden tests per Execution Profile, and protocol, SDK, CLI and MCP exposure for the network approval kind, the receipt's policy digest, the containment error and a maia doctor runtime check. S47b: Codex and Claude Code in a pinned sandbox image, with the Session worktree and the Git directories it needs mounted, a Codex policy (OpenShell ships none), API-key and gateway Connections, approvals mapped, and today's launch limits (CPU, memory, process count, wall time) and cleanup proof carried by the sandbox; the Project setup command runs inside the sandbox before the first turn, with at most 3 attempts across launches and its last 64 KiB of output kept with the outcome (D-174). S47c: S23 Pi and Maia agent, S31–S34 harnesses and S21 processes; managed run_command and process tools open once the escape suite passes (execution profiles). R2 and every slice waiting for S47 need only S47a and S47b; each S47c integration ships with its executor slice. S47e: person-set allow, ask and deny rules on commands, tool calls and network hosts per Workspace, Project or Agent (E5), where deny beats ask and ask beats allow, lockable at Workspace scope, enforced by the sandbox and pushed to each harness's approval hooks (S13); every refusal names its rule and revision, and a model reviewer may flag or escalate, never approve. S47f, after S47b and S73c: a sandbox provider contract (create, exec, stream, file sync, network policy, destroy, usage) that Maia verified extensions implement for hosted sandbox services; an Agent or Routine step names its placement, the provider runs Maia's compiled policy with its Connection's credential, and the S47 escape suite passes on it before admission (D-116). S47d: delete the replaced native worker-containment machinery, the cooperative tier and the vendor sandbox profiles, then update the architecture, security and README docs. Keep the terminal/PTY and screen host (D-182); an agent terminal still runs inside its Session's containment. S47d and the mandatory switch wait for the subscription design below, unless the owner records that subscription Sessions end at S47d.

Entry conditions. No owner decision remains (D-116, D-118). S47a's own decision entry records the containment parts of D-015, D-018, D-019 and D-110 that it supersedes, the dependency reason, and the new capability ID and clean-host evidence that the execution-profile rule requires; the OpenShell release, gateway binary and sandbox image pinned by digest and past the 7-day minimum age that D-065 sets for packages; an install path for the official TypeScript SDK (D-118), since it is only on GitHub Packages (the npm package openshell is unrelated and never installed); and a design for subscription accounts, whose vendor subscription credential Maia never reads, stores or proxies (custody rule).

Acceptance. On Linux first, which unblocks SH2 on a Linux Node, then on macOS (Docker Desktop and MicroVM), the escape suite denies every filesystem, process, network, secret, resource and escape probe, including the S18a hostile-target probes retargeted to the sandbox's mounts. Network is denied by default: one approved host answers, a second is refused, and a person's approval reaches a running sandbox without a restart. Negative tests prove the advisor cannot approve a rule and a policy changed outside the Node stops its Session. No key, token or Session credential is readable inside a sandbox. A Node restart reconciles gateway sandbox records with Sessions, ends orphan sandboxes with a receipt and leaves no Session running without a sandbox. S7 runs at 8, 16 and 50 Sessions report sandbox start p95, memory per sandbox and Node CPU; caps rise only to measured levels. S47e: a denied command, tool call or host is refused in the sandbox and in the harness, an ask creates one approval, a Project rule never loosens a locked Workspace rule, and a model reviewer's approval is refused.

Known gaps (OpenShell 0.1.5 documentation). macOS needs Docker Desktop or the MicroVM driver; Linux needs Landlock ABI 3 (Linux 6.2) and recent seccomp features; Docker inside a sandbox, nested vendor sandboxes and subscription OAuth logins are not addressed; relayed TCP reports the relay as its peer; support covers the latest two minor releases; Windows is experimental.

Slices this changes. R2 qualifies OpenShell as its hard-containment adapter; S5's write profile and Claude Bash sandbox become OpenShell policy; the Linux process host in S7 (finding F1), S9 and S10 gives way to OpenShell on the VPS, and S10 and RL3 detect the container runtime or MicroVM prerequisite and refuse with a typed, actionable error when it is missing; the v1 vendor executor scope and S45 sign-in keep subscription accounts only through the subscription design; S15 and S16 attribute listeners and leased ports through sandbox port forwarding; S18a's read denial becomes an OpenShell filesystem rule; S18c, S24 and the executor harness rules move launch-environment credentials to providers and replace "Maia's host containment" with S47; S21, S23, S31–S34 and S45's endpoint containment launch through S47; and the unsandboxed local-operator-workspace class leaves the execution profiles.

Imported from Maia OS docs at 3dc3e07