A Podman wrapper that runs codex inside a container and always uses:
--dangerously-bypass-approvals-and-sandbox(the actual “yolo” behavior)--sandbox danger-full-access--enable web_search_request(web search tool available to the agent)
Networking is enabled (full egress).
You need an image that includes codex, git, bash, and uv (plus a Python runtime; this image uses uv-managed Python by default, and exposes it as python3 in the container).
Use Containerfile:
podman build -t localhost/codex-container-sandbox:latest -f Containerfile .Or use the Makefile (also installs the wrapper):
make installIf you're on a corporate network with an npm mirror, override the registry:
make install NPM_REGISTRY=https://your-registry.example.com/If TLS is intercepted (transparent proxy / self-signed in chain), pass a corporate root CA cert:
make install EXTRA_CA_CERT_PATH=$HOME/wbg_root_ca_g2.cerIf ~/wbg_root_ca_g2.cer exists, the Makefile auto-detects it on the WBG laptop
hostname (PCACL-G7MKN94) when EXTRA_CA_CERT_PATH is not set.
This cert is not stored in the repo; it’s a local machine file and should not be committed.
You can also override bundled tool versions:
make install MQ_VERSION=0.5.9 TYPST_VERSION=0.14.2 TYPST_TARGET=x86_64-unknown-linux-muslOverride the default uv-managed Python version:
make install UV_DEFAULT_PYTHON=3.14You can also override the bundled uv binary version (rarely needed):
make install UV_VERSION=0.9.21If you want a smaller build (skip Playwright’s bundled browser download), set:
make install INSTALL_PLAYWRIGHT_BROWSERS=0install -m 0755 ./codex-container-sandbox ~/.local/bin/codex-container-sandboxCreate ~/.config/codex-container-sandbox/config.sh:
CODEX_CONTAINER_SANDBOX_IMAGE="localhost/codex-container-sandbox:latest"
# Optional: force an OCI runtime (useful on some WSL/work setups).
# CODEX_CONTAINER_SANDBOX_PODMAN_RUNTIME="runc"
# Optional: override DNS servers used inside the container (default is pinned).
# Disable the override to inherit host/Podman DNS behavior:
# CODEX_CONTAINER_SANDBOX_DISABLE_DNS_OVERRIDE=1
# Or override the server list (in order):
# CODEX_CONTAINER_SANDBOX_DNS_SERVERS=(45.90.28.212 45.90.30.212 1.1.1.1 8.8.8.8)
#
# Note: When DNS override is enabled, the wrapper bind-mounts a generated
# /etc/resolv.conf into the container to bypass Podman DNS forwarders (often a
# 169.254.x.x hop).
# Mount helper tools read-only (mapped under /home/codex/...)
CODEX_CONTAINER_SANDBOX_RO_MOUNTS=(
"$HOME/.local/bin"
"$HOME/bin"
)
# Persist caches if needed
CODEX_CONTAINER_SANDBOX_RW_MOUNTS=(
"$HOME/.cache/uv"
"$HOME/tmp"
)codex-container-sandbox exec "Summarize the repo"From the repo root:
make image
make selftest
make pii-scan
make validate-docsRuns three checks:
- Container has internet connectivity.
- Host files outside the workspace are not visible by default.
- An explicitly mounted host directory is readable and writable (RW mount).
./selftest.shcodex-container-sandbox --shellCODEX_CONTAINER_SANDBOX_DEBUG=1 codex-container-sandbox exec "hello"By default the wrapper prints the computed codex ... command (to stderr) before starting.
Disable with:
codex-container-sandbox --no-print-codex-cmd exec "hello"To avoid git commit failing with “Author identity unknown”, the wrapper will (by default)
copy user.name / user.email from the host git config into a persistent container-global
gitconfig under CODEX_HOME, and set GIT_CONFIG_GLOBAL accordingly.
Override (or set explicitly if host identity is not set):
CODEX_CONTAINER_SANDBOX_GIT_NAME="Your Name" \
CODEX_CONTAINER_SANDBOX_GIT_EMAIL="you@domain" \
codex-container-sandbox ...Disable:
CODEX_CONTAINER_SANDBOX_DISABLE_GIT_IDENTITY_SYNC=1 codex-container-sandbox ...- If you run inside a git repo, the repo root is mounted read-write.
- The container working directory is set to your original
$PWDinside that mount. - Extra mounts under
$HOMEare mapped to the same relative path under/home/codex. XDG_CACHE_HOMEis set to$CODEX_HOME/cacheso tools likeuvhave a writable cache by default.
Codex credentials live in CODEX_HOME (~/.local/state/codex-container-sandbox by default).
Login once inside the container:
codex-container-sandbox --shell
codex loginIf you already have a working host login (for example ~/.codex/auth.json), you can mount it
into the container so codex doesn't prompt for login again:
- Auto-detects and mounts
~/.codex/auth.jsonif it exists. - Override the path with
CODEX_CONTAINER_SANDBOX_AUTH_FILE=/path/to/auth.json. - Disable mounting entirely with
CODEX_CONTAINER_SANDBOX_DISABLE_AUTH_MOUNT=1. - Control mount mode (default
ro) withCODEX_CONTAINER_SANDBOX_AUTH_MOUNT_MODE=ro|rw.
To keep prompts and skills consistent with your host setup, the wrapper can also mount:
~/.codex/prompts->$CODEX_HOME/prompts(read-only)~/.codex/skills->$CODEX_HOME/skills(read-only)
Controls:
- Override paths:
CODEX_CONTAINER_SANDBOX_PROMPTS_DIR=/path/to/promptsCODEX_CONTAINER_SANDBOX_SKILLS_DIR=/path/to/skills
- Disable:
CODEX_CONTAINER_SANDBOX_DISABLE_PROMPTS_MOUNT=1CODEX_CONTAINER_SANDBOX_DISABLE_SKILLS_MOUNT=1
If you have read-pdf installed on the host at ~/.local/bin/read-pdf, the wrapper will
mount that executable (and its helper scripts like read_pdf_page_candidates.py) read-only
into the container (without mounting the entire ~/.local/bin directory) so it is available
on the container $PATH.
Disable with:
CODEX_CONTAINER_SANDBOX_DISABLE_LOCAL_BIN_MOUNT=1 codex-container-sandbox ...The image ships with a few common “skills dependencies” so you don’t need host mounts:
imagemagick(convert,identify) forimage-croppoppler-utils(pdfinfo,pdftoppm) forread-pdf --as-imagesmarkitdownforread-webpage-content-as-markdownandread-pdf --as-text-fastpandocmqtypstchromium+playwright(JS/client-rendered pages)
If you install CLIs on the host via:
uv tool install ...(often creates symlinks under~/.local/binpointing at~/.local/share/uv/tools/...)
the wrapper can mount the needed host directories read-only so those tools work inside the container.
Defaults (best-effort, only when detected):
- Mount
~/.local/share/uv/toolsread-only whenttokis detected as a uv tool install. - Also mount
~/.local/share/uv/pythonread-only (needed for uv tool shebang interpreters) when present.
Disable:
CODEX_CONTAINER_SANDBOX_DISABLE_UV_TOOLS_MOUNT=1 codex-container-sandbox ...
CODEX_CONTAINER_SANDBOX_DISABLE_UV_PYTHON_MOUNT=1 codex-container-sandbox ...This wrapper is about filesystem isolation (mount boundaries), not egress safety.
Because this runs full yolo with full networking, the agent can exfiltrate anything it can
read inside the container (including anything you mount, and CODEX_HOME/auth.json).