[BUG] Codex executed its own safety instructions from a rollout JSONL, deleting the Windows HOME directory
What version of Codex CLI is running?
codex-cli 0.146.0
What subscription do you have?
API-based usage; ChatGPT subscription not applicable.
Which model were you using?
gpt-5.6-sol
What platform is your computer?
Windows 10 Pro 10.0.19045 x64
What terminal emulator and version are you using (if applicable)?
Windows Terminal; Codex commands were executed through Git Bash.
Codex doctor report
Not provided because it contains sensitive local diagnostics.
What issue are you seeing?
During a forensic audit of previous Codex sessions, Codex attempted to inspect a historical rollout JSONL file but placed the JSONL pathname in the program position of a Bash login-shell command.
Git Bash treated the data file as shell input. The first JSONL record contained saved model base instructions with Markdown backtick examples. Bash interpreted those backticks as command substitutions and executed them. One safety-prohibition example recursively deleted the effective HOME directory, which resolved to C:\Users\<redacted>.
The triggering session was 019fcd08-55ee-7b42-a979-2d4d27244faa. The historical rollout accidentally executed as shell input was 019fc120-5de7-7910-822a-10549c7fda3f.
The triggering tool call occurred at 2026-08-04 14:52:17.209 UTC. Independent evidence includes a Git hard-reset reflog entry at 14:52:18 UTC and a later child process showing that Bash continued interpreting the JSONL beyond the deletion fragment.
The command discarded standard error and ignored its failure status, allowing execution to continue without surfacing the mistake. The thread used danger-full-access, approval policy never, and the Windows elevated sandbox.
The destructive literal came from the bundled gpt-5.6-sol safety instructions in codex-rs/models-manager/models.json, introduced by commit d26a9bf671b1c03aabfc32e1092d137c1feb3962. Its intent was to prohibit destructive behavior. It became dangerous only because the rollout JSONL containing it was executed as shell input.
No raw rollout, username, credentials, provider diagnostics, or Codex doctor report is included here.
What steps can reproduce the bug?
I have not attempted a destructive reproduction.
Observed sequence:
- Start Codex CLI on Windows with existing rollout history under
CODEX_HOME/sessions. - Ask Codex to audit previous session JSONL files.
- Codex constructs a Bash command intended to inspect a rollout.
- The rollout pathname is accidentally placed in the command's program position instead of being passed to a read-only parser.
- Bash interprets the JSONL as shell input.
- Markdown backtick content stored in the JSONL is executed as command substitution.
- A command embedded as a safety-prohibition example targets the effective HOME directory and causes data loss.
A safe regression test should use a synthetic rollout fixture containing only a benign marker and verify that the execution layer rejects all session and data files in the program position before starting a shell.
What is the expected behavior?
Rollout JSONL files must always be treated as untrusted data, never as executable programs or shell input.
The execution harness should:
- Reject paths under
CODEX_HOME/sessionsandarchived_sessionswhen they resolve to the program position. - Reject JSONL, JSON, Markdown, logs, and other data formats as shell programs regardless of executable bits.
- Prevent file contents from reaching
source,eval, command substitution, or pipe-to-shell paths. - Canonicalize destructive targets and require an unbypassable confirmation for HOME, root, workspace ancestors, or out-of-workspace deletion, including in Full Access mode.
- Avoid hiding standard error or ignoring failure for unvalidated commands.
- Terminate the complete child process tree when a command times out.
- Preserve an append-only execution audit containing resolved executable and target paths.
Additional information
Exact Markdown stored in the historical JSONL
The following section is quoted verbatim from payload.base_instructions.text. It is forensic evidence, not reproduction instructions.
It is byte-for-byte identical to the corresponding gpt-5.6-sol section in the tracked models.json. Section SHA-256:
608b9f9aa2f668c04f933fc56a39b7329ae59bb72093fb70318436e9bb238442
# Destructive Actions
Be cautious with commands or API calls that can delete, overwrite, or otherwise make data difficult to recover.
Before taking a destructive action:
- Make sure the action is clearly within the user's request.
- Resolve the exact targets with read-only checks when necessary.
- Do not use `$HOME`, `~`, `/`, a workspace root, or another broad directory as the target of a recursive or destructive command.
- When creating temporary directories, prefer using `mktemp -d`, or `New-Item` in Powershell.
- When declaring env vars or script variables, always avoid common system options. Never repurpose `$HOME`, `$home`, or `$CODEX_HOME`. Instead, use a task-specific variable name.
- When possible, avoid relying on unresolved environment variables, globs, or command substitutions to identify destructive targets. Use explicit, validated paths.
- Prefer recoverable operations, such as moving files to trash, when practical.
- If the target or scope is unclear, stop and ask the user.
Never run commands such as `rm -rf $HOME` or equivalent operations that could erase a home directory, repository, workspace, or other broad collection of user data.
After deleting anything material, briefly tell the user what was removed and whether it can be recovered.
The incident demonstrates why prompt-level prohibition is not a sufficient security boundary: once a transcript containing safety examples is interpreted as shell code, the prohibited examples themselves become executable syntax.
This was not caused by a later Git revert. That operation occurred approximately 44 minutes after the HOME deletion trigger.
The symlink entries C:\Users\<redacted>\.codex and .claude were deleted, while their D-drive targets survived because deletion removed the links without traversing their targets.
The exact short-lived deletion-process PID is unavailable because Windows process-creation auditing and Sysmon were not enabled. The session command, Git reflog, process ordering, HOME mapping, and filesystem reconstruction times nevertheless form a consistent causal chain.
Related but not duplicate:
- https://github.com/openai/codex/issues/27131 - session JSONL self-ingestion causing token growth, but not shell execution.
- https://github.com/openai/codex/issues/33624 - hard confirmation for bulk and HOME deletion, but not rollout data executed as code.
- https://github.com/openai/codex/issues/32684 - Windows HOME deletion through a PowerShell variable collision; different mechanism.
- https://github.com/openai/codex/issues/33557 - repository deletion through temporary-directory cleanup and a bind mount; different mechanism.
- https://github.com/openai/codex/issues/18509 - Windows data loss during archive handling; different trigger.
A sanitized forensic report and selected evidence can be provided privately to OpenAI. Raw session files will not be posted publicly because they contain prompts, local paths, command outputs, and configuration data.