ASK KNOX
beta
LESSON 530

Approvals, Sandboxing, and Safety

Codex autonomy is set by two independent dials — an approval policy and a sandbox mode — learn the blast-radius mental model that lets you choose the right combination.

9 min read·Getting Started with OpenAI Codex

The Permission Problem

Every AI coding agent faces the same tension. On one side: you want the agent to move fast, apply changes, run commands, and get things done without constant interruption. On the other: an agent operating without guardrails on an unfamiliar codebase is a liability. One wrong command can delete a directory, corrupt a config, or send credentials to an unintended endpoint.

Codex resolves this tension with two independent controls rather than one combined "mode." Your job as an operator is to set each dial to match what the task actually requires — not to minimize friction, and not to maximize control. The right answer depends on the reversibility of the actions involved.

Two Dials, Not Three Modes

Codex separates autonomy into two orthogonal axes that work together:

  • approval_policywhen Codex must stop and ask you before it acts. Values: untrusted (ask before almost everything), on-request (Codex acts within its allowed scope and asks when it needs to step outside it), and never (do not interrupt — pair only with a constraining sandbox).
  • sandbox_modewhat Codex is technically allowed to do, enforced by the OS. Values: read-only (read files, no writes, no commands), workspace-write (read, edit within the workspace, and run routine local commands inside that boundary), and danger-full-access (no filesystem or network boundary at all).

The two dials are independent: an approval policy works with any sandbox mode. That is the whole point — you decide when to be interrupted separately from what the agent can touch.

The CLI ships named presets that are just convenient points on this grid:

  • Read Only = sandbox_mode: read-only + approval_policy: on-request. Codex reads and proposes, but cannot write or run commands without your say-so. This is the setting for unfamiliar codebases, sensitive configurations, and any situation where you want a review step before changes land.
  • Auto = sandbox_mode: workspace-write + approval_policy: on-request. Codex can read, edit files inside the workspace, and run routine commands inside that boundary automatically, but it asks for approval to write outside the workspace or to reach the network. This is the low-friction default for trusted local work — refactoring, code generation, scaffolding.
  • Full Access = sandbox_mode: danger-full-access + approval_policy: never. No boundaries and no interruptions. Reserve this for genuinely isolated, disposable environments (a throwaway container in CI), never on a machine that can reach production.

A practical note on the older vocabulary: tutorials and earlier releases talked about "full-auto" and "auto-edit" as if they were single modes. The current model is the two-dial grid above; --full-auto survives only as a deprecated compatibility shorthand. When you reach for autonomy, set the two dials explicitly.

The Blast-Radius Mental Model

Think of it as two dials, not a switch. The question is never "do I trust Codex?" — the question is "what is the worst thing that can happen if Codex makes an error, and is that acceptable given the task at hand?"

For a test scaffold in an isolated container: the Full Access preset (danger-full-access + never). Worst case, you delete the container and start over.

For an edit to a production secrets file: the Read Only preset (read-only + on-request). Every change gets your eyes before it lands.

For a large refactor in a known codebase: the Auto preset (workspace-write + on-request). File changes apply inside the workspace; Codex still asks before reaching outside it or running networked commands.

The blast-radius model is why Knox's systems use explicit kill switches and approval gates at every layer. When you read about asyncio.wait_for timeouts in every trading coroutine or the operator approval queue in Codex sessions — that is the same principle applied at different scales. Autonomy without a ceiling is a liability. jeremyknox.ai/deep-dives has a full breakdown of how kill-switch discipline compounds over time in autonomous systems.

How the Sandbox Works

The sandbox is not a software promise — it is kernel enforcement. On macOS, Codex uses Apple Seatbelt (sandbox-exec) to define a profile that restricts which filesystem paths and system calls the process can touch. On Linux, it uses landlock for filesystem path rules combined with seccomp for syscall allowlisting. These are not policies Codex can override — they are OS-level constraints.

What this means practically:

Filesystem writes are locked to the project working directory and designated temp paths, with protected paths (like .git and .codex) carved out even inside writable roots. Under workspace-write the agent cannot write to ~/.ssh/config or modify files outside the project tree. Note that this bounds writes and commands, not reads: by default the sandbox lets Codex read broadly (it can still read a file like /etc/hosts), so do not rely on the sandbox alone to keep secrets outside the repo unreadable. Confining reads is a separate opt-in (restricted read access) you enable deliberately.

Network is off by default under workspace-write. This is the key safety property. A sandboxed Codex session running your test suite cannot phone home, cannot exfiltrate code, and cannot call external APIs unless you explicitly grant network access (or move to danger-full-access). The sandbox enforces this, not just Codex's prompt.

Commands run inside the boundary. When Codex runs npm test or python -m pytest, those processes are also subject to the sandbox constraints. A test that tries to make an HTTP call to an external service will fail — the sandbox blocks the connection.

Applying the Model: Common Scenarios

Scenario 1 — Unfamiliar legacy codebase Use the Read Only preset (read-only + on-request). You want every proposed change reviewed before it lands. The blast radius of unknown code is unknown.

Scenario 2 — Generating tests for a new module Use the Auto preset (workspace-write + on-request). You know the scope (the new module), the changes are additive, and a wrong test file is easy to delete and regenerate.

Scenario 3 — Running a build pipeline in CI The Full Access preset (danger-full-access + never) is acceptable only because the CI environment is isolated and the build artifacts are disposable, and speed matters more than human checkpoints. On any non-disposable machine, prefer workspace-write with the sandbox active.

Scenario 4 — Editing a multi-service deployment config Read Only (read-only + on-request), always. Deployment configs touch production. Every edit needs your eyes. The blast radius of a misconfiguration in Kubernetes or Docker Compose is not recoverable in seconds.

The Irreversibility Test

When in doubt, ask: "If Codex makes a mistake in this mode, can I recover in under 60 seconds?" If yes, the mode is probably fine. If no — if the action persists somewhere you cannot easily undo, modifies data you cannot restore, or touches systems beyond your immediate control — drop to a more conservative mode.

This is not about Codex's reliability. It is about the blast radius of being wrong. Even a 99% reliable system will be wrong 1% of the time. The approval mode determines what that 1% looks like.