Audit your codebase read-only, CWE-grounded
Claude reads the codebase and dependency manifests, writes a structured security audit plan with CWE, CVE, and GHSA references. Codex validates each finding and surfaces what Claude missed. Claude finalizes. Fixes only happen after your explicit go-ahead.
- OWASP Top 10 + CWE
- GHSA / NVD-grounded
- No auto-fixes
Usage
Audit scope is optional. With no path arg, codexgrill audits the whole repo. Pass one or more paths to scope.
One pass. Claude reviews the codebase, writes the audit plan, Codex validates and extends,
Claude finalizes, presents via ExitPlanMode (or asks for go-ahead before applying fixes).
/codexgrill:security-once # whole repo
/codexgrill:security-once src/auth # scope to one path
/codexgrill:security-once src/auth src/billing # multiple paths
/codexgrill:security-once src/auth --effort=high# paths + flags
/codexgrill:security-once --model=gpt-5.4 # override model
Also reachable via the router: /codexgrill:once → pick "Security audit".
The plan file is written to .claude/plans/security-audit-<ts>.md.
Iterate until clean. Loops Codex review + Claude validation + plan edits until Codex says
AUDIT CLEAN and Claude finds nothing missed, or --max rounds run out.
/codexgrill:security-loop # whole repo
/codexgrill:security-loop src/auth # scope to one path
/codexgrill:security-loop --max=10 # bump the cap (default 7)
/codexgrill:security-loop --effort=xhigh # override reasoning effort
/codexgrill:security-loop --model=gpt-5.4 # override model
Pins Codex to one thread, sends unified diffs after iter 1. Same convergence rules as the plan loop —
both models must agree the audit is clean. Also reachable via the router: /codexgrill:loop
→ pick "Security audit".
What you'll see in chat
Claude reads the codebase + dependency manifests, queries advisory sources (GHSA, NVD), writes the audit plan to .claude/plans/security-audit-<ts>.md.
Verbatim. First-line verdict (AUDIT CLEAN / NEEDS REVISION / CRITICAL ISSUES), then per-finding CONFIRMED / REFUTED / EXTENDED, plus any new findings Claude missed.
Claude re-reads each cited file. Codex's findings get CONFIRMED / REFUTED / UNVERIFIABLE. UNVERIFIABLE → flagged in chat.
In plan mode: ExitPlanMode with the audit. Otherwise: "Review the plan. Should I proceed with the fixes?" Fixes only run after explicit yes.
How it works
Four phases. Claude does the first review (no Codex yet); Codex validates and extends; Claude finalizes; the user gets the final call on fixes.
-
1
Claude reviews the codebase
Claude reads the scoped files, dependency manifests (
package.json,requirements.txt,go.mod, etc.), and runsWebSearch/WebFetchagainst authoritative advisory sources (GHSA, NVD, vendor advisories). Categories: injection, auth flaws, broken access control, crypto failures, hardcoded secrets, SSRF, path traversal, deserialization, XSS, CSRF, race conditions, missing security headers, vulnerable dependencies, CORS misconfig, more — all anchored to OWASP Top 10 + CWE. -
2
Codex validates and extends
The wrapper sends Claude's plan to
codex execwith a validate-and-extend prompt. Codex checks each finding against the actual code, marks it CONFIRMED / REFUTED / EXTENDED, and adds NEW findings Claude missed. All grounded inpath:linecitations and primary-source CVE/GHSA links. -
3
Claude validates Codex's response
For every finding Codex returns (validation + new), Claude invokes
Readon the cited file. Codex's verdict gets CONFIRMED / REFUTED / UNVERIFIABLE by Claude. No memory shortcuts. External claims hit primary sources viaWebSearch/WebFetch. -
4
The audit plan is updated
CONFIRMED findings stay in the plan with concrete fix recommendations. REFUTED ones are dropped. UNVERIFIABLE items flagged. In
security-loopmode this repeats with a pinned Codex thread until both models agree the audit is clean (Codex says AUDIT CLEAN + Claude finds nothing missed). -
5
Present — and only fix on go-ahead
In plan mode:
ExitPlanModewith the audit. You approve through the normal plan-mode UX. In normal chat: Claude asks "Review the plan. Should I proceed with the fixes, or do you want to make changes first?" Fixes only happen after an explicit yes — never auto-applied. When the audit is empty (zero findings), the "should I proceed?" prompt is skipped entirely.
Findings format
The audit plan file at .claude/plans/security-audit-<ts>.md follows a strict structure
— copy-pasteable fixes, CWE refs, primary-source advisory links.
Severity scheme
Findings are tagged Critical / High / Medium / Low / Info + a CWE category reference. We don't compute CVSS for in-code findings (CVSS requires environment context the auditor doesn't have — "is this internet-facing? does the user already have auth?"). CVSS scores are quoted only when they come from an upstream CVE / GHSA advisory.
Sample finding
### [CRITICAL] Hardcoded API key in source
- **CWE**: CWE-798 ([Hardcoded Credentials](https://cwe.mitre.org/data/definitions/798.html))
- **Location**: `src/auth/client.ts:42`
- **Evidence**:
```ts
const STRIPE_KEY = "sk_live_REDACTED_EXAMPLE";
```
- **Why it's vulnerable**: Live secret committed to source. Anyone with repo
read access (employees, contractors, leaks) can drain the account.
- **Recommended fix**:
```ts
const STRIPE_KEY = process.env.STRIPE_SECRET_KEY;
if (!STRIPE_KEY) throw new Error("STRIPE_SECRET_KEY required");
```
- **References**:
- [OWASP Secrets Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html)
- Rotate the key immediately at https://dashboard.stripe.com/apikeys
Sample dependency finding
### [HIGH] [email protected] — CVE-2024-29041
- **Severity**: GHSA: Moderate, CVSS 6.1
- **Advisory**: [GHSA-rv95-896h-c2vc](https://github.com/advisories/GHSA-rv95-896h-c2vc)
- **Fixed in**: 4.19.2
- **Recommended action**: bump to `^4.19.2` and run `npm audit`.
Containment & revert
The security wrapper enforces read-only with the same mechanisms as the plan flow, plus one extra check specifically for the audit plan file.
1. SHA256 working-tree containment
The wrapper hashes every Git-visible dirty + untracked path before and after every Codex call. Any change → exit 2 (WORKING_TREE_CHANGED), loop halts, you decide.
2. Explicit plan-file SHA256
The audit plan lives at .claude/plans/security-audit-<ts>.md, which is under gitignored .claude/. The git-status snapshot wouldn't see mutations there — so the security wrapper hashes the plan file directly, pre and post. Any change → exit 2 with the plan path in changedFiles.
3. Prompt-level read-only contract
The audit prompt's <action_safety> block explicitly tells Codex any modification — including to the plan file — will cause the run to be REJECTED.
4. User approval before fixes
The plugin never auto-fixes. Either ExitPlanMode hands the audit to the user (plan mode), or Claude asks explicitly: "Should I proceed with the fixes?" No fix runs without an explicit yes.
Revert safety net
Same as the plan flow: each iteration builds a content snapshot pinned under
refs/codexgrill/<run-id>/iter-<N>-pre. Revert with:
git restore --source=<preIterStash.hash> --staged --worktree -- :/
git clean -fd
One thing the revert does NOT cover
The audit plan file at .claude/plans/security-audit-<ts>.md is gitignored, so a working-tree revert does not restore its contents. The pre/post hash check still detects mutations to the plan file (and you can see the changed bytes), but recovering the prior plan body means re-running the audit or restoring from a separate backup.
Run artifacts
Every run drops artifacts under .claude/temp/codexgrill/<run-id>/ (gitignored).
The audit plan itself lives at .claude/plans/security-audit-<unix-secs>.md.
security-once runs
| file | description |
|---|---|
prompt.txt | Exact prompt sent to Codex. |
final.txt | Codex's final validation message (raw — JSON when structured-output is in effect, plain markdown on fallback). |
codex.jsonl | Full JSONL event stream from codex exec. |
result.json | Wrapper summary — thread_id, exit_code, token usage, paths, preIterStash hash, plus planHashBefore / planHashAfter / planFileChanged for the plan-file containment check. |
findings.json | Parsed structured-output JSON from Codex (verdict + validation[] + newFindings[] + externalRefsChecked[]). Schema: scripts/lib/schemas/security-findings.json. |
quote-validation.json | Per-finding quote-match summary — total, matched, skipped, lineDrift, unverified, outOfScope. |
review.md | Rendered markdown with [line_drift] / [unverified_citation] tags. This is what gets written to stdout; persisted for truncation-recovery. |
security-loop runs
Each artifact above gets an -iter<N> suffix, plus:
| file | description |
|---|---|
state.json | Run state — pinned codex_thread_id, audit_scope, per-iter verdicts, validation counts. |
refuted-log.txt | Cumulative refutations, prepended to each iteration's prompt. |
plan-snapshot-iter<N>.md | Verbatim copy of the audit plan sent to Codex in iter N. Baseline for iter N+1's diff. |
plan-diff-iter<N>.diff | Unified diff of audit-plan changes vs the prior iter's snapshot. |
Tuning for large audits
codex exec has no auto-compaction — a single audit turn that overruns the per-turn context window
aborts with an error instead of retrying. Security audits over a whole repo are particularly prone to this.
If you see "Codex ran out of room in the model's context window":
- The most common cause is
model_reasoning_effort = "xhigh"in~/.codex/config.toml. Reasoning tokens count toward the per-turn budget. - Pass
--effort=highto override the config for this run only (one notch belowxhigh— usually frees enough context without giving up reasoning depth). Valid levels:none,minimal,low,medium,high,xhigh. - Or narrow the scope: pass explicit
--scopepaths instead of running on the whole repo. Audits scale roughly with the size of the audited source.
No silent retries
The plugin never auto-retries on context exhaustion or rate-limit errors. It surfaces the diagnostic and waits for your call. No surprise extra spending.
Want to grill a plan instead?
codexgrill also reviews implementation plans before you write the code. Same safety contract, same convergence rules.