Codex CLI Permissions and Sandbox Reference

Updated by

Independent reference, not affiliated with OpenAI. Tables are generated from the Codex CLI source at rust-v0.159.2 (v0.159.2). Official documentation: learn.chatgpt.com.

Codex CLI limits commands in two ways: a sandbox decides which files and network a command can reach, and an approval policy decides when Codex asks you first. The sandbox comes from legacy sandbox_mode or from permission profiles selected by default_permissions, with built-ins :read-only, :workspace and :danger-full-access. Administrators can lock both in requirements.toml.

What are Codex sandbox modes?#

sandbox_mode takes three values, each equivalent to a built-in permission profile. Only requirements.toml accepts a fourth value, external-sandbox.

sandbox_modeAccepted in
read-onlyconfig.toml, -s/--sandbox, requirements.toml
workspace-writeconfig.toml, -s/--sandbox, requirements.toml
danger-full-accessconfig.toml, -s/--sandbox, requirements.toml
external-sandboxrequirements.toml allowed_sandbox_modes only
ProfileSame as sandbox_modeFilesystemNetworkUsable in extends
:read-onlyread-only:root readoffyes
:workspaceworkspace-write:root read, :workspace_roots write, :slash_tmp write, :tmpdir writeoffyes
:danger-full-accessdanger-full-accessno sandboxunrestrictedno

:workspace reads everywhere and writes to the workspace roots (the working directory plus any --add-dir directories), /tmp and $TMPDIR, with network off. The legacy [sandbox_workspace_write] table tunes the same thing:

[sandbox_workspace_write] keyTypeDefaultNotes
exclude_slash_tmpbooleanfalse—
exclude_tmpdir_env_varbooleanfalse—
network_accessbooleanfalse—
writable_rootsstring[][]—

The sandbox is enforced by the operating system:

OSSandbox
macOSSeatbelt via /usr/bin/sandbox-exec
Linuxbubblewrap by default; Landlock with the use_legacy_landlock feature
Windowsselected with [windows] sandbox = elevated | unelevated | mxc

What approval policies does Codex support?#

approval_policyAliasAccepted inBehaviour
untrusted—rejected in config.tomlInternal policy for projects marked untrusted. Commands require approval unless an explicit exec policy rule allows them.
on-requeston-failureconfig.toml, -a/--ask-for-approvalThe model decides when to ask the user for approval.
granular—config.toml as { granular = { ... } }Fine-grained controls for individual approval flows.
never—config.toml, -a/--ask-for-approvalNever ask the user to approve commands. Failures are immediately returned to the model, and never escalated to the user for approval.

With no approval_policy set, Codex uses on-request, except for projects marked untrusted, which get the internal untrusted policy. granular answers each kind of prompt separately: true lets that kind reach you, false rejects it automatically without asking.

approval_policy = { granular = { sandbox_approval = true, rules = true, mcp_elicitations = false } }
KeyTypeDefaultNotes
mcp_elicitationsboolean—Whether to allow MCP elicitation prompts.
request_permissionsbooleanfalseWhether to allow prompts triggered by the `request_permissions` tool.
rulesboolean—Whether to allow prompts triggered by execpolicy `prompt` rules.
sandbox_approvalboolean—Whether to allow shell command approval requests, including inline `with_additional_permissions` and `require_escalated` requests.
skill_approvalbooleanfalseWhether to allow approval prompts triggered by skill script execution.

approvals_reviewer decides who answers an escalated request. auto_review sends it to a reviewer subagent instead of you; guardian_subagent is the legacy name for the same value.

approvals_reviewer
user
auto_review
guardian_subagent

What is the difference between sandbox mode and approval policy?#

The sandbox is the hard boundary: a command in :workspace cannot write outside the workspace roots whatever the model intends. The approval policy only governs what happens when a command needs more than the sandbox allows, or a rule asks for confirmation: on-request lets the model ask you, never returns the failure to the model without asking. never with :read-only gives an agent that can read but never change anything and never prompts.

How do Codex permission profiles work?#

A profile is a named [permissions.<name>] table, selected with default_permissions = "<name>". It can extends :read-only, :workspace or another profile of yours, then adds filesystem entries and network settings on top; child keys override the parent's. Names starting with : are reserved for built-ins, and :danger-full-access cannot be extended.

default_permissions = "dev"

[permissions.dev]
extends = ":workspace"
description = "Workspace write, one secret hidden, network on"

[permissions.dev.filesystem]
"/srv/secrets" = "deny"

[permissions.dev.network]
enabled = true

