Jarek Hartman
Monday, February 2, 2026

Codex in the Jail

OpenAI Codex

I wanted to run codex-cli in a real sandbox on macOS. The goal was simple: keep the tool useful, but stop it from touching anything outside my working tree. This is the story of two tries: a native macOS sandbox first, then a container‑based setup that finally worked.

Attempt 1: macOS sandbox-exec

My first idea was to use sandbox-exec with a strict “deny by default” profile and poke holes only where needed.

% sandbox-exec -f codex-full.sb /opt/homebrew/bin/codex
zsh: abort      sandbox-exec -f codex-full.sb /opt/homebrew/bin/codex

Profile (trimmed to the essentials):

codex-cli.patch
(version 1)

(trace "/private/tmp/codex.trace")

(deny default)

(allow file-read* file-write*
  (subpath "/Users/jhartman/scripts/codex"))

(allow file-read*
  (subpath "/System")
  (subpath "/usr/lib")
  (subpath "/usr/share")
  (subpath "/Library"))

(allow file-read*
  (subpath "/opt/homebrew"))

(allow file-read*
  (subpath "/usr/lib/dyld")
  (subpath "/var/db/dyld"))

(allow file-read* file-write*
  (subpath "/dev"))

(allow file-read* file-write*
  (subpath "/private/tmp"))

;; OpenAI config
(allow file-read*
  (subpath "/Users/jhartman/.config/openai"))

(allow process*)

(allow mach-lookup)

(allow network*)

The sandbox denied root reads and sysctl probes:

Sandbox: codex-aarch64-apple-darwin(...) deny(1) file-read-data /
Sandbox: codex-aarch64-apple-darwin(...) deny(1) sysctl-read security.mac.lockdown_mode_state
Sandbox: codex-aarch64-apple-darwin(...) deny(1) sysctl-read kern.bootargs

In practice this meant:

  • codex (via Node + system libraries) performs early environment checks that touch / and sysctl.
  • Allowing file-read-data / would effectively expose the whole filesystem, which defeats the point.
  • I could keep expanding the profile, but I’d end up re‑creating “allow almost everything” just to get it to start.

Verdict: sandbox-exec is too brittle for this use case. It’s great for a fixed, minimal app, but not for a CLI that probes the system at startup.

Attempt 2: Container on Apple Silicon (no Docker)

Next idea: containers. I didn’t want Docker, so I used Apple’s native container runtime on Apple Silicon. It gives me a real filesystem boundary and a predictable runtime without installing a massive daemon.

Build the image

  1. Clone the repo:
https://github.com/openai/codex.git
  1. Patch codex/codex-cli/Dockerfile:
diff --git a/codex-cli/Dockerfile b/codex-cli/Dockerfile
index 21a90a483..c6f9afe39 100644
--- a/codex-cli/Dockerfile
+++ b/codex-cli/Dockerfile
@@ -23,6 +23,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   unzip \
   ripgrep \
   zsh \
+  python3 python3-pip \
+  imagemagick libpng-dev libjpeg-dev libtiff-dev \
   && rm -rf /var/lib/apt/lists/*
@@ -39,8 +41,7 @@ ENV NPM_CONFIG_PREFIX=/usr/local/share/npm-global
 ENV PATH=$PATH:/usr/local/share/npm-global/bin

 # Install codex
-COPY dist/codex.tgz codex.tgz
-RUN npm install -g codex.tgz \
+RUN npm install -g @openai/codex \
   && npm cache clean --force \
@@ -57,3 +58,5 @@ RUN chmod 500 /usr/local/bin/init_firewall.sh
 USER node
+
+ENTRYPOINT [ "codex" ]
  1. Build script:
build.sh
#!/usr/bin/env bash

pushd ../codex/codex-cli > /dev/null

git diff > ../../image/codex-cli.patch
git checkout .
git pull

git apply ../../image/codex-cli.patch

container build -t codex:latest

popd > /dev/null

Run it like a tool

codex.sh
#!/usr/bin/env bash

container system start

container run --rm -it \
  -v "$PWD:/workspace" \
  -v /Users/jhartman/scripts/codex/.codex:/home/node \
  -w /workspace \
  codex:latest "$@"

Notes:

  • -v "$PWD:/workspace" gives Codex only the current repo.
  • I keep my token and preferences in /Users/jhartman/scripts/codex/.codex and bind‑mount that to /home/node.
  • No Docker daemon, no virtualization UI — just a light container runtime on Apple Silicon.

Demo

Wrap‑up

The macOS sandbox approach was elegant on paper but fragile in reality. The container runtime is boring — and that’s exactly what I want. I now have Codex isolated, reproducible, and still fast enough to use daily.

References