Security audits with Codex
PLA security audit with Codex runs deterministic scanners first, then parallel read-only codex exec audits, one per security domain, and merges their findings. Each accepted finding gets an exploit test that fails before the fix, and the fix runs in its own Git worktree. AGENTS.md review rules and a scheduled sweep stop the same classes from returning.
A security researcher has filed a responsible disclosure: your API returns stack traces in production error responses, and the password reset endpoint tells an attacker which email addresses have accounts. The report goes public in 48 hours. You need to fix those two, find every sibling of them in the codebase, and make sure the next pull request cannot reintroduce them. This page is for the developer who runs that audit with Codex and the tech lead who owns the gates afterwards.
What you’ll walk away with from a Codex security audit
Section titled “What you’ll walk away with from a Codex security audit”- A seven-step audit order, from containing live secrets to scheduling the next sweep.
- A shell loop that runs three domain audits in parallel under the
:read-onlypermission profile, so no audit can edit what it judges. - Six copy-paste prompts: targeted investigation, three domain audits, a merge-and-dedupe pass, and an exploit-test-first fix.
- A rule for accepting fixes without reading every diff line: no failing exploit test, no fix.
- A security block for the
## Code Review Rulessection ofAGENTS.md, with “Do not flag” lines that keep the noise down.
This page covers the hands-on audit you drive from the Codex CLI. OpenAI’s Codex Security agent, @codex security review and the finding-to-merge lifecycle are covered in Codex Security and the agents command center; the CI gate built on openai/codex-action is in Codex in CI/CD.
Which Codex tool fits which part of the audit?
Section titled “Which Codex tool fits which part of the audit?”Each part of an audit needs a different level of access. Checked against Codex CLI 0.157.1 on 2026-09-26, except the two GitHub surfaces, which were last verified on OpenAI’s docs on 2026-08-28.
| Part of the audit | Tool | Access it needs | What you get |
|---|---|---|---|
| Secrets, known-vulnerable packages, rule-based patterns | Gitleaks, TruffleHog, npm audit, Semgrep (not Codex) | Your shell and the network | Deterministic reports Codex can reason over |
| Investigating a reported issue or one security domain | codex exec with -c 'default_permissions=":read-only"' | Read the repository, no writes, no network | A findings report per domain |
| Confirming a finding and fixing it | codex --worktree with the :workspace profile | Write inside an isolated checkout | A failing exploit test, then a fix on a branch |
| Checking a branch before it becomes a pull request | codex exec review or /review | Read the diff | Review findings steered by AGENTS.md |
| Checking a pull request | @codex security review on GitHub | Codex’s GitHub connection | Security-focused review comments |
| Repeating the sweep | A Codex desktop app automation, or codex exec from cron | Same as the domain audit | A daily report of new findings only |
The default model in Codex is GPT-6.1 Sol, which runs at low effort unless you change it (see the models hub). An audit traces input across many files, so raise effort for the audit runs with -c model_reasoning_effort="high" before you consider a different model.
How to run a Codex security audit, step by step
Section titled “How to run a Codex security audit, step by step”The order matters. Containment comes first, because a leaked key is being abused while you read the report. Scanners come before Codex, because their output is ground truth the agent can reason over, and the read-only profile gives Codex no network to run them itself.
-
Contain live secrets and give Codex a clean copy. Run the audit in a fresh clone of the repository. A fresh clone has no gitignored
.env, so the audit sessions do not read the credentials in your local.env; committed secrets are what step 2 finds. To audit code you do not trust, such as a vendor’s repository, choose Open restricted at Codex’s “Trust this folder?” prompt: config, hooks and exec policies from an untrusted folder stay disabled, and since Codex 0.150.0 an untrusted project does not supply itsAGENTS.mdeither.Terminal window git clone --no-local . ../app-audit && cd ../app-audit -
Run the deterministic scanners and keep their output. Install the scanners first, for example
brew install gitleaks trufflehog semgrep jq(orpip install semgrep). You need Gitleaks 8.19.0 or later: that release added thegitsubcommand, and older versions only knowdetect(checked against the Gitleaks releases on 2026-09-26). Then, in a terminal at the root of the audit clone:Terminal window mkdir -p auditgitleaks git --redact --report-path audit/gitleaks.json # secrets in full git history, values maskedtrufflehog git file://. --results=verified,unknown --json \| jq -c 'del(.Raw, .RawV2)' > audit/trufflehog.json # live check against the issuing service; raw values strippednpm audit --omit=dev --json > audit/npm-audit.json # advisories in production dependenciessemgrep scan --config auto --json -o audit/semgrep.json # rule-based patterns; auto sends your project URL to the Semgrep RegistryBoth reports keep the raw secret by default.
--redactmasks it in the Gitleaks report, and thejqfilter drops theRawandRawV2fields from each TruffleHog result, because Codex reads these files in step 4 and anything it reads goes to the model provider. The commit, file and detector name are still there, which is all the audit needs.Any secret TruffleHog reports as verified is live. Rotate it now, before anything else on this page. Codex cannot revoke a credential, and a secret that reached a pushed commit stays compromised after a history rewrite, because forks, clones and CI caches keep copies.
-
Investigate the reported issues first, read-only. Paste the first prompt below into
codex -c 'default_permissions=":read-only"'. It maps the reported vulnerabilities to code and proposes fixes without applying them, so you have a written plan for the disclosure deadline within the first hour. -
Run the domain audits in parallel. Save the three domain prompts below as
.codex/audit/input-validation.md,.codex/audit/authz.mdand.codex/audit/deps-config.md, then start all three at once:Terminal window for domain in input-validation authz deps-config; docodex exec \-c 'default_permissions=":read-only"' \-c model_reasoning_effort="high" \-o "audit/$domain.md" - < ".codex/audit/$domain.md" > "audit/$domain.log" 2>&1 &donewaitRead-only audits do not need worktrees: none of them writes to the checkout, so all three can share it.
codex exechas no-ain 0.157.1 and needs none: it runs with approvalnever, so a command that needs more access fails instead of waiting for an approval nobody is there to give.-owrites each session’s final report to a file, and-reads the prompt from standard input. -
Merge the reports into one list. Run the consolidation prompt below. Three audits find overlapping issues from different angles, and a single list with one ID per finding is what you triage, assign and close.
-
Confirm each finding with a failing test, then fix it in a worktree. For every critical or high finding, start an isolated session with
codex --worktree -c 'default_permissions=":workspace"'and paste the exploit-test-first prompt. Each finding gets its own worktree and branch, so fixes land as separate, reviewable pull requests. The Codex worktrees guide covers bootstrapping a worktree so the test suite runs in it. -
Lock the gates. Add the
AGENTS.mdrules below, runcodex exec reviewbefore every push that touches a risky path, request@codex security reviewon pull requests (setup in code review with Codex), add the structured security gate from Codex in CI/CD, and schedule the daily sweep.
Copy-paste prompts for a Codex security audit
Section titled “Copy-paste prompts for a Codex security audit”Every prompt tells Codex to treat repository content as data. OWASP’s GenAI LLM Top 10 2026 (GenAI Security Project, published 2026-08-04) lists “a public GitHub issue, a support ticket, or a malicious npm package” among the places attackers plant instructions for agents, and an audit reads all of them.
Save the merge prompt as .codex/audit/merge.md and run it with the :workspace profile, not :read-only, because it writes audit/findings.md:
codex exec -c 'default_permissions=":workspace"' - < .codex/audit/merge.mdKeep audit/ out of Git by adding it to .git/info/exclude in the audit clone: the reports describe exploitable paths in your code.
How do you verify security fixes without reading every line?
Section titled “How do you verify security fixes without reading every line?”An audit is only useful if you can accept its output on evidence. These checks replace line-by-line review of each fix.
| Evidence | What it proves | Who signs off |
|---|---|---|
Exploit test in tests/security/ that failed before the fix and passes after | The finding was real and is closed | The security owner for that path, not the fix author |
| Full test suite and type check green on the fix branch | The fix did not change legitimate behaviour | CI, as required checks |
Scanners rerun clean: Gitleaks, and npm audit --audit-level=high exits zero | No secret left in HEAD, no high advisory left unpatched | CI |
| The domain audit rerun on the fixed branch no longer reports the finding | The class is gone, not only the one instance | Developer who ran the audit |
Every “Do not flag” line in AGENTS.md has a written reason | A false positive was judged, not ignored | Tech lead |
A human still reads two short things: the exploit test (does it attack what the finding describes?) and every suppression. The fix itself is judged by the test, the suite and the rescan. The finding-state table and sign-off rules for a team are in Codex Security and the agents command center.
To check the auditor itself, plant known defects once a quarter: a throwaway branch with string-built SQL, a route without an ownership check and a hard-coded token. Run the three domain audits against it. The number of planted defects they report is your baseline, and a drop after you change a prompt or the AGENTS.md rules is a regression.
Encode the audit’s rules in AGENTS.md
Section titled “Encode the audit’s rules in AGENTS.md”Local reviews (/review, codex exec review) read the applicable AGENTS.md files (Codex 0.157.1); GitHub reviews look for the ## Code Review Rules section (OpenAI docs, checked 2026-10-12; the 2026-08-28 check named it ## Review guidelines). Put the rules under that heading and one rule serves both. The AGENTS.md guide covers where the file loads. Turn the findings from this audit into rules a reviewer can check from a diff:
## Code Review Rules
### Security- P0: an error handler that returns err.stack, err.message from an internal error, file paths or SQL text to the client. Log them; return { error: "internal" }.- P0: SQL or NoSQL queries built with template literals or + concatenation.- P0: a route under src/routes/ that loads a record by an ID from the request without requireOwnership() or requireRole().- P0: a secret, token or private key literal in any file, including tests.- P1: auth endpoints (login, register, reset-password) without the rate limiter, or with responses that differ for known and unknown accounts.- P1: a new dependency that is not already in package.json; check that the name exists on the registry and is the package the author meant.- Do not flag: Drizzle .where() calls with bound values; they are parameterized.- Do not flag: fake credentials under tests/fixtures/.- When you report a finding, name the rule above that it violates.The dependency rule is there because OWASP’s LLM04 Supply Chain entry (GenAI LLM Top 10 2026) warns that coding assistants “hallucinate plausible but nonexistent package names”, which attackers register in advance, a practice it calls “slopsquatting”.
Before each push that touches src/routes/, src/middleware/ or src/auth/, run a review against the base branch:
codex exec review --base main -o review.mdIn Codex 0.157.1, --base, --uncommitted and --commit cannot be combined with custom review instructions: codex exec review --base main "focus on security" fails with the argument '--base <BRANCH>' cannot be used with '[PROMPT]'. That is why the security rules belong in AGENTS.md, where the preset review modes read them, rather than in a prompt.
Schedule a daily security sweep
Section titled “Schedule a daily security sweep”A one-off audit decays as soon as the next pull request merges. A daily sweep reports only what changed. Run it as an automation in the Codex desktop app, or from cron on an always-on host with the same codex exec -c 'default_permissions=":read-only"' command as the domain audits. The Codex automations guide covers where a scheduled job should run and how to test the prompt before you schedule it; scheduled security scans covers retaining the evidence.
Regenerate audit/npm-audit.json in the job before Codex runs, since the read-only profile has no network. The exact “nothing new” line lets a script or a reader tell a clean run from a failed one at a glance.
When a Codex security audit goes wrong
Section titled “When a Codex security audit goes wrong”The domain audits stop with permission errors. Under :read-only, commands that write or reach the network fail, and codex exec, which runs with approval never, returns the failure instead of asking. Recovery: run the command yourself (a scanner, a dependency install) and point the prompt at its output file. Do not switch the audit to :workspace or bypass the sandbox to get past it.
codex exec review rejects your security instructions. In 0.157.1 the --base, --uncommitted and --commit modes take no prompt. Recovery: move the instructions into the ## Code Review Rules section of AGENTS.md, or run codex exec with a prompt that names the diff (“review the changes on this branch against origin/main”).
Codex flags parameterized queries as SQL injection. It does not know your ORM binds values. Recovery: add a “Do not flag” line naming the ORM call, as in the AGENTS.md block above, and keep the rule that forbids template-literal SQL.
Two runs of the same audit report different findings. Model-based audits are nondeterministic. Recovery: treat the merged audit/findings.md as the record, rerun only the domain whose result you doubt, and let the planted-defect branch tell you whether a prompt change helped.
A finding is “confirmed” by argument, with no test. The session writes a convincing explanation instead of a failing test. Recovery: send it back with “write the failing test first; no explanation without it”, and do not open a pull request for that finding until the test exists.
A dependency upgrade breaks the build. The fixed version has breaking changes. Recovery: read the breaking-changes list from item 1b of the deps-config.md audit before upgrading, upgrade one package per commit, and leave NOT REACHABLE advisories on a tracked backlog instead of this week’s work.
The daily sweep repeats the same accepted findings. Every report lists the same medium advisories you triaged last month, and the team stops reading it. Recovery: record each accepted advisory ID with a reason and an expiry date in .security-ignore.json, and keep the prompt’s “only report IDs not in the ignore file” rule.
An audited repository runs its own hooks. Trusting a vendor’s repository to audit it enables its config, hooks and exec policies. Recovery: audit untrusted code in its own clone and choose Open restricted. A session that ran while the folder was trusted can keep that configuration, so start a new session after changing trust.
How do Claude Code and Cursor handle the same audit?
Section titled “How do Claude Code and Cursor handle the same audit?”This page stays on Codex. Claude Code has /security-review and the Claude Security plugin, covered in security audits with Claude Code. Cursor’s security review features are covered in security in Cursor. The tool-neutral version of this workflow, with scanners as CI gates and any of the three agents triaging their output, is security operations automation.
Where to go next after a Codex security audit
Section titled “Where to go next after a Codex security audit”Back to the Codex Operate overview.