Filesystem values are read, write or deny (none is a legacy alias of deny). When two equally specific entries target the same path, deny beats write and write beats read. Besides absolute paths, entries accept these tokens; unknown :tokens are warned about and ignored, so a newer config still loads:

Path tokenAlias
:root—
:minimal—
:workspace_roots:project_roots
:tmpdir—
:slash_tmp—
[permissions.<name>] keyTypeDefaultNotes
descriptionstring——
extendsstring——
filesystemobject——
filesystem.glob_scan_max_depthinteger—Optional maximum depth for expanding unreadable glob patterns on platforms that snapshot glob matches before sandbox startup.
networkobject——
network.allow_local_bindingboolean—Permits local servers and direct host-loopback connections and skips the proxy's additional private-network destination checks. Proxy domain rules still apply. Defaults to true for MXC, which cannot enforce false; otherwise defaults to false.
network.allow_upstream_proxyboolean——
network.dangerously_allow_all_unix_socketsboolean——
network.dangerously_allow_non_loopback_proxyboolean——
network.domainsobject——
network.enable_socks5boolean——
network.enable_socks5_udpboolean——
network.enabledboolean——
network.mitmobject——
network.mitm.actionsobject——
network.mitm.hooksobject——
network.modelimited | full——
network.proxy_urlstring——
network.socks_urlstring——
network.unix_socketsobject——
workspace_rootsobject——

sandbox_mode or default_permissions: which one wins?#

Both keys still work in 0.159.2. Codex decides per session which model applies:

ConfigurationEffective permissions
-s/--sandbox on the command linelegacy sandbox_mode wins for this run
-c default_permissions=... on the command linepermission profiles win for this run
Both keys across config layersthe highest-precedence layer that sets either key decides; in the same layer default_permissions wins
Neither key set:workspace when the project has a trust decision, else :read-only (also :read-only on Windows with the sandbox disabled)
[sandbox_workspace_write] with profilesapplied to the implicit :workspace default only; an explicit default_permissions = ":workspace" ignores it
[permissions] defined, default_permissions unsetstartup error: "config defines `[permissions]` profiles but does not set `default_permissions`"
Profile name starting with :rejected: reserved for built-in profiles
approval_policy unseton-request, except the internal untrusted policy for projects marked untrusted

So with nothing configured, a trusted repository gets :workspace with on-request approvals, an untrusted one gets :workspace with untrusted approvals, and a directory with no trust decision gets :read-only.

Why are my Codex permissions locked by requirements.toml?#

requirements.toml is the administrator's file. Its allowed_* lists limit which values your config may choose, and a few keys such as default_permissions pin a value outright. It is read from the system location, enterprise cloud bundles and macOS managed preferences, never from your user or project config.

allowed_approval_policies = ["on-request"]
allowed_sandbox_modes = ["read-only", "workspace-write"]
requirements.toml keyTypeValuesAlias
allowed_approval_policieslist of AskForApprovaluntrusted, on-request, granular, never—
allowed_approvals_reviewerslist of ApprovalsRevieweruser, auto_review, guardian_subagent—
allowed_sandbox_modeslist of SandboxModeRequirementread-only, workspace-write, danger-full-access, external-sandbox—
allowed_permission_profilestable of boolean<profile id> = true | false—
default_permissionsstring——
permissionstable——
experimental_networktable——
allow_managed_hooks_onlyboolean——
rulestable——
featurestable—feature_requirements
SituationWhat Codex does
Configured value outside an allowed_* listfalls back to the required value with a startup warning "Configured value for `<field>` is disallowed by requirements"
approval_policy = "never" when danger-full-access is not allowedstartup error instead of a silent read-only session with approvals off
Profile not in allowed_permission_profilesshown as "Disabled by requirements" in the permissions picker
requirements.toml location/etc/codex/requirements.toml, %ProgramData%\OpenAI\Codex\requirements.toml on Windows, plus cloud bundles and macOS managed preferences

Is there a Codex equivalent of --dangerously-skip-permissions?#

Yes: --dangerously-bypass-approvals-and-sandbox, aliased --yolo. It runs every command without a sandbox and without asking, and is meant for environments that are already sandboxed from outside, such as a disposable container. --approve-for-me keeps the workspace-write sandbox and routes approval requests to the automatic reviewer instead of you.

