codex-adversarial-tenderly-auditor
Skill1 starsChanged 5 months agoMITView on GitHub
Adversarial follow-up to /claude-tenderly-auditor. Reads the defensive AUDIT_REPORT.md produced by that skill and asks Codex CLI to challenge every PASS row, propose attack vectors against the surfaced risks, and attempt to weaponize the staging artefacts (mock oracle crashes, setStorageAt slot writes, impersonated CCTP messages) into demonstrable exploit paths on the same vnet.
In this repository22 other files it gives its agents.
- AGENTS.mdAGENTS.md
- .agents/skills/vercel-react-best-practices/AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- agent-browserSkill
- ai-sdkSkill
- baseline-uiSkill
- chat-sdkSkill
- claude-tenderly-auditorSkill
- code-reviewSkill
- codex-adversarial-review-tenderly-testnetSkill
- deploy-open-harnessSkill
- emil-design-engSkill
- frontend-designSkill
- gateman-analysisSkill
- plan-modeSkill
- raj-demand-driven-contextSkill
- remove-demo-limitsSkill
- tenderly-proSkill
- tenderly-testnetSkill
- vercel-react-best-practicesSkill
- web-animation-designSkill
- workflowSkill
The file
We split this skill into the rules it gives an agent
7 rules. About 0 are common, 5 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈5
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 65
If the user invokes this without a defensive report present, STOP and ask which protocol/vnet should be audited — there is no useful …
- Very specific: line 78
Active vnet matches the report: Read mcp__tenderly__get_vnet and confirm vnet_id matches the report header.
- Very specific: line 97
Read the §Staging Artefacts table from AUDIT_REPORT.md
- Distinctive: line 235
Do not fix issues raised. That's the implementation phase, separate from this audit.
- Distinctive: line 241
Update the sign-off table:
- Distinctive: line 248
If Codex's adversarial pass surfaces any High or Critical finding that BROKE a defensive PASS:
- Distinctive: line 256
Update the defensive Summary table row from PASS → PASS (defensive) / BROKEN (adversarial) so the asymmetric result is visible at a glance
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Codex Adversarial Tenderly Auditor
Sibling to /claude-tenderly-auditor. Reads its AUDIT_REPORT.md
artefact, points Codex at the live vnet, and asks Codex to break the
defensive baseline.
When to invoke
User-driven only — this skill is opt-in and triggered after the defensive audit lands. Common entry points:
- "Run the codex adversarial pass on
reports/AUDIT_REPORT.md" - "Challenge every PASS in the audit"
- "Try to weaponize the surfaced risks into a real exploit"
If the user invokes this without a defensive report present, STOP and ask which protocol/vnet should be audited — there is no useful adversarial pass without a baseline.
Prerequisites
- A defensive
AUDIT_REPORT.mdexists atreports/AUDIT_REPORT.md(or path passed in args). Read it first; the report contains the snapshot IDs, staging artefacts, and risk rows the adversarial pass will target. - Tenderly MCP authenticated in the current session
(
mcp__tenderly__list_projectsreturns). - Codex CLI available via
~/.claude/skills/codex/runtime. - Active vnet matches the report. Read
mcp__tenderly__get_vnetand confirmvnet_idmatches the report header. If mismatched, ABORT and ask which vnet to use.
Step 0 — Safety gate
Identical to /claude-tenderly-auditor:
mcp__tenderly__get_vnet→fork_config.network_id- Match against allow-list. Refuse on any mainnet ID with the network_id in the error.
- Refuse if the report header references a mainnet network_id (someone handed you a bogus defensive report).
Step 1 — Restore from defensive snapshot
The defensive audit ran a sequence of staged mutations. To run the adversarial pass on the same starting state:
- Read the §Staging Artefacts table from
AUDIT_REPORT.md mcp__tenderly__revert_vnet(snapshot_id=<entry #1 in table>)— clean fork- Re-apply staging artefacts in order (re-fund whale, re-install mock oracle / mock transmitter). Use the canonical Bash+MCP commands from the report's §Reproducer block.
mcp__tenderly__snapshot_vnet→ new adversarial-base snapshot. Cite in the appended findings section.
This gives Codex a deterministic starting point identical to the defensive baseline.
Step 2 — Build the Codex prompt
Compose the prompt with these sections (in order):
2a. Inheritance block
You are running an ADVERSARIAL audit pass over a defensive baseline.
The defensive auditor (Claude /claude-tenderly-auditor) ran the stress
matrix at <vnet_id> and produced reports/AUDIT_REPORT.md. Your job is
to CHALLENGE every PASS row and propose attack vectors against the
surfaced risks.
You have full Tenderly MCP access. Test your hypotheses against the
LIVE vnet — do not just reason from the diff.
Hard rules:
- TESTNET ONLY (network_id ∈ allow-list above).
- Snapshot before any destructive op. Use Pattern G branching.
- Append findings to reports/AUDIT_REPORT.md under an "Adversarial
Findings" section. Do NOT rewrite the defensive sections.2b. Defensive report verbatim
Paste the entire AUDIT_REPORT.md content. Codex needs:
- Snapshot IDs (to revert/branch)
- Staging artefacts table (to know what's mocked)
- Storage layout pins (to know what slots are valid
setStorageAttargets) - Risks surfaced (the seed list for adversarial exploitation)
- Trace links + state-snapshot tables (to know what "normal" looks like)
2c. Adversarial agenda
Append these standing challenges (every adversarial pass MUST address each; user-supplied additions go on top):
- PASS rows as preconditions for attack. For each PASS, ask: "What
precondition does this PASS implicitly assume, and can I violate it?"
E.g., Case S1 PASS assumes the wrapper is empty at first deposit —
try inflation-attack the first deposit by racing a direct USDC
transferto the wrapper before any user'sdeposit(). - Weaponize the staging artefacts. The mock oracle / mock transmitter / setErc20Balance writes are AUDIT ARTEFACTS, but they also represent capabilities an attacker has IF they ever land in production (e.g., a governance takeover swapping the oracle, or a compromised relayer). For each artefact: assume the attacker has that capability and attempt to drain funds.
- Compose risks. The defensive report lists risks in isolation. Adversarial pass: try chaining two-or-more risks. E.g., R3 (4.38% bonus vs 5% assumption) + R4 (bad-debt rounding) — does the combination create a MEV path where a liquidator can profit by over-liquidating at the boundary?
- Out-of-scope items as primary attack surface. Cases marked BLOCKED or DEFERRED in the defensive report are NOT proven safe — they're untested. Try to construct the missing dependency (e.g., deploy a stub UniV4 PoolManager for S4) and run the adversarial case Codex believes is most dangerous.
- Trace divergence. For every Codex hypothesis: run the actual tx
through
simulate_vnet_transactionand link the trace URL. A hypothesis without an on-chain trace is a guess, not a finding. - Severity downgrade attempt. For every Critical / High risk in the defensive report: try to prove it's actually Medium or Low by running the realistic-precondition path on-chain. If Codex can't trigger it under realistic conditions, downgrade with justification.
2d. Output format
Codex must output findings using the same severity rubric and table
schema as the defensive AUDIT_REPORT.md (no "Theoretical" tier —
actionable rows only, with explicit preconditions). Findings go in a
new section appended to the report:
## Adversarial findings (Codex pass)
**Pass date:** {{ISO date}}
**Codex run id:** {{...}}
**Adversarial-base snapshot:** {{snap_id_from_step_1}}
### Challenged PASS rows
| Defensive case | Defensive result | Adversarial verdict | Trace |
| -------------- | ---------------- | ---------------------------- | ----- |
| S1 | PASS | UPHELD / **BROKEN — see F1** | ... |
| ... | ... | ... | ... |
### New findings
| # | Class | Severity | Surface | One-liner | Preconditions | PoC trace | Recommended check |
| --- | --------- | ---------------------------- | --------------- | --------------- | --------------------------- | ---------- | ----------------- |
| F1 | {{class}} | {{Critical/High/Medium/Low}} | `{{path:line}}` | {{description}} | {{realistic preconditions}} | `0x{{tx}}` | {{patch or test}} |
### Severity reassessments of defensive risks
| Defensive # | Defensive severity | Adversarial verdict | Justification |
| ----------- | ------------------ | ------------------- | ------------- |
| R3 | Operational | UPHELD | ... |
| ... | ... | ... | ... |Step 3 — Invoke Codex
# Codex CLI runtime is at ~/.claude/skills/codex/
node "${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/skills/codex}/scripts/codex-companion.mjs" \
adversarial-review \
--include-file reports/AUDIT_REPORT.md \
--include-file /tmp/storage-layouts/*.txt \
"$(cat /tmp/codex-adversarial-prompt.txt)"The Codex runtime has its own session continuity — for multi-turn
challenges, use /codex:consult follow-ups.
Step 4 — Hand-off Codex output verbatim, append to report
Per /codex:adversarial-review rules:
- Return Codex stdout exactly as-is. Do not paraphrase or summarize.
- Do not fix issues raised. That's the implementation phase, separate from this audit.
- Append Codex output under the
## Adversarial findings (Codex pass)heading inreports/AUDIT_REPORT.md(or write toreports/AUDIT_REPORT_ADVERSARIAL.mdif the user prefers a separate file). - Update the sign-off table:
| Adversarial pass | ☑ Complete — see §Adversarial findings |
Step 5 — Re-run defensive cases against new findings
If Codex's adversarial pass surfaces any High or Critical finding that BROKE a defensive PASS:
- Snapshot before re-test
- Re-run the affected defensive cases under the adversarial preconditions
- Append the re-run state tables to the affected
## Case S{{N}}sections — clearly marked "Adversarial re-test" - Update the defensive Summary table row from PASS → PASS (defensive) / BROKEN (adversarial) so the asymmetric result is visible at a glance
Patterns Codex should be primed to challenge
Append these standing prompts to §2c unless the user already covered them:
- First-depositor race on ERC-4626 wrappers — even if hub flow "guarantees" the first deposit is bridged, what if a direct USDC transfer lands first? Inflation-attack the share-price ratio.
- Oracle compromise → liquidation cascade — assume governance
takeover or compromised oracle signer. Use
tenderly_setCodeto simulate a price spike or crash in one block; chain multiple liquidations; measure realized bad debt and supplier haircut. - CCTP V2 hookData malleability — the hub receiver binds
hookData == keccak(abi.encode(beneficiary, hubCalldata)). Codex should try constructing ahubCalldatathat is benign on inspection but pulls USDC to a controlled address viatransferFromafter the receiver'sforceApprovewindow (race-condition class). - Liquidation bonus economics — at 4.38% bonus (Morpho LIF, not the brief's assumed 5%), what's the keeper-loss line for a 1B liquidation? Can an attacker grief liquidations by frontrunning the keeper's repay tx with a smaller, profit-extracting liquidation?
- Stranded-deposit grace window MEV — at 1000 stranded entries, can a malicious beneficiary sweep their entry AND inject a new stranded entry at the same nonce slot via storage collision? Verify slot derivation from Step 0.5 layout dump.
- Bad-debt socialization order — when N positions go underwater in one block, does the order of liquidations affect the realized haircut per supplier? If yes, that's MEV.
- uint96 truncation on extreme messages — even if Circle caps real
burnAmount, can Codex construct a CCTP message with mintedAmount
above 2^96 that truncates silently in
uint96(minted)? The mock transmitter can be reconfigured to mint > 2^96 — try it.
Rules
Security
- TESTNET ONLY. Mainnet network_id = HARD REFUSE.
- NEVER echo admin-RPC URLs containing vnet UUIDs in the public report. Redact identically to the defensive pass.
- NEVER propose attacks against live mainnet contracts. The adversarial pass is a thought experiment on the vnet only.
- ALWAYS snapshot before each adversarial scenario; chain-of-custody must be reproducible.
- ALWAYS include trace URLs for findings — a finding without an on-chain proof is downgraded to "hypothesis".
Best practices
- Codex stdout verbatim — no summary, no paraphrase. This is a /codex:adversarial-review-style hand-off.
- Pattern G branching between scenarios — never run two adversarial
scenarios from the same starting state without resetting via
revert_vnet. - One snapshot per scenario — each F-number finding has its own snapshot_id so reviewers can replicate without re-running the entire pass.
- Append, never rewrite — the defensive report's sections are immutable. Adversarial output goes in a new section only.
Style
- Tables over prose.
- Severity reassessments must include justification — never lower a defensive severity without a Codex trace proving the realistic- precondition path can't trigger it.
- Findings are CONCRETE: contract:line + trace URL + recommended check. "There may be an issue with X" is not a finding.
Reference
/claude-tenderly-auditor(sibling skill — produces the defensive baseline this skill challenges)AUDIT_REPORT_TEMPLATE.mdin/claude-tenderly-auditorskill dir — canonical schema both skills emit/codex:adversarial-review(the underlying review primitive)/codex-adversarial-review-tenderly-testnet(older sibling — diff- centric review; this skill is artefact-centric)/tenderly-proPattern G (snapshot branching)
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

