False-positive cybersecurity hard failures in codex operated in a homegrown harness during local software-integrity unit tests (8 events across 4 jobs)
What version of Codex CLI is running?
codex-cli 0.144.6
What subscription do you have?
Pro 20x
Which model were you using?
gpt-5.6-sol xhigh
What platform is your computer?
Linux 7.1.3-arch1-2 x86_64 unknown
What terminal emulator and version are you using (if applicable)?
zellij
Codex doctor report
codex doctor --json
{
"schemaVersion": 1,
"generatedAt": "1784642889s since unix epoch",
"overallStatus": "fail",
"codexVersion": "0.144.6",
"checks": {
"app_server.status": {
"id": "app_server.status",
"category": "app-server",
"status": "ok",
"summary": "background server is not running",
"details": {
"control socket": "/home/marc/.codex/app-server-control/app-server-control.sock",
"daemon state dir": "/home/marc/.codex/app-server-daemon",
"mode": "ephemeral",
"pid file": "/home/marc/.codex/app-server-daemon/app-server.pid (missing)",
"settings": "/home/marc/.codex/app-server-daemon/settings.json (missing)",
"status": "not running",
"update-loop pid file": "/home/marc/.codex/app-server-daemon/app-server-updater.pid (missing)"
},
"remediation": null,
"durationMs": 0
},
"auth.credentials": {
"id": "auth.credentials",
"category": "auth",
"status": "ok",
"summary": "auth is configured",
"details": {
"auth env vars present": "OPENAI_API_KEY",
"auth file": "/home/marc/.codex/auth.json",
"auth storage mode": "File",
"stored API key": "false",
"stored ChatGPT tokens": "true",
"stored agent identity": "false",
"stored auth mode": "chatgpt"
},
"remediation": null,
"durationMs": 0
},
"config.load": {
"id": "config.load",
"category": "config",
"status": "ok",
"summary": "config loaded",
"details": {
"CODEX_HOME": "/home/marc/.codex",
"config.toml": "/home/marc/.codex/config.toml",
"config.toml parse": "ok",
"cwd": "/media/ubuntussd/home/lavallee/Projects/keel",
"enabled feature flags": "shell_tool, unified_exec, shell_snapshot, code_mode_host, terminal_resize_reflow, sqlite, memories, hooks, enable_request_compression, multi_agent, apps, tool_search_always_defer_mcp_tools, tool_suggest, plugins, in_app_browser, browser_use, browser_use_full_cdp_access, browser_use_external, computer_use, remote_plugin, plugin_sharing, external_migration, image_generation, resize_all_images, skill_mcp_dependency_install, mentions_v2, steer, guardian_approval, goals, collaboration_modes, tool_call_mcp_elicitation, auth_elicitation, personality, fast_mode, tui_app_server, remote_compaction_v2, workspace_dependencies",
"feature flag overrides": "memories=true, external_migration=true",
"feature flags enabled": "37",
"log dir": "/home/marc/.codex/log",
"mcp servers": "3",
"model": "gpt-5.6-sol",
"model provider": "openai",
"sqlite home": "/home/marc/.codex"
},
"remediation": null,
"durationMs": 0
},
"git.environment": {
"id": "git.environment",
"category": "git",
"status": "ok",
"summary": "git version 2.55.0",
"details": {
".git entry": "directory",
"PATH git #1": "/usr/bin/git",
"PATH git entries": "1",
"git branch": "main",
"git build options": "git version 2.55.0; cpu: x86_64; built from commit: e9019fcafe0040228b8631c30f97ae1adb61bcdc; sizeof-long: 8; sizeof-size_t: 8; shell-path: /bin/sh; rust: enabled; feature: fsmonitor--daemon; gettext: enabled; libcurl: 8.21.0; OpenSSL: OpenSSL 3.6.3 9 Jun 2026; zlib-ng: 2.3.3; SHA-1: SHA1_DC; SHA-256: SHA256_BLK; default-ref-format: files; default-hash: sha1",
"git exec path": "/usr/lib/git-core",
"git version": "git version 2.55.0",
"repo detected": "true",
"repo root": "/media/ubuntussd/home/lavallee/Projects/keel",
"selected git": "/usr/bin/git"
},
"remediation": null,
"durationMs": 20
},
"installation": {
"id": "installation",
"category": "install",
"status": "fail",
"summary": "npm install -g @openai/codex would update a different install",
"details": {
"PATH codex #1": "/home/marc/.local/bin/codex",
"PATH codex #2": "/home/marc/.local/bin/codex",
"PATH codex #3": "/usr/bin/codex",
"PATH codex #4": "/home/marc/.local/bin/codex",
"PATH codex #5": "/home/marc/.local/bin/codex",
"PATH codex #6": "/home/marc/.local/bin/codex",
"PATH codex #7": "/home/marc/.local/bin/codex",
"PATH codex #8": "/home/marc/.local/bin/codex",
"PATH codex entries": "8",
"current executable": "/media/ubuntussd/home/lavallee/.npm-cache/_npx/c8ab89660c602c20/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/bin/codex",
"install context": "npm (package /media/ubuntussd/home/lavallee/.npm-cache/_npx/c8ab89660c602c20/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl, bin /media/ubuntussd/home/lavallee/.npm-cache/_npx/c8ab89660c602c20/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/bin, resources /media/ubuntussd/home/lavallee/.npm-cache/_npx/c8ab89660c602c20/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/codex-resources, path /media/ubuntussd/home/lavallee/.npm-cache/_npx/c8ab89660c602c20/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/codex-path)",
"managed by bun": "false",
"managed by npm": "true",
"managed by pnpm": "false",
"managed package root": "/media/ubuntussd/home/lavallee/.npm-cache/_npx/c8ab89660c602c20/node_modules/@openai/codex",
"npm package root": "/home/marc/.local/share/mise/installs/node/25.1.0/lib/node_modules/@openai/codex",
"running package root": "/media/ubuntussd/home/lavallee/.npm-cache/_npx/c8ab89660c602c20/node_modules/@openai/codex"
},
"remediation": "Fix PATH or npm prefix so the running package root (/media/ubuntussd/home/lavallee/.npm-cache/_npx/c8ab89660c602c20/node_modules/@openai/codex) matches the npm global package root (/home/marc/.local/share/mise/installs/node/25.1.0/lib/node_modules/@openai/codex).",
"durationMs": 65
},
"mcp.config": {
"id": "mcp.config",
"category": "mcp",
"status": "ok",
"summary": "MCP configuration is locally consistent",
"details": {
"configured servers": "3",
"disabled servers": "0",
"streamable_http servers": "3"
},
"remediation": null,
"durationMs": 4412
},
"network.env": {
"id": "network.env",
"category": "network",
"status": "ok",
"summary": "network-related environment looks readable",
"details": {
"proxy env vars": "none"
},
"remediation": null,
"durationMs": 0
},
"network.provider_reachability": {
"id": "network.provider_reachability",
"category": "reachability",
"status": "ok",
"summary": "active provider endpoints are reachable over HTTP",
"details": {
"openai API base URL": "https://api.openai.com/v1 reachable (HTTP 404)",
"openai API route probe": "https://api.openai.com/v1/<redacted> route exists (HTTP 401)",
"reachability mode": "API key auth"
},
"remediation": null,
"durationMs": 313
},
"network.websocket_reachability": {
"id": "network.websocket_reachability",
"category": "websocket",
"status": "ok",
"summary": "Responses WebSocket handshake succeeded",
"details": {
"DNS": "2 IPv4, 2 IPv6, first IPv4",
"auth mode": "chatgpt",
"connect timeout": "15000 ms",
"endpoint": "wss://chatgpt.com/backend-api/<redacted>",
"handshake result": "HTTP 101 Switching Protocols",
"model provider": "openai",
"models etag present": "true",
"provider name": "OpenAI",
"proxy env vars": "none",
"reasoning header": "false",
"server model present": "false",
"supports websockets": "true",
"wire API": "responses"
},
"remediation": null,
"durationMs": 590
},
"runtime.provenance": {
"id": "runtime.provenance",
"category": "runtime",
"status": "ok",
"summary": "running npm on linux-x86_64",
"details": {
"commit": "unknown",
"current executable": "/media/ubuntussd/home/lavallee/.npm-cache/_npx/c8ab89660c602c20/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/bin/codex",
"install method": "npm (package /media/ubuntussd/home/lavallee/.npm-cache/_npx/c8ab89660c602c20/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl, bin /media/ubuntussd/home/lavallee/.npm-cache/_npx/c8ab89660c602c20/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/bin, resources /media/ubuntussd/home/lavallee/.npm-cache/_npx/c8ab89660c602c20/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/codex-resources, path /media/ubuntussd/home/lavallee/.npm-cache/_npx/c8ab89660c602c20/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/codex-path)",
"platform": "linux-x86_64",
"version": "0.144.6"
},
"remediation": null,
"durationMs": 0
},
"runtime.search": {
"id": "runtime.search",
"category": "search",
"status": "ok",
"summary": "search is OK (bundled)",
"details": {
"search command": "/media/ubuntussd/home/lavallee/.npm-cache/_npx/c8ab89660c602c20/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/codex-path/rg",
"search command readiness": "file exists",
"search provider": "bundled"
},
"remediation": null,
"durationMs": 0
},
"sandbox.helpers": {
"id": "sandbox.helpers",
"category": "sandbox",
"status": "ok",
"summary": "sandbox configuration is readable",
"details": {
"approval policy": "OnRequest",
"codex-linux-sandbox helper": "/home/marc/.codex/tmp/arg0/codex-arg0QvXt2B/codex-linux-sandbox",
"execve wrapper helper": "/home/marc/.codex/tmp/arg0/codex-arg0QvXt2B/codex-execve-wrapper",
"filesystem sandbox": "restricted",
"network sandbox": "restricted"
},
"remediation": null,
"durationMs": 0
},
"state.paths": {
"id": "state.paths",
"category": "state",
"status": "ok",
"summary": "state paths and databases are inspectable",
"details": {
"CODEX_HOME": "/home/marc/.codex (dir)",
"active rollout files": "1782 files, 2203491813 total bytes, 1236527 average bytes",
"archived rollout files": "0 files, 0 total bytes, 0 average bytes",
"goals DB": "/home/marc/.codex/goals_1.sqlite (file)",
"goals DB integrity": "ok",
"log DB": "/home/marc/.codex/logs_2.sqlite (file)",
"log DB integrity": "ok",
"log dir": "/home/marc/.codex/log (dir)",
"memories DB": "/home/marc/.codex/memories_1.sqlite (file)",
"memories DB integrity": "ok",
"sqlite home": "/home/marc/.codex (dir)",
"state DB": "/home/marc/.codex/state_5.sqlite (file)",
"state DB integrity": "ok"
},
"remediation": null,
"durationMs": 579
},
"state.rollout_db_parity": {
"id": "state.rollout_db_parity",
"category": "threads",
"status": "warning",
"summary": "rollout files and state DB thread inventory differ",
"details": {
"default model provider": "openai",
"rollout DB active files": "1781",
"rollout DB active rows": "1781",
"rollout DB archive mismatches": "0",
"rollout DB archived files": "0",
"rollout DB archived rows": "0",
"rollout DB duplicate DB paths": "0",
"rollout DB duplicate rollout thread ids": "0",
"rollout DB malformed file names": "0",
"rollout DB missing active rows": "0",
"rollout DB missing archived rows": "0",
"rollout DB model providers": "openai=1781",
"rollout DB rows": "1781",
"rollout DB scan cap reached": "false",
"rollout DB scan error sample": "/home/marc/.codex/sessions/2026/06/19/rollout-2026-06-19T02-19-07-019ede88-7bc4-7650-a2f1-d34df0e156a2.jsonl (no parseable rollout items)",
"rollout DB scan errors": "1",
"rollout DB sources": "exec=1572, subagent:thread_spawn=145, cli=63, subagent:review=1",
"rollout DB stale rows": "0"
},
"issues": [
{
"severity": "warning",
"cause": "rollout scan was incomplete or found bad files",
"measured": "1 scan errors, 0 malformed names, scan cap reached: false",
"expected": "rollout directories are fully scannable",
"remedy": "Check file permissions and unexpected files under CODEX_HOME sessions.",
"fields": []
}
],
"remediation": null,
"durationMs": 20586
},
"system.environment": {
"id": "system.environment",
"category": "system",
"status": "ok",
"summary": "OS language en-US",
"details": {
"EDITOR": "set",
"LANG": "en_US.UTF-8",
"VISUAL": "not set",
"os": "Arch Linux [64-bit]",
"os language": "en-US",
"os type": "Arch Linux",
"os version": "Unknown"
},
"remediation": null,
"durationMs": 1
},
"terminal.env": {
"id": "terminal.env",
"category": "terminal",
"status": "ok",
"summary": "terminal metadata was detected",
"details": {
"COLORTERM": "truecolor",
"DISPLAY": "present",
"WAYLAND_DISPLAY": "present",
"color output": "enabled",
"effective locale": "en_US.UTF-8",
"multiplexer": "zellij 0.44.3",
"stderr is terminal": "true",
"stdin is terminal": "true",
"stdout is terminal": "true",
"terminal": "Alacritty",
"terminal size": "86x47"
},
"remediation": null,
"durationMs": 0
},
"terminal.title": {
"id": "terminal.title",
"category": "title",
"status": "ok",
"summary": "terminal title default",
"details": {
"terminal title activity": "true",
"terminal title items": "activity, project-name",
"terminal title project source": "git repo root",
"terminal title project value": "keel",
"terminal title source": "default"
},
"remediation": null,
"durationMs": 0
},
"updates.status": {
"id": "updates.status",
"category": "updates",
"status": "fail",
"summary": "update would target a different npm install",
"details": {
"cached latest version": "0.144.6",
"check for update on startup": "true",
"last checked at": "2026-07-20T15:36:26.992907308Z",
"latest version": "0.144.6",
"latest version status": "current version is not older",
"npm package root": "/home/marc/.local/share/mise/installs/node/25.1.0/lib/node_modules/@openai/codex",
"running package root": "/media/ubuntussd/home/lavallee/.npm-cache/_npx/c8ab89660c602c20/node_modules/@openai/codex",
"update action": "npm install -g @openai/codex",
"version cache": "/home/marc/.codex/version.json"
},
"remediation": "Fix PATH or npm prefix so the running package root (/media/ubuntussd/home/lavallee/.npm-cache/_npx/c8ab89660c602c20/node_modules/@openai/codex) matches the npm global package root (/home/marc/.local/share/mise/installs/node/25.1.0/lib/node_modules/@openai/codex).",
"durationMs": 249
}
}
}
What issue are you seeing?
I have a homegrown software building and testing system (called fab) that tries to, as it puts it, run “release/worktree custody tests simulate crashes, malformed state, symlink replacement, TOCTOU races, replay, and fail-closed behavior.”
In this case, I’m working on an autonomous deep research engine (called keel) that I’m evolving to be more resilient in the face of interrupted research jobs. Keel’s benchmark-authorization tests construct deliberately inconsistent local data packets and prove that authorization validation rejects them.
I sometimes run a sequence of fab jobs through an interactive codex session, so it dispatches work to fab, which, in this case, is in turn running codex in a sub-process, and monitoring the output. So the issue was raised from the non-interactive codex session.
Tracing this helped me find two partial self-remedies for the way this failed. My llm wrapper (somm) was not properly identifying REFUSED responses and escalating to me internally. Separately, I think the framing of my unit/integration tests, not the contents, is what tripped the blocker.
I had codex trace logs and reason about what trigged the issues:
There was no malware development, credential theft, scanning, remote exploitation, persistence, or interaction with third-party systems. Almost everything was local unit testing in temporary directories.
Title: False-positive cybersecurity hard failures in Codex CLI during local software-integrity unit tests (8 events across 4 jobs)
Summary
Codex CLI repeatedly terminated legitimate local software-engineering tasks with:
"This content was flagged for possible cybersecurity risk. If this seems wrong, try rephrasing your request. To get authorized for security work, join the Trusted
Access for Cyber program: https://chatgpt.com/cyber"
These tasks were not cybersecurity operations. They were local, defensive software-integrity reviews and unit tests for:
- A software-factory queue/release system named Fab.
- An offline research-benchmark authorization contract in a project named Keel.
The apparent trigger is accumulated context containing synthetic failure-injection tests, local symlink/TOCTOU simulations, deliberately inconsistent data structures, and terms such as "forged", "hostile", "bypass", "fail closed", "security/custody ledger", and "authorization".
Environment
- OS: Arch Linux, kernel 7.1.3-arch1-2, x86_64
- Codex CLI: 0.144.6
- Invocation surface: noninteractive codex exec --json
- Originator recorded in session metadata: codex_exec
- Model provider: openai
- Effective model recorded in affected turn contexts: gpt-5.6-sol
- Reasoning effort: xhigh
- Fab: 0.1.0
- Somm: 0.14.0
- Somm Core: 0.14.0
- Python used by Fab service: 3.13.0
Architecture
George creates a bounded software task. Fab creates or reuses an isolated Git worktree and supervises execution, retries, verification, and release. Somm is the
generic one-attempt adapter that invokes the Codex CLI and parses its JSON event stream.
The effective Codex invocation is structurally:
codex exec --json
--dangerously-bypass-approvals-and-sandbox
--skip-git-repo-check
--model <configured model>
--config model_reasoning_effort=<configured effort>
<prompt>
Fab currently asks Somm for allow_unsafe=True; therefore the CLI bypass flag is present. This is the same invocation path used by many successful non-cyber jobs,
so there is no evidence that this flag alone causes the classification. Fab provides repository/worktree isolation and explicit task constraints around the
process.
What the flagged work was actually doing
A. Fab release and worktree integrity
Fab manages autonomous code changes through disposable Git worktrees. We were independently verifying that it cannot:
- publish a queued job before state is durably recorded;
- follow a replaced or symlinked path;
- mistake one repository/worktree for another;
- lose or duplicate work after a simulated crash;
- overwrite a file outside its staging directory;
- publish duplicate GitHub proposals after replay;
- report cleanup success when cleanup failed;
- accept malformed or contradictory local state.
The tests use temporary directories, local Git repositories, monkeypatching, and in-memory HTTP/GitHub adapter mocks. Some tests deliberately replace a temporary
file with a symlink or inject a crash between two local state transitions. These are defensive regression tests for our own code, not attempts to compromise
another system.
B. Keel offline benchmark authorization
Keel is a research system. We were implementing an offline authorization format for a benchmark run. The test constructs a valid local Python dataclass, modifies
one source-cutoff field, serializes the inconsistent request, and proves that the public authorization APIs reject it unless it corresponds to a separately
supplied canonical roster.
The synthetic packet was 115,294 bytes. It contains research task metadata, route/model ceilings, and authorization coordinates. It contains no executable payload
and is never sent to a provider or external service.
The filtered trace included a local Python snippet conceptually equivalent to:
- load local test fixtures;
- copy a dataclass;
- alter one date field;
- serialize the modified object;
- print its size and SHA-256;
- add regression tests proving that validation rejects it.
No benchmark, model call, database write, deployment, external scan, or live research action was performed.
Observed incidents
- Fab job 20260720T042723_a2c0f1
- Created: 2026-07-20 04:27 UTC
- Purpose: fourth independent, read-only verification of Fab release/worktree custody
- Filter events: 3 of 3 attempts
- Prompt size: 9,947 bytes
- Prompt SHA-256: ce7f6ee09c119088f43d1e78f2b4be033f0114e0d27c1e7f0093b0b2388cdc0c
- Threads:
- 019f7dc7-59f6-7251-960a-068f884590bf
- 019f7dcd-dc05-71b1-8a4e-8c766fb81090
- 019f7dd4-3e5c-79f3-941a-072a4cf9a86c
- The prompt asked for a "required hostile audit" of local state handling and named synthetic cases such as malformed JSON, symlink retargeting, forged lease
- identity, crash injection, and fail-closed behavior. One attempt was terminated immediately after Codex created an ephemeral /tmp/.../ test_hostile_independent.py regression-test file. No target repository file or external system was changed.
- Fab job 20260720T181014_a60173
- Created: 2026-07-20 18:10 UTC
- Purpose: second read-only verifier of the same Fab custody branch
- Filter events: 1
- Prompt size: 3,712 bytes
- Prompt SHA-256: 1aa5a7cb69a53e658de3e1091a119575485ca7892ce222e22dd09b751085db85
- Thread:
- 019f80b8-b446-7ad2-8c89-6963d86592c5
- Before termination, Codex ran synthetic local probes:
- a TemporaryDirectory test replacing a staged file with a symlink;
- an in-memory mock checking duplicate GitHub proposal handling;
- the local pytest suite.
- The first full run reached 699 passed / 1 environmental failure. A focused rerun passed. The filter terminated the turn as the corrected full test command
- began. Captured JSON stdout was approximately 1.33 MB.
- Fab job 20260720T183233_80c752
- Created: 2026-07-20 18:32 UTC
- Purpose: third read-only verifier of the same Fab custody branch
- Filter events: 1
- Prompt size: 4,694 bytes
- Prompt SHA-256: 74c6af33211a7e0707f7b310e4ca9622ea3bfeb1ede7b24d071848327b6016d1
- Thread:
- 019f80cd-2379-7b11-ad77-8535011f2e65
- This turn had only inspected local Git state, source code, and unit-test sections dealing with crash recovery, terminal proof, path replacement, and symlinks.
- It was terminated after a large read-only source dump. Captured JSON stdout was approximately 829 KB.
- Keel job 20260721T045227_d9dff8
- Created: 2026-07-21 04:52 UTC
- Purpose: repair an offline benchmark-authorization trust boundary
- Filter events: 3 of 3 attempts
- Prompt size: 13,145 bytes
- Prompt SHA-256: 87b59ef3dad6b592dff15be33b41eca4af116504e531416150e09ffeae0c72b6
- Threads:
- 019f8304-acbb-7e30-b01d-e0c2985b4e80
- 019f830b-d5a8-72f0-9d3b-fa0119d4cf19
- 019f8311-d689-71c1-9178-2b39d3c7b7a0
- The local reproduction changed one dataclass field, serialized an inconsistent offline authorization packet, and added tests requiring a separate canonical
- roster at every trust boundary. In the final attempt, 70 focused tests passed, formatting passed, and the filter terminated the turn when the ordinary full
- pytest -q suite was started. Captured JSON output ranged from approximately 347 KB to 734 KB per attempt.
Total: 8 terminal cybersecurity-filter events across 4 Fab-supervised jobs.
Successful controls
The same code, test families, CLI, model, effort level, and execution adapter also succeeded repeatedly:
- Fab job 20260720T184905_872105 reviewed the same custody branch, ran 302 focused and 709 full tests, and reported several real integrity findings without being
- filtered. Its prompt contained at least as much security-adjacent vocabulary as one of the filtered prompts.
- Keel job 20260721T124538_503003 reviewed the repaired authorization implementation and ran 70 focused and 522 full tests without being filtered. Its prompt still
- referred to typed forgeries and trust boundaries.
- Subsequent Keel jobs ran 112 focused and 590 full tests, including symlink, ownership, path-replacement, authorization, and terminal-privacy cases, without being
- filtered.
This suggests that prompt length, test-suite presence, context size, the Codex model, and individual words are not sufficient causes.
The strongest observed difference was workflow shape:
Filtered:
- large source/test dumps;
- inline construction of synthetic inconsistent objects;
- dynamically authored failure-injection tests;
- local symlink/TOCTOU simulations;
- repeated unchanged prompts after the first safety termination.
Successful:
- exact committed test-node selection;
- ordinary pytest execution;
- neutral "invariant mismatch" terminology;
- no newly authored inline failure probe;
- no replay of a byte-identical filtered prompt.
Retry amplification in our local stack
Our stack amplifies the original classification, although it does not cause the first event.
Somm currently recognizes messages matching patterns such as:
- content filter
- content policy
- refused
- policy violation
The exact Codex message is:
- This content was flagged for possible cybersecurity risk
That phrase does not match Somm's refusal classifier. Somm therefore reports generic FAILED. Fab maps generic FAILED to ERRORED, whose default policy retries
twice.
That explains why two jobs produced three byte-identical failed attempts:
- Fab custody prompt SHA-256 ce7f6e... was retried three times.
- Keel authorization prompt SHA-256 87b59e... was retried three times.
We plan to fix this locally by recognizing the exact message as REFUSED/PERMANENT_INPUT and escalating once. A stable machine-readable Codex error code would be
substantially more reliable than matching English error text.
Other diagnostics
codex doctor reported:
- Codex version 0.144.6
- config and auth loaded
- state databases healthy
- WebSocket connected
- active provider endpoints reachable
- no proxy environment variables
It also reported potentially orthogonal configuration notes:
- mixed ChatGPT-login and API-key signals;
- the running Codex package is from an npm/npx cache path, while global update would target another installation;
- a large local rollout inventory caused an incomplete thread scan.
The same environment produced both successful and filtered jobs, so none of these findings currently explains the content-dependent failures.
Unrelated MCP authentication warnings also appear in both successful and failed Codex sessions, so they do not correlate with the cybersecurity filter.
Expected behavior
For these local defensive software-engineering tasks, Codex should complete normally. If cyber-safety routing is required, we expected a rerouted result and an explicit notice, not a terminal turn.failed event with no usable model result.
Actual behavior
The turn terminates with a plain English cybersecurity message. The JSON event provides no stable machine-readable safety reason code or request ID. Fab/Somm therefore cannot distinguish the event reliably from a generic process/model failure without fragile text matching.
Working through a roadmap for a deep research tool in /goal mode triggers the cybersecurity block. it might be something in the generated test suite. this codex session isn't building the code itself, it's using a homegrown software factory and monitoring the output of that factory to keep tasks going, triage PRs and merge/deploy where viable. This may be in the uploaded thread, but here's what I see before the goal gets blocked:
• Updated Plan
└ M4a is merged with a fresh Fab verifier receipt. Roster ratification is still pending via Roger, so the next safe slice is an offline request authoring/materialization
path that can produce the exact call/route/ceiling packet after the owner answer without executing anything.
✔ Re-ground in Barnowl, Keel, George, Fab, Roger, and prior goal context
✔ Merge benchmark roster, inventory, and review contracts (M1-M3)
□ Propose the exact 60-task roster and request owner ratification
✔ Merge the offline baseline authorization contract (M4a)
□ Build and verify a private offline authorization-request materializer (M4b)
□ Incorporate roster ratification and materialize the exact bounded plan
□ Run and adjudicate the 20-result double review
□ Run two authorized repeatable baselines with complete receipts
□ Publish honest George closure and final milestone evidence
• Ran git show origin/main:keel/research/benchmark_export.py | sed -n '1,520p'
└ """Fail-closed filesystem custody for benchmark inventory artifacts.
… +478 lines (ctrl + t to view transcript)
except OSError:
pass
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
• I’ve found the next bounded gap: M4a can validate an in-memory request, but Keel still lacks a safe authoring/materialization path for the exact two-run action list and call
ceilings. I’m commissioning M4b through George→Fab as an offline-only private packet writer—generic fixtures only, no roster read, database access, provider call, or
execution.
• Ran git show-ref --verify --quiet refs/heads/fab/keel-benchmark-authorization-materializer-v1 && exit 3 || true
│ test -z "$(git ls-remote --heads origin refs/heads/fab/keel-benchmark-authorization-materializer-v1)"
│ payload=$(jq -nc \
│ … +53 lines
└ {"registered":{"id":"01KY2C94PH61QZ46YCG7B5DG0T","ts":"2026-07-21T13:01:42Z","path":"/home/lavallee/projects/Central/.george/inbox/
codex-goal-runner/2026-07.jsonl"},"planned":{"id":"01KY2C95RF72X4KT1PG6MFFTA3","ts":"2026-07-21T13:01:44Z","path":"/home/lavallee/projects/Central/.george/inbox/
codex-goal-runner/2026-07.jsonl"}}
ⓘ This content can't be shown
We take extra caution with cybersecurity requests. If you’re a security professional, you may be able to apply for Trusted Access.
Trusted Access: https://openai.com/form/enterprise-trusted-access-for-cyber/
Learn more: https://help.openai.com/en/articles/20001326
• Feedback uploaded. Please open an issue using the following URL:
Or mention your thread ID 019f8055-d446-7fc0-9ac1-9129548ee4cb in an existing issue.
What steps can reproduce the bug?
Uploaded thread: 019f8055-d446-7fc0-9ac1-9129548ee4cb
What is the expected behavior?
I imagine we'll be living with these types of flags for the foreseeable future. I think it would be great if these exceptions were raised in a more machine-friendly way, at least when codex is being run non-interactively.
Additional information
_No response_
4 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Thanks for reporting. We're continuing to refine our classifiers.
This issue helped me design a prompt to avoid repeatedly encountering these cybersecurity hard failures while attempting what I assumed would have been a straightforward git bisect of openblas, so thank you!
This is still reproducible on
codex-cli 0.145.0, Windows,gpt-5.6-solxhigh, in a Codex Desktop collaboration subagent.A benign local compiler-runtime unit-test task was hard-stopped with exactly:
The task was entirely local in the user's own repository: reproduce a Rust unit-test abort, identify the failing lifecycle invariant, improve the local Cargo test wrapper's timeout/diagnostics, and add tests. There was no network target, credential work, scanning, exploitation, or third-party system.
The likely lexical trigger was ordinary systems-testing language such as
SIGABRT,signal/exit status,process guard,per-test isolation, andtimeout. The failure killed the subagent turn and left its worktree WIP stranded. I immediately resent the same engineering scope phrased as “benign local software-quality/unit-test debugging” and it resumed successfully without any other change.This is especially damaging in multi-agent mode because the hard failure looks like a crashed worker and requires orchestrator recovery/signal preservation. Please reopen or link to the active classifier issue; defensive local crash/lifecycle testing should not hard-stop as cyber risk.