Skip to content

Expose Codex's external-sandbox policy as a session mode so an already-sandboxed host avoids a nested macOS sandbox #671

Open

Description

@chenmingwei23

Summary

When codex-acp runs inside a host that already applies its own OS sandbox, there is no way to ask Codex not to apply a second one. On macOS this makes every command fail, because macOS refuses a Seatbelt sandbox nested inside an active Seatbelt sandbox.

Please expose Codex's external-sandbox sandbox policy as a selectable session mode (or config option), so a caller that is already the isolation boundary can tell Codex to enforce no OS sandbox of its own while keeping its approval policy unchanged.

Environment

  • @agentclientprotocol/codex-acp 2.2.2 (bundling @openai/codex 0.160.1)
  • macOS (any recent version)
  • The adapter launched by an outer process that itself wraps the child in a macOS Seatbelt sandbox (sandbox-exec).

What happens

Every ordinary command the agent runs fails immediately:

sandbox-exec: sandbox_apply: Operation not permitted
exit code: 71

Why

The mode config option is a combined approval-and-sandbox preset. Its four values map to these sandbox policies (src/AgentMode.ts):

mode approvalPolicy sandboxPolicy
read-only on-request readOnly
workspace-write on-request workspaceWrite
agent (Auto review) on-request workspaceWrite
agent-full-access never dangerFullAccess

On macOS, Codex enforces readOnly and workspaceWrite by running each command under /usr/bin/sandbox-exec with a generated Seatbelt profile. When the adapter is already running inside another process's Seatbelt sandbox, that second sandbox_apply is refused by the OS, and the command dies with exit 71.

Every approval-preserving mode (read-only, workspace-write, agent) applies a Seatbelt sandbox, so all of them hit this. The only mode that avoids the nested sandbox is agent-full-access, which also sets approvalPolicy: never and drops the approval boundary entirely — not an acceptable trade for a caller that wants to keep approvals.

Setting sandbox_mode = "external-sandbox" in the Codex config does not help here either: CodexAcpClient.sendPrompt passes the selected mode's sandboxPolicy to runTurn on every turn, and that per-turn policy overrides the startup/config value. There is no mode whose sandboxPolicy is externalSandbox, and the string external-sandbox does not appear in the adapter at all.

Requested change

Codex core already defines an external-sandbox policy: Codex applies no OS sandbox of its own and assumes the caller already sandboxed the process, while still tracking network access. Exposing it through the adapter — as a new session mode, or as a config option that sets sandboxPolicy to externalSandbox independently of the approval preset — would let a host that is already the isolation boundary run Codex on macOS with approvals intact and no nested sandbox.

A minimal shape would be an AgentMode whose approvalPolicy stays on-request (approvals preserved) and whose sandboxPolicy is { type: "externalSandbox" }, selectable the same way the existing modes are.

Workaround today

None that keeps approvals: the only non-nesting mode is agent-full-access, which disables approvals.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions