Files
codex/docs/network-proxy-design.md
2025-12-21 12:03:20 -08:00

4.7 KiB

Codex Network Proxy Design

This document describes the Codex network proxy that runs outside the sandbox and enforces an allow-only network policy for sandboxed subprocesses. The proxy is a single binary with HTTP proxying, SOCKS5, and an admin API. Codex owns the policy state in ~/.codex/config.toml; the proxy reads that configuration and applies it at the network edge.

Goals

  1. Enforce allow-only network access with denylist precedence.
  2. Support wildcard domain patterns, including apex match for *.domain.tld.
  3. Allow two modes: limited (read-only) and full (all methods).
  4. Provide optional MITM to enforce read-only on HTTPS.
  5. Allow hot-reloaded configuration via admin API.
  6. Provide clear audit logging of allow/deny decisions and policy changes.
  7. Enable a single binary with HTTP proxy, SOCKS5 proxy, and admin API.

Non-Goals

  • Enterprise policy distribution or centralized multi-tenant orchestration.
  • Deep packet inspection beyond the supported HTTP/HTTPS interception modes.
  • Perfect protocol coverage for all network traffic types.

Architecture

flowchart LR
  subgraph Sandbox["Codex (sandboxed)"]
    Tools["commands / tools<br/>curl, git, python"]
    SocksClients["SOCKS clients"]
  end

  subgraph Proxy["codex-network-proxy (host process)"]
    HttpProxy["HTTP Proxy :3128<br/>CONNECT tunnel<br/>MITM (optional)"]
    SocksProxy["SOCKS5 Proxy :8081"]
    Admin["Admin API :8080<br/>/health /config /blocked<br/>/reload /mode"]
  end

  Config["~/.codex/config.toml<br/>[network_proxy.*]"]

  Tools -->|HTTP| HttpProxy
  SocksClients -->|SOCKS5| SocksProxy
  Admin -->|reads + reloads| Config

Configuration Model

The proxy reads ~/.codex/config.toml:

  • [network_proxy] for endpoints, mode, and toggles.
  • [network_proxy.policy] for allowed_domains / denied_domains (and, on macOS, optional local IPC allowances).
  • [network_proxy.mitm] for MITM CA paths and inspection settings.
  • Codex integration is rollout-gated behind [features].network_proxy = true.

Codex is the source of truth. Approval actions update the config and trigger a proxy reload.

Enforcement Model

  • Allow/deny precedence: denylist wins; allowlist is required for access.
  • Limited mode: only GET/HEAD/OPTIONS are permitted. HTTPS requires MITM to enforce method constraints; otherwise CONNECT is blocked with a clear reason.
  • Full mode: all methods allowed; CONNECT tunneling is permitted without MITM.

macOS Sandbox Integration (Seatbelt)

On macOS, Codex uses Seatbelt (sandbox-exec) for OS-level enforcement.

Key points:

  • Per-domain gating happens in the proxy, not in Seatbelt: Seatbelt network rules are intentionally limited to loopback proxy ports (e.g. localhost:3128 / localhost:8081) so all outbound traffic is forced through the proxy, which then applies the allow/deny policy and prompts.
  • Local IPC is deny-by-default when proxy-restricted network access is active. Some tools rely on Unix domain sockets (e.g. the SSH agent). These are blocked unless explicitly allowed via:
    • network_proxy.policy.allow_unix_sockets (absolute socket paths, $SSH_AUTH_SOCK, or the ssh-agent preset), and/or
    • network_proxy.policy.allow_local_binding (if you need to bind/listen on localhost ports).

When approvals are enabled, Codex can preflight commands that appear to require the SSH agent and prompt to allow the SSH agent socket before running.

Logging and Auditability

The proxy logs:

  • Allow/deny decisions (host, client, reason).
  • Policy updates (allowlist/denylist adds/removes).
  • Mode changes and config reloads.
  • MITM lifecycle events (CA generated, TLS established).

Decision to Make: Preflight Strictness

Codex performs a preflight check before running some commands. Preflight currently scans CLI args for URLs on known network tools (curl, git, etc.) and shell -c snippets.

We need to decide how strict preflight should be:

Option A: Heuristic preflight (current)

  • Pros: catches obvious curl https://... style commands early.
  • Cons: misses dynamic URLs inside scripts; can still overprompt on shell snippets.

Option B: Strict preflight

  • Only preflight when a URL argument is present in the command.
  • For everything else, rely on the proxy /blocked prompt at connect time.
  • Pros: fewer false positives, clearer user experience.
  • Cons: fewer early prompts; approvals shift to runtime events.

Decision: TBD. We should choose a configuration flag (network_proxy.preflight_mode = "heuristic" | "strict") and default based on observed UX.

Open Items

  • Finalize preflight strictness and expose a config toggle if needed.
  • Confirm documentation for MITM trust steps and CA injection into sandboxed commands.