security-audit-runner
Skill3 starsChanged 29 days agoMITView on GitHub
Runs Cloudflare's security-audit skill in full audit mode from Claude Code. It builds each agent's prompt file from that skill's text, pulls each agent's JSON reply out of its transcript, and keeps the coverage ledger, findings, agent-call budget and NEEDS-VALIDATION.md. Use it together with `security-audit` when the user asks for a full, end-to-end or report-producing security audit or pen test of a codebase. For a security question or a focused review, use `security-audit` alone.
In this repository22 other files it gives its agents.
- confluence-jira-linksSkill
- diagnosing-bugsSkill
- epic-reviewSkill
- explain-the-numberSkill
- grillingSkill
- handoffSkill
- leader-1-1-prepSkill
- llm-integrationSkill
- no-ai-attributionSkill
- open-in-my-browserSkill
- pick-upSkill
- plain-writingSkill
- regression-proofSkill
- researchSkill
- retroSkill
- skill-collision-auditSkill
- supervisorSkill
- tddSkill
- ticket-digestSkill
- ticket-trimSkill
- ticket-writeSkill
- writing-for-agentsSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 2 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
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 17
Fresh IDs: Every agent ID is lowercase, used once, and never the ID of an agent that hunted, verified or rewrote the same candidate.
- Very specific: line 26
Seed the ledger: Write a spec (see Seed spec) and run R seed RUN spec.json.
- Very specific: line 28
Merge shared root causes: When two fingerprints are one root cause, run R merge RUN <keep> <drop> --reason "..." [--lead <fp with the …
- Distinctive: line 43
Add one call for each discarded reply that is re-run.
≈ “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
Security audit runner
Cloudflare's security-audit skill (MIT) supplies the method: phases, prompts, schemas, validators. It is a dependency, installed separately, and its files decide every rule. This skill is the parent-side tooling for its full audit mode in Claude Code. scripts/audit_runner.py reads the installed skill at run time, copies its blocks into prompt files verbatim, checks each reply against the contract its prompt gave, and writes the parent-owned run files. It was tested against security-audit at commit c1c8a8c. If a later version renames a heading, the script stops and names the missing anchor; it never guesses.
Requirements: Python 3.9+, and node for the skill's two validators. Below, R is python3 -I <this skill's folder>/scripts/audit_runner.py and RUN is the run's output directory. R <command> -h lists each command's options.
Rules the run depends on
- Replies stay out of context. Prompts run to tens of kilobytes, so each agent gets one line: the
agent_promptthatR promptprints, which tells it to read its prompt file. Launch every agent in the background. Its completion notice names its transcript,.../tasks/<agentId>.output(a JSONL symlink). Pass that path toR extractand never open it yourself. Read aresult.jsononly where a step below says so. - A bad reply is discarded, never repaired.
extractchecks each reply against its role's contract and its schema branch, runsvalidate-findings.cjson any record, and on any error saves the raw text asdiscarded-reply.txtand marks the call discarded. A code fence or a word of prose around the JSON counts as an error. A real verifier once put a field besiderecordand added a stray brace; both are caught here. The fix is a fresh agent under a new ID, so leave room in the budget for a re-run. - Validate early.
apply-hunterchecks each hunter result as it stands: paths must already be repository-relative, and each candidate must pass its schema branch andvalidate-findings.cjs(a trace with twosinkentries fails it). A unit whose result or candidate fails goes back toplannedfor a fresh hunter. Every ledger and findings write runs the skill's validator first and saves nothing on failure; withoutnodethe script refuses to save. - Fresh IDs. Every agent ID is lowercase, used once, and never the ID of an agent that hunted, verified or rewrote the same candidate. The script refuses a reused or dependent ID.
- Models. Reconnaissance and hunters run on Sonnet. Critics and verifiers run on Opus. Use
subagent_type: general-purposeand themodelthatR promptprints. Reconnaissance, critics and record verifiers are the skill's read-onlyresearchrole, and only their prompts keep them from writing. - macOS runs are source-only. macOS cannot enforce the skill's sandbox controls, so
initrefuses--sandboxthere. Prompts then forbid target code, and onlysourcechecks count.
Steps
- Confirm full audit mode. Use it only for the requests
security-audit's SKILL.md names. If the request could be guidance, ask that skill's one focused question. Settle the profile (quick,standardordeep), any scope paths and any budget with the user. Readsecurity-audit's SKILL.md now. - Start the run.
R init [RUN] --target <repo> --profile <p> [--budget N] [--scope path ...] [--prior <earlier run> ...] [--skill-dir <dir>] [--sandbox "<how target code is confined>"]. The skill defaults to~/.claude/skills/security-audit, andRUNdefaults to~/security-audit-skill/<repo>/run-<N>. Pass--sandboxonly for a sandbox that enforces every control in their SKILL.md. When the budget cannot fund 4 reconnaissance calls, the critics and one verifier,initrefuses: ask for a larger budget, a narrower scope or another profile. - Reconnaissance. For each of
1a 1b 1c 1d:R prompt recon RUN r-<x> --agent <x>, then launch it. A focused agent takes--text-filewith your own prompt. As each finishes, runR extract RUN r-<x> <transcript>and read itsresult.md. WriteRUN/architecture.mdfrom the four results under RECONNAISSANCE.md's cap. - Seed the ledger. Write a spec (see Seed spec) and run
R seed RUN spec.json. It derives eachcoverage_id, checks every block reference against the skill files, and fails on any duplicate. For each unchanged priorconfirmedor still-blockedneeds_validationrecord, runR carry RUN --prior-findings <file> --fingerprint <fp> --unit <coverage_id>against its planned unit. - Hunt one wave.
R budget RUNprintshunters_affordable. Take units in HUNTING.md's priority order. For each hunter:R assign RUN h-<name> <coverage_id> ..., thenR prompt hunter RUN h-<name>, then launch. As each finishes:R extract RUN h-<name> <transcript>, thenR apply-hunter RUN h-<name>.assignrefuses a hunter the budget cannot fund before it touches the ledger, andR unassign RUN h-<name>frees units whose prompt was never built. Units the budget cannot reach getR defer RUN --reason budget_cannot_reserve_critics_and_validation <coverage_id> .... Eachuncoveredentry a hunter returns lands inuncovered.jsonand in the critic's prompt. Seed it as a unit for the next wave, or inquickasdeferredwith a reason. - Merge shared root causes. When two fingerprints are one root cause, run
R merge RUN <keep> <drop> --reason "..." [--lead <fp with the strongest trace>]. - Critic.
R prompt critic RUN c-<n>(add--final-cleanfor that pass instandardanddeep), launch it,R extract, then read itsresult.jsonand judge each proposal.R apply-critic RUN c-<n>accepts every missing unit unless told otherwise:--reject N=reason,--out-of-scope N=reason,--keep-closed <coverage_id>=reason. Pass--refswith source-derivedcanonical_refsfor each accepted unit, because refs derived from the critic's labels are weaker. Aquickrun records accepted and reopened units asdeferredwithquick_profile_final_critic. Instandardanddeep, planned units mean another wave from step 5. A clean post-wave critic is followed by a final-clean critic. - Verify candidates. For each
unvalidatedcandidate, in fingerprint order:R prompt verifier RUN v-<n> --fingerprint <fp>, launch,R extract, thenR apply-verifier RUN v-<n>. This rewritesfindings.json. After a discard, re-run with a fresh ID when the budget allows. Otherwise stop and finish incomplete withvalidation_budget_exhausted. A verifier that returns a new fingerprint changes nothing until you decide.--different-root-causeadds its record as a new candidate, and both fingerprints then need a fresh verifier. - Verify final records (
standardanddeep; inquickthe step 8 verifier already did this). For eachconfirmedandneeds_validationrecord:R prompt record-verifier RUN r-<n> --fingerprint <fp>, launch,R extract, thenR apply-record-verifier RUN r-<n>. A material replacement waits for another fresh record verifier. - Close, then report.
R status RUNshows the counts, the spend and any open work. RunR finish RUN, orR finish RUN --incomplete <reason>, which removes disputed records and marks each unvalidated candidate on its units. Then runR validate RUN(both codes must be 0) andR needs-validation RUN [--order fp,...]. WriteREPORT.mdandFINDINGS-DETAIL.mdyourself from the final records, under VALIDATION-AND-REPORTING.md's Phase 6.
Cost
Count before step 3 and tell the user. budget reserves the critics and validation for you, and its hunters_affordable is what assign will allow.
| Profile | Agent calls |
quick | 4 reconnaissance + one per hunter + 1 critic + 1 verifier per candidate |
standard, deep | 4 reconnaissance + hunters per wave + 2 critics per wave + 2 verifiers per candidate |
Add one call for each discarded reply that is re-run.
Seed spec
A JSON array, one object per unit:
{
"surface": "GET /items", "boundary": "Item owner check", "subsystem": "API", "attack_class": "Access control",
"refs": {"surface": "src/routes.js#GET /items", "boundary": "src/authz.js#requireOwner", "subsystem": "src"},
"starting_paths": ["src/routes.js"],
"ordinary_block": "ATTACK-CLASSES.md#Access control",
"companions": {"WEB-PROTOCOL-AND-AUTH.md": ["<class name as written in bold>"]},
"excluded_blocks": [{"block": "FILE.md#<class>", "reason": "the source fact that excludes it"}],
"priority": 1, "rationale": "lowest-trust entry surface"
}companions expands to that file's Core discipline, the named classes, Universal moves and Validation rules. Use companion_blocks instead for an explicit list. refs.attack_class defaults to the ordinary block, else the first companion class. A quick run fixes the subsystem ref to profile/quick/all-in-scope-subsystems, so omit subsystem there. status may be out_of_scope, not_applicable or deferred with a reason, and prior_status and lifecycle (with refs.lifecycle) follow RECONNAISSANCE.md.
Run files
The skill's own: run-metadata.json, architecture.md, coverage-ledger.json, findings.json, NEEDS-VALIDATION.md, REPORT.md, FINDINGS-DETAIL.md. The runner adds agent-calls.json (every call, its role, model and status), candidates.json (proposals, merges and verifier decisions by fingerprint), uncovered.json, critic-log.json, and agents/<id>/ with prompt.md, result.json or discarded-reply.txt, scratch/ and artifacts/.
In a sandboxed run, list each file an agent may keep with --allow-artifact <scratch path>=<bytes> when building its prompt. After its sandbox exits, R promote RUN <id> <scratch path> copies the file into artifacts/ with descriptor-relative, no-follow opens and the size checks. A local check counts only when its artifact was promoted this way. The script opens the scratch and artifacts roots at promotion time, not before the agent runs. That matches the skill's retained-descriptor rule only while nothing but the parent can write agents/<id>/.
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.