FlagAliasHelp text
--sandbox, -s—Select the sandbox policy to use when executing model-generated shell commands.
--approve-for-me--not-so-yoloRoute approval requests through automatic review using the workspace-write sandbox.
--dangerously-bypass-approvals-and-sandbox--yoloSkip all confirmation prompts and execute commands without sandboxing. EXTREMELY DANGEROUS. Intended solely for running in environments that are externally sandboxed.
--dangerously-bypass-hook-trust—Run enabled hooks without requiring persisted hook trust for this invocation. DANGEROUS. Intended only for automation that already vets hook sources.
--add-dir—Additional directories that should be writable alongside the primary workspace.
--ask-for-approval, -a—Configure when the model requires human approval before executing a command.
FlagEquivalent to
--dangerously-bypass-approvals-and-sandboxsandbox danger-full-access + approval never
--approve-for-meapprovals_reviewer auto_review + approval on-request + sandbox workspace-write
--dangerously-bypass-hook-trustruns enabled hooks without review for this invocation

How do I allow network access in workspace-write?#

Network is off in :workspace and workspace-write by default. The switch depends on which permission model is active:

SettingEffect
[sandbox_workspace_write] network_access = truelegacy switch for workspace-write; default false
[permissions.<name>.network] enabled = trueprofile switch for sandbox network access; proxy settings in the profile do not start the managed proxy by themselves
[features] network_proxy = truestarts the managed network proxy for sandboxed sessions
:danger-full-access / danger-full-accessno sandbox, unrestricted network
KeyStageDefaultWhat it doesLegacy alias
exec_permission_approvalsunder developmentoffAllow exec tools to request additional permissions while staying sandboxed.request_permissions
request_permissions_toolunder developmentoffExpose the built-in request_permissions tool.—
use_legacy_landlockdeprecatedoffUse the legacy Landlock Linux sandbox fallback instead of the default bubblewrap pipeline.—
experimental_windows_sandboxremovedoffEnable Windows sandbox (restricted token) on Windows.enable_experimental_windows_sandbox
elevated_windows_sandboxremovedoffUse the elevated Windows sandbox pipeline (setup + runner).—
network_proxyexperimentaloffStart the managed network proxy for sandboxed sessions.—

Frequently asked questions#

What are Codex sandbox modes?#

read-only lets commands read files but not write them or use the network; workspace-write also lets them write inside the workspace roots, /tmp and $TMPDIR; danger-full-access removes the sandbox. They correspond to the built-in permission profiles :read-only, :workspace and :danger-full-access. Set one with sandbox_mode in config.toml or -s on the command line.

What is the difference between sandbox mode and approval policy?#

The sandbox limits what a command can touch; the approval policy decides whether Codex asks you when a command needs more. on-request lets the model ask for escalation, never sends failures straight back to the model, and granular accepts or rejects each prompt type separately. They combine: workspace-write with on-request is the usual interactive setup.

How do I stop Codex from always asking for approval?#

Set approval_policy = "never" (or run with -a never) to stop prompts while keeping the sandbox; blocked commands then fail back to the model. --approve-for-me hands prompts to an automatic reviewer and keeps workspace-write. Trusting the project also helps, because untrusted projects use the stricter internal untrusted policy. Only --yolo removes both prompts and sandbox.

Is there a Codex equivalent of --dangerously-skip-permissions?#

--dangerously-bypass-approvals-and-sandbox, also accepted as --yolo, is the equivalent: it sets danger-full-access and approval never for the run. The flag conflicts with -a in the interactive CLI. Use it only inside an environment that is sandboxed externally, because Codex then runs commands with your full user permissions.

Why are Codex permissions locked by requirements.toml?#

An administrator's requirements.toml (in /etc/codex/, %ProgramData%\OpenAI\Codex\, a cloud bundle or macOS managed preferences) restricts which approval policies, sandbox modes and permission profiles are allowed. A value outside the list falls back to an allowed one with a startup warning, and profiles it excludes show "Disabled by requirements". Only the administrator can change it.

How do I allow network access in Codex workspace-write mode?#

With the legacy model, set network_access = true under [sandbox_workspace_write]. With permission profiles, add [permissions.<name>.network] with enabled = true to the profile named in default_permissions. Note that an explicit default_permissions = ":workspace" ignores the legacy table, so the network switch must then live in a custom profile that extends :workspace.

Does default_permissions replace sandbox_mode?#

Not yet: both work in 0.159.2. When both are set, the highest-precedence config layer that sets either decides, default_permissions wins inside a single layer, and -s on the command line forces the legacy key for that run. Defining [permissions] profiles without default_permissions is a startup error.

Sources

Release-by-release changes: Codex CLI version tracker. All Codex CLI pages: Codex CLI reference index.