All Agent Engineering

Spec file

Codex sandbox, approvals and command network: check how the three switches combine

Separate sandbox_mode, approval_policy and network_proxy, and model domain-rule matching with an offline script.

AI Nav CityWritten / Updated

Codex limits commands in two layers: the sandbox mode decides what a command can technically do, such as where it can write and whether it can reach the network, and the approval policy decides when Codex must ask you first. Filtering network access by domain needs a third switch, network_proxy. They are independent, and the usual mistakes are assuming network_proxy by itself allows network access, or that domain rules are always enforced. This guide builds a combination checklist and a domain-rule model script from the official documentation. Codex was not started, no network was allowed or reached, and the model output cannot replace real product behavior.

Verified
· Not tested by us
Applies to
  • Codex Applies to local commands in the Codex CLI, IDE extension and desktop app. The page gives no unified version floor, and managed environments add administrator requirements.[1]
Tools

File locations

PathScopeHow it is read
~/.codex/config.tomlUser-level approval_policy, sandbox_mode, network and proxy settings.Read by Codex at startup; lower precedence than command-line flags, trusted project config and the selected profile.[2]
./.codex/config.tomlProject-level overrides, loaded only when you trust the project.Applied from the project root down to the current directory, the closest winning.[2]

When to use

  • You need to confirm whether commands can reach the network, which domains constrain them, or why approval prompts appear.[1]

When not to use

  • You need to constrain web search, MCP connections or model requests, none of which go through the command network proxy.[1]

Two layers: sandbox and approvals

  • The sandbox mode (sandbox_mode) decides what a command can technically do; the approval policy (approval_policy) decides when Codex must ask you first.
  • The Codex CLI and IDE extension default to no network access and write access limited to the active workspace. The workspace includes the current directory and temporary directories such as /tmp; use /status to see it.
  • Under the Auto preset (workspace-write plus on-request), reads, writes and commands inside the workspace proceed automatically, while editing outside the workspace or running a command that needs the network asks for approval first.
  • Under workspace-write, .git, .agents, .codex and .aws inside a writable root (when they are directories) remain read-only, and the protection is recursive.
  • The docs retired approval_policy = "untrusted". Left in user or project config, profiles, startup scripts or managed defaults it can stop the client from starting, so remove it and follow the migration section of the docs.

[1]

How network access and network_proxy combine

The docs say network_proxy changes how enabled network access is constrained and does not grant network access itself, and domain rules alone do not enable the proxy. With domains unset the behavior is allowlist-based, so no external destination is allowed until you add allow rules.[1]

Table: command network and network_proxy combinations (per the docs)
sandbox_workspace_write.network_accessfeatures.network_proxy.enabledResult stated in the docs
Off (default)OnNetwork stays off and the feature does nothing
OnOff or unsetNetwork on, unrestricted direct outbound access
OnOnNetwork on, outbound traffic constrained by the configured policy

[1]

Below is an original configuration sample that enables command networking and uses the proxy to limit outbound traffic to **.example.org while denying ads.example.org. I confirmed only that it parses as valid TOML with Python tomllib; Codex never read it.[1]

Example: original configuration sample; only TOML syntax was parsed and Codex did not read it
approval_policy = "on-request"
sandbox_mode = "workspace-write"

[sandbox_workspace_write]
network_access = true

[features.network_proxy]
enabled = true
domains = { "**.example.org" = "allow", "ads.example.org" = "deny" }

[1]

Domain matching and a model script

  • An exact host matches only itself.
  • *.example.com matches subdomains such as api.example.com but not example.com itself.
  • **.example.com matches both the apex and subdomains.
  • A bare * is a global allow that matches any public host that is not denied; the docs advise preferring narrower rules, and * is valid only in allow rules.
  • deny always wins over allow.

[1]

The script below implements only the matching rules above and the three switch combinations, with eight assertions. It does not decide what counts as a public host and does not model DNS or private-address checks, so its results are only useful for checking what a wildcard covers before you write the rule.[1]

Example: original modeling script, run offline and not the Codex network proxy
import assert from "node:assert/strict";

const match = (rule, host) => {
  if (rule === "*") return true; // docs: any public host; the public check is not simulated
  if (rule.startsWith("**.")) return host === rule.slice(3) || host.endsWith(rule.slice(2));
  if (rule.startsWith("*.")) return host.endsWith(rule.slice(1));
  return host === rule;
};

export function decide({ networkAccess, proxy, domains = {} }, host) {
  if (!networkAccess) return "blocked: command network is off";
  if (!proxy) return "allowed: direct, domain rules not enforced";
  const hit = want => Object.entries(domains).some(([rule, v]) => v === want && match(rule, host));
  if (hit("deny")) return "blocked: deny rule";
  if (hit("allow")) return "allowed: allow rule";
  return "blocked: no allow rule";
}

const domains = { "api.openai.com": "allow", "*.example.com": "allow", "evil.example.com": "deny" };
const on = { networkAccess: true, proxy: true, domains };
assert.match(decide({ networkAccess: false, proxy: true, domains }, "api.openai.com"), /^blocked/);
assert.match(decide({ networkAccess: true, proxy: false, domains }, "anything.test"), /^allowed: direct/);
assert.match(decide(on, "api.openai.com"), /^allowed/);
assert.match(decide(on, "a.example.com"), /^allowed/);
assert.match(decide(on, "example.com"), /^blocked/); // *.example.com excludes the apex
assert.match(decide(on, "evil.example.com"), /^blocked: deny/); // deny wins
assert.match(decide({ ...on, domains: { "**.example.com": "allow" } }, "example.com"), /^allowed/);
assert.match(decide({ ...on, domains: {} }, "api.openai.com"), /^blocked: no allow/);
console.log("net policy model: all assertions passed");

[1]

Table: model results for the sample rules above (script model, not Codex output)
HostModel resultReason
example.orgAllowed**.example.org also matches the apex
docs.example.orgAllowedThe subdomain hits the allow rule
ads.example.orgBlockeddeny wins over allow
other.testBlockedNo matching allow rule

[1]

What the proxy does not cover

  • Per the docs, the command network proxy filters scripts, programs and child processes running inside the local command sandbox. It does not filter web search, app or connector tool calls, MCP server connections, browser or Computer Use activity, cloud tasks, or the client's own model and authentication requests.
  • By default allow_local_binding = false blocks loopback, link-local and private-network destinations, and a hostname that resolves to a private address stays blocked even if it matches an allow rule. The docs say the DNS and IP classification check reduces DNS rebinding risk but does not eliminate it.
  • In managed environments administrators configure network requirements separately, and the docs advise testing both ordinary commands and approved sandbox escalations because an approved full escalation can bypass the command proxy.
  • The script models none of these. Web search has its own web_search setting, which reads from a cache by default and is not command networking.

[1]

Configuration precedence and scope

The documented order of precedence, highest first, is command-line flags and -c overrides, the .codex/config.toml of a trusted project, the profile selected with --profile, the user ~/.codex/config.toml, cloud-managed defaults, system config and built-in defaults. A one-off -c override therefore beats the file, and an administrator requirements.toml can forbid values such as approval_policy = "never". When network behavior differs from expectations, confirm the effective values with /status and the launch flags before changing rules. Only the official description was checked here: Codex was not started, no domain was allowed, no network was used and no plan or quota is certified.[1][2]

Sources

All links are official pages; verification dates are listed per source, and links point to the version checked.

  1. OpenAI · Agent approvals & security
  2. OpenAI · Config basics

Found an error? Tell us →