Understanding the Codex CLI Sandbox Through nsjail Architecture: Isolation Boundaries, Designing AGENTS.md, and Wiring Autonomous Refactoring via codex exec in CI
For senior backend and full-stack developers integrating Codex CLI into a team pipeline, two things ultimately matter: how far you can isolate the agent process, and how reliably you can convey team conventions within that isolation. This article breaks down the structure of isolation boundaries through the conceptual lens of nsjail, covers how to solidify AGENTS.md as a team standard interface, and summarizes the options and failure patterns you must watch for when inserting codex exec into CI.
What the Codex CLI Sandbox Actually Blocks
Codex CLI runs the agent process in OS-level isolation. On Linux, Bubblewrap (bwrap) is the default engine, wrapping the process with user/PID namespaces and seccomp filters. In environments where the kernel doesn't support unprivileged user namespaces, it falls back to Landlock LSM; on macOS, Apple Seatbelt (sandbox-exec) fills the same role. This is documented in the OpenAI Codex official repository and the Windows sandbox implementation blog.
There are two optional defense layers on top. You can stack container isolation via Docker or devcontainer, and you can restrict the agent's network egress through custom configuration. Note that built-in isolation is not unique to Codex CLI — other agents such as Claude Code offer similar baseline isolation — so the fact that it's "on by default" is a reason to adopt it, not evidence of absolute superiority over other tools.
Each layer can be toggled independently, so you can choose a combination that matches your organization's risk tolerance. For sensitive repositories, apply all three — OS isolation + container + egress restriction; for personal experiments, OS isolation alone is often sufficient.
Understanding Isolation Boundaries Through the nsjail Model
To be clear upfront: nsjail is not an officially supported isolation mechanism for Codex CLI. It does not appear in OpenAI documentation, and Codex does not directly consume the example configuration below. The reason this section exists is that the axes nsjail exposes explicitly — Linux namespaces, seccomp, cgroups — serve as a useful checklist for understanding what properties a Bubblewrap-based sandbox actually guarantees, and what to watch for when wrapping an agent in an external wrapper (e.g., a pre-hook in your own CI runner).
| Axis nsjail exposes | Corresponding concern in Codex operation |
|---|---|
| Filesystem write scope restriction | Mount only the workspace as read-write; home and system paths as read-only |
| Network egress control | Allow only permitted domains via Codex config or an external proxy |
| CPU/memory/process count caps (cgroups) | cgroup v2 limits, plus --max-turns and token caps to control loop costs |
| PID/net/uts namespace isolation | Bubblewrap's user/PID namespaces provide equivalent coverage |
Below is a conceptual configuration example you can reference when wrapping a codex exec process with an nsjail wrapper on your own runner. Read it to see how the four axes in the table above are expressed in actual configuration — not as something to copy directly into production.
name: "codex-sandbox-example"
mount {
src: "/workspace"
dst: "/workspace"
is_bind: true
rw: true
}
mount {
src: "/usr"
dst: "/usr"
is_bind: true
rw: false
}
clone_newnet: true
rlimit_as_type: HARD
rlimit_cpu_type: HARD
max_cpus: 2In a real team environment, there are two places you can touch directly: specifying the sandbox mode and network access in Codex's config file, and explicitly locking down workspace mounts and egress paths in your Docker/CI image.
The general form for setting sandbox policy in ~/.codex/config.toml looks like this. For exact key names and valid values, check codex --help for the Codex CLI version you're running, and verify against the official repository.
# ~/.codex/config.toml — conceptual example (confirm actual keys against your installed version's docs)
sandbox_mode = "workspace-write"
[sandbox_workspace_write]
network_access = falseWhen you need to allow specific domains rather than blocking egress entirely, a practical pattern is to route Codex traffic inside the container through a sidecar proxy. Docker's network_mode: none cuts all networking as the name implies, which also blocks the OpenAI API calls. To enforce a whitelist via proxy, set up a separate network and an egress proxy as shown below.
# docker-compose.yml — conceptual example
services:
egress-proxy:
image: mitmproxy/mitmproxy:latest
networks:
- codex-egress
command: >
mitmdump --set block_global=true
--allow-hosts '^(api\.openai\.com|registry\.npmjs\.org|pypi\.org|github\.com)$'
codex-agent:
image: codex-universal:latest
depends_on: [egress-proxy]
networks:
- codex-egress
volumes:
- ./workspace:/workspace:rw
- ./codex-config.toml:/root/.codex/config.toml:ro
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
- HTTPS_PROXY=http://egress-proxy:8080
- HTTP_PROXY=http://egress-proxy:8080
command: >
codex exec 'Analyze the CI failure log and fix the root cause'
restart: 'no'
networks:
codex-egress:
driver: bridge
internal: falseUsing Bubblewrap inside a container depends on whether the host kernel permits unprivileged user namespaces. On hardened Kubernetes nodes, additional kernel parameter tuning may be required, so it's safer to include unshare -Urn true as an early validation step in your CI runner image.
AGENTS.md: Hardening Team Conventions into an Agent Interface
Pushing context directly into prompts breaks down as codex exec invocations multiply. AGENTS.md is a Markdown file placed at the repository root or in a subpackage, and it serves as a shared conventions file read by Codex CLI and many other coding agents. The spec and list of adopting tools can be found at the AGENTS.md project site. (Exact governance and adoption numbers shift over time, so this article does not cite specific figures.)
The practical benefit is that swapping out the agent doesn't require rewriting team context — as long as AGENTS.md stays in place.
Layout in a Monorepo
In a monorepo, place a separate AGENTS.md in each subpackage so the agent prioritizes the file closest to the current working path.
my-monorepo/
├── AGENTS.md ← shared context for the whole repo
├── services/
│ ├── api/
│ │ └── AGENTS.md ← Python FastAPI service specific
│ └── frontend/
│ └── AGENTS.md ← TypeScript React specific
└── packages/
└── shared/
└── AGENTS.md ← shared library specificStart Under 30 Lines
If you start with over 100 lines, agents tend to give relatively less weight to the instructions that actually matter (test commands, lint rules). It's safer to start with a skeleton like the one below and add entries one by one as the team encounters real problems.
# Project Context
## Tech Stack
- Runtime: Node.js 22, TypeScript 5.4
- Framework: Fastify v5
- Testing: Vitest (unit), Playwright (E2E)
- Package manager: pnpm
## Code Conventions
- Prefer named functions over arrow functions
- Use the Result type pattern for error handling (neverthrow)
- Place test files in the same directory as the source, with a .test.ts suffix
## Test Commands
- Unit tests: pnpm test
- E2E tests: pnpm test:e2e (requires a local server)
## Pre-PR Checklist
- [ ] pnpm lint passes
- [ ] pnpm typecheck passes
- [ ] Related tests added or updated
- [ ] CHANGELOG.md updatedIt's good practice to review AGENTS.md in a PR just like code. This way, when conventions change, humans and agents adopt the new rules at the same time. The AGENTS.md team adoption guide (personal blog) also notes that files written and maintained by humans produce more stable results than those generated automatically — though this observation is case-based rather than from academic research, so pairing it with your own internal measurement is advisable.
Using codex exec in a CI Pipeline
codex exec is Codex CLI's non-interactive (headless) execution mode — it runs a task to completion and exits. Because it supports piping and redirection like any other shell command, it can be inserted directly as a CI step.
codex exec "Analyze and fix the failing tests"
codex exec --approval-mode full-auto "Fix all lint errors and commit"
codex exec --max-turns 10 "Update dependencies to their latest versions"Option names and approval mode labels have varied across versions, so run codex exec --help before adopting to confirm the actual flags in your installed version.
Auto-Fix Workflow on Build Failure
When CI fails, the flow for analyzing failure logs and creating a patch branch looks roughly like this:
In GitHub Actions, the actual workflow looks like this. Check the OpenAI developer docs for the latest version and input parameters of openai/codex-action.
# .github/workflows/autofix.yml
name: Codex Auto Bug Fix
on:
workflow_run:
workflows: ["CI"]
types: [completed]
branches: [main, "feature/**"]
jobs:
autofix:
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Codex Auto Fix
uses: openai/codex-action@v1
with:
prompt: |
The CI build has failed. Analyze the failure log, fix the
root cause in the code, and commit the changes. Fix tests
too if they need updating. Do not make tests pass by
removing test logic.
approval-mode: full-auto
max-turns: "15"
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}A reference implementation of this pattern is available in the OpenAI cookbook autofix example.
Connecting Tickets to PRs
The Atlassian MCP server and Jira agent integration flow is moving quickly as of this writing, so rather than citing a specific GA date, it's more useful to understand the flow itself: a ticket webhook triggers codex exec, and the agent reads issue details via the MCP server to handle implementation and PR creation end-to-end. Conceptually, the webhook handler looks like this:
#!/bin/bash
# Conceptual example — add authentication and validation steps before deploying
ISSUE_ID=$1
codex exec \
--approval-mode full-auto \
--max-turns 20 \
"Read the details of Jira issue ${ISSUE_ID} via the Atlassian MCP server,
implement the feature, write tests, and create a PR.
Include the issue number and a summary of changes in the PR description."Large-Scale Refactoring with Sub-Agents
In a monorepo mixing Python, TypeScript, and Go, it's effective for a manager agent to delegate per-subpackage work to language-specific sub-agents, then aggregate the results into a final PR. Per-subpackage AGENTS.md files are critical here: each sub-agent automatically reads the language-specific conventions and test commands from the AGENTS.md in the directory it enters, so the manager doesn't need to repeat stack-specific instructions in every delegation prompt. Check the --help output and release notes of your installed Codex CLI version for the exact scope and options of sub-agent functionality.
Trade-offs and Common Mistakes to Review Before Adopting
| Axis | What to verify in practice |
|---|---|
| Isolation on by default | OS-level isolation is active without extra configuration; container and egress layers must be added separately |
| Layered defense | OS, container, and network layers can be assembled independently |
| Non-interactive execution | Use codex exec to turn steps into CI steps; always specify approval mode and --max-turns |
| Cross-tool conventions | AGENTS.md minimizes context rewriting when switching agents |
| Approval policy | Apply Suggest / Auto Edit / Full Auto separately based on repository sensitivity and branch type |
| Project maturity | The official README states experimental status — pin versions |
| Data governance | For corporate codebases, verify enterprise contract terms and data retention policy before using personal API keys |
| Cost caps | Double-defense with --max-turns, token caps, and cgroup CPU limits |
| Security updates | There is a history of shell-injection-related fixes; regularly check release notes and GitHub Security Advisories |
| Kernel requirements inside containers | On hardened Kubernetes, verify unprivileged user namespace support in advance |
| Package confusion | Always install as @openai/codex; the codex npm package is an unrelated, separate package |
Failure patterns seen repeatedly in real teams tend to involve several intertwined issues:
- Running Full Auto on flaky tests without
--max-turns. Retry loops exceeding twenty iterations that blow past token budgets are common. In CI, always specify--max-turnswithout exception, and separately monitor organization-level token limits via the dashboard. - Over-designing AGENTS.md from the start. Starting with more than 100 lines causes core instructions (how to run tests, commit rules) to be relatively buried. Starting with a skeleton under 30 lines and adding entries as the team encounters actual regressions and misunderstandings produces better adherence.
- Running corporate code against a personal API key. This moves source code under consumer terms of service. Before adopting, work with legal and security teams to verify enterprise contract terms and data retention policy.
- Mistaking
network_mode: nonefor isolation. Cutting all networking inside a container also prevents the agent from making API calls, making it non-functional. If you want a whitelist, you need a separate network and proxy container as shown in the egress proxy pattern above.
A Recommended Order for Getting Started
The lower-risk way to adopt Codex CLI is to replace a single step in your pipeline rather than switching over entirely at once. The following order is recommended:
- Run one or two small tasks (e.g., automatic lint fixes) with
codex exec --max-turns 5on a personal repository or staging branch. - Commit a 30-line AGENTS.md at the repository root and establish a review process with a first PR. From then on, discuss convention changes as AGENTS.md update PRs.
- Enable the GitHub Actions autofix workflow from the previous section on
feature/**branches only to observe it under limited traffic. Measure failure logs, PR quality, and token consumption together. - For sensitive repositories, bake the Docker container + egress proxy combination into your CI runner image in advance and promote it to your standard runner.
- Introduce per-subpackage AGENTS.md to absorb language and framework variation in a monorepo.
Tracking three metrics makes management easier: task success rate (the percentage of agent PRs merged without human edits), token cost per step, and isolation violation event count (out-of-whitelist egress attempts, write attempts outside the workspace). When any one of these spikes, the cause is almost always one of three things: --max-turns, clarity of AGENTS.md instructions, or consistency of the proxy whitelist.
References
OpenAI Official Resources
- OpenAI Codex GitHub Official Repository
- OpenAI Codex GitHub Action Documentation
- OpenAI Cookbook: CI Auto Bug Fix Example
- OpenAI Official Blog: Windows Sandbox Implementation
- GitHub Security Advisories (openai/codex)
Standards and Specs
Community and Personal Blogs
- Codex CLI Approval Modes Overview (personal blog)
- Security Hardening Your Codex CLI Setup (personal blog)
- Codex CLI Network Security (personal blog)
- Codex CLI Devcontainers & Docker Sandboxes (personal blog)
- Docker Sandboxes for Codex CLI (personal blog)
- Codex CLI for CI/CD, codex exec in Practice (personal blog)
- Ticket-Driven Development with Codex CLI (personal blog)
- Codex Exec in CI Guide (personal blog)
- Codex CLI Guide 2026 (personal blog)
- How Claude Code and Codex Sandbox Untrusted Code (Medium)
Third-Party Analysis and Marketing Resources (for reference)
- Agent Safehouse: Codex CLI Sandbox Analysis
- AGENTS.md Team Adoption Guide (marketing blog)
- AGENTS.md Spec Summary (marketing blog)
- Risks of Using OpenAI Codex With Private Repositories (analysis)
- Codex vs Claude Code: A CTO Perspective (marketing blog)
- Coding Agent Sandbox: Secure Environments (marketing blog)
- AGENTS.md for OpenAI Codex Setup Guide (marketing blog)