Cloudflare’s security-audit skill is the number one repo on GitHub’s weekly trending list right now: about 48K stars as of 26 Oct 2026, roughly 15K of them this week, MIT-licensed. It isn’t a scanner. It’s a set of Markdown instructions plus two small Node validators that turn a coding agent like Claude Code into an audit team: parallel sub-agents map the code and hunt for bugs, then separate agents try to disprove every candidate before anything gets a severity.
This is my guide to what it actually does: the six phases in four steps, how to install and run it with Claude Code, what findings.json looks like, what it costs in usage, how to sandbox it, and how I’d wire it into a weekly routine. I read the README, SKILL.md, the phase guides, the JSON schema and Cloudflare’s launch post on 26 Oct 2026. I haven’t run a full audit for this post, so everything below is attributed to those sources, and where the advice is mine I say so.
The timing isn’t random. It’s climbing the same week PHP2Shell (reportedly found with AI help) and the LiteLLM and Railway incidents landed — I covered those in my October 21 security roundup. If attackers use models to find bugs, running a disciplined version of the same thing on your own code first is cheap insurance.
1. What the Security Audit Skill Is
The GitHub description is precise: “A coding-agent skill for multi-phase security audits with independently verified, machine-readable findings.” The README adds that it “orchestrates isolated agents through reconnaissance, coverage-led hunting, candidate validation, structured output, independent record verification, and target-neutral reporting.” In plain words: your agent becomes the coordinator (the skill calls it the parent), and each unit of work goes to a fresh sub-agent with its own instructions and no knowledge of what the others concluded.
Repo facts (verified 26 Oct 2026)
- Repository: github.com/cloudflare/security-audit-skill
- Stars: ~48K (47,993 per the GitHub API) · ~3K forks · #1 on GitHub weekly trending with ~15K stars this week
- License: MIT (Copyright (c) 2025-2026 Cloudflare, Inc.)
- Created: 18 June 2026, the day Cloudflare published its harness post · last push 14 Sept 2026 · 14 commits
- What ships: SKILL.md, three phase guides, an attack-class catalog, ten domain companions, report-schema.json and two zero-dependency Node validators with tests
- Install: Skills CLI — npx skills add, per project or with --global
- Runs on: Any coding agent whose model supports tool use and parallel sub-agents (the README names no specific agent)
What you install is Markdown plus two Node scripts: no binary, no service, no API key of its own. Your agent’s model does the reading and reasoning; the skill supplies the method — who does what, what counts as a finding, what evidence it needs and how to prove it. That’s also why results depend on the agent and model you run it with, and why the same repo can produce different results on different runs.
Where it came from
The README says this is the skill that seeded Cloudflare’s vulnerability discovery harness. In “Build your own vulnerability harness” (18 June 2026), Grant Bourzikas writes that they “started with a ~450-line security-audit skill that we ran on a single repository” and grew it into a fleet scanner covering 128 repos. The post’s funnel: 20,799 raw candidates, about 12,057 surviving validation and 7,245 actionable findings after deduplication and routing, with the validation rejection rate falling from 40% to 11%. Two caveats: those numbers belong to the internal multi-stage harness, not to this single-repo skill, and the harness itself isn’t in this repo — the post said it would follow.
If you read about it in June, re-read it
The June post describes the original skill as a 7-phase audit in one session. The repo changed a lot on 10 Sept 2026: a commit titled “Rework the audit workflow, findings contract, and validators end to end” introduced the three verdicts, the deterministic coverage ledger, the ten domain companions, the OS-sandbox rule and the coverage-ledger validator. Its message says both validators ship with test suites (65 tests) and that the rework was checked with a live, budget-limited audit against an internal repository. Today’s README documents six phases, so older summaries may describe a different skill.
2. The Architecture in 4 Steps
The README lists six phases. I group them into four steps, because phases 3 and 5 are both independent verification and phases 4 and 6 are both output:
Step 1 — Reconnaissance and the coverage ledger (phase 1)
Four baseline research agents run in parallel — product and stack, principals and controls, entry surfaces and sinks, local execution and deployment visibility — and return facts with file:line references without writing files. The parent synthesizes architecture.md and a deterministic coverage-ledger.json: one unit per combination of entry surface, trust boundary, subsystem and attack class. That ledger is what makes coverage, and spend, countable.
Step 2 — Coverage-led hunting waves (phase 2)
Each planned unit goes to an isolated hunter whose prompt carries architecture.md verbatim plus the exact attack-class blocks selected for it, from ATTACK-CLASSES.md and the companions (AI/LLM, web protocol and auth, client-side, cloud, supply chain, memory safety and more). Hunters return exactly one JSON object. After each wave a fresh coverage critic looks for unmapped entry points and gaps, and the loop repeats until the critics find no new work or the profile or budget stops it.
Step 3 — Adversarial validation (phases 3 and 5)
Every unique candidate goes to a fresh verifier whose prompt opens with “You did not write this candidate. Try to refute it.” It returns confirmed, needs_validation or rejected. After the findings file is written, another fresh agent re-verifies each final confirmed and needs_validation record against source; a material change, such as an upgrade to confirmed, goes to yet another independent verifier before it is applied.
Step 4 — Structured output and reports (phases 4 and 6)
The parent writes findings.json, checks it against report-schema.json with validate-findings.cjs and checks the ledger with validate-coverage-ledger.cjs. Only after every retained record passes verification does it derive REPORT.md, FINDINGS-DETAIL.md and NEEDS-VALIDATION.md — and the prose may never change a verdict or a severity.
The rule that makes it different: severity needs proof
Only confirmed records get a severity, and overall severity can’t exceed demonstrated impact. needs_validation means a specific, source-grounded hypothesis is blocked by a fact the agent can’t see, and it carries no severity at all. Defense-in-depth gaps are hardening notes, not vulnerabilities. SKILL.md calibrates with these anchors:
- Critical: An unauthenticated actor gains code execution, full data-store access or takeover of arbitrary accounts.
- High: An actor fully defeats an explicit control with real consequences: auth bypass, cross-tenant read or write, stored script execution against other users, authenticated code execution.
- Medium: A real boundary violation with limited blast radius, uncommon preconditions or a narrow set of affected resources.
- Low / informational: Disclosure of non-secret internals or minimal-gain effects; informational is confirmed but minimal impact.
A clean run may have zero confirmed findings, and VALIDATION-AND-REPORTING.md tells the agent to say so “without inventing LOW findings.”
3. Quickstart With Claude Code
The README lists three requirements. The third is the one people skip:
Requirements (README)
- • A coding agent with a model that supports tool use and parallel sub-agents.
- • Node.js, for the two zero-dependency validators (findings and coverage ledger).
- • An OS-enforced sandbox for anything that builds, tests or runs target code: no external network, a sanitized allowlisted environment, resource limits and writes only to assigned scratch paths. Without it, the skill doesn’t execute target code and keeps those leads as needs_validation.
Install it with the Skills CLI. These are the README’s own commands — project-level first, then user-level with --global:
# Project-level install (README) npx skills add https://github.com/cloudflare/security-audit-skill \ --skill security-audit # User-level install, available in every repo (README) npx skills add https://github.com/cloudflare/security-audit-skill \ --skill security-audit \ --global
To skip the agent picker and target Claude Code directly, the Skills CLI documents -a (agent) and -y (skip confirmation prompts). Its agents table puts Claude Code skills in .claude/skills/ for a project and in ~/.claude/skills/ globally:
# Target Claude Code only and skip the prompts (-a and -y from the Skills CLI docs) npx skills add https://github.com/cloudflare/security-audit-skill \ --skill security-audit -a claude-code -y # Project: .claude/skills/security-audit/ # Global (--global): ~/.claude/skills/security-audit/
Then start Claude Code inside (or pointed at) the repo you want to audit and ask. These three prompts come straight from the README; the skill activates on requests like “security audit”, “find vulnerabilities” or “pen-test the code”, and you can also call it explicitly with /security-audit:
security audit this codebase find security vulnerabilities in ./src do a security review, output to ~/audits/my-project
Two behaviors worth knowing before you hit enter. First, a direct audit or pen-test request runs full audit mode, while a security question or a focused review runs guidance mode, which writes no audit files; if the request is ambiguous, SKILL.md tells the agent to ask you one question first. Second, output defaults to ~/security-audit-skill/<repo-name>/run-<N>, outside your repo. It writes inside the target only if you explicitly pick a directory that version control ignores.
SKILL.md also defines three run profiles — quick (one hunter wave, one final critic, one verifier per candidate), standard (the default) and deep (finer units, critic waves until a clean pass, separate verifiers) — plus scoped runs on named paths, one subsystem or the diff between two refs, and an optional budget measured in agent invocations. The profile is picked from your request, so I simply state it (my phrasing):
security audit this codebase, quick profile, scoped to src/api, budget 20 agents
When the run finishes, re-run the validators yourself. These are the invocations from VALIDATION-AND-REPORTING.md, with the paths that a project-level Claude Code install and the default output directory produce:
node .claude/skills/security-audit/validate-findings.cjs \ ~/security-audit-skill/my-api/run-1/findings.json node .claude/skills/security-audit/validate-coverage-ledger.cjs \ ~/security-audit-skill/my-api/run-1/coverage-ledger.json
Other agents
The skill is written to be agent-neutral: it talks about a parent, a Task tool and two delegated roles (research and general) and asks you to map them to your platform’s equivalents. The Skills CLI can install it for Codex, Cursor, OpenCode and dozens of other agents (-a codex, -a cursor, -a opencode). The README names none of them, so check for yourself that your agent really runs parallel sub-agents with isolated context — the independence of the verifiers is the whole point.
Tip: on Windows, use WSL2
Claude Code’s sandboxing docs say that on native Windows it runs commands unsandboxed, and that you should run Claude Code inside a WSL2 distribution to get the sandbox. For this skill that matters: without an enforceable sandbox, every lead that needs running code stays needs_validation.
4. What the Output Looks Like
A full-audit run directory, assembled from the files that SKILL.md and the phase guides define (the comments are my summary):
~/security-audit-skill/my-api/run-1/
├── run-metadata.json # run_id, repo, source_ref, profile, scope_paths, budget, run_status
├── architecture.md # phase 1 map: stack, principals, trust boundaries, entry surfaces
├── coverage-ledger.json # units: planned → in_progress → covered | candidate | blocked | deferred
├── findings.json # confirmed + needs_validation + rejected records
├── REPORT.md # profile, scope, posture, findings table, coverage summary
├── FINDINGS-DETAIL.md # full trace + local reproduction for medium/high/critical
├── NEEDS-VALIDATION.md # leads with exact blockers and resolution plans, no severity
└── agents/<agent-id>/
├── scratch/ # the only place a sub-agent (and target code) may write
└── artifacts/ # parent-owned, filled only by the safe promotion procedurefindings.json is an array of records, each with a verdict. The schema uses additionalProperties: false, so each verdict has a strict field contract:
confirmed
fingerprint, title, description, root_cause, intended_behavior, trace (entrypoint → propagation → sink, each with file, line, scope and description), evidence, conditions (kinds such as authentication_level, authorization_role, user_interaction or system_configuration), execution (attacker_perspective, payloads, instructions, observed_result), remediation (strategy plus optional code_changes), severity (likelihood and impact, each with score and reason, plus overall_severity) and confidence (low, medium or high, with a reason).
needs_validation
fingerprint, title, description, claimed_root_cause, trace, evidence, blockers (the exact facts it couldn’t observe) and validation_plan with a local and/or deployment field. No severity, no execution, no remediation — by design.
rejected
fingerprint, title, description, claimed_root_cause, trace, evidence and the reason it was disproved. Kept so future runs don’t raise the same unsupported claim again unless the evidence changes.
Here is the shape of a confirmed record. The field names come from report-schema.json; the values are an invented example of mine, trimmed with “…”:
[
{
"verdict": "confirmed",
"fingerprint": "api/invoices:cross-tenant-read",
"title": "Invoice lookup skips the tenant check",
"description": "…",
"root_cause": "findInvoiceById filters by id only, not by tenant_id",
"intended_behavior": "Users can read only invoices of their own tenant",
"trace": [
{ "kind": "entrypoint", "file": "src/routes/invoices.ts", "line": 42,
"scope": "GET /invoices/:id", "description": "…" },
{ "kind": "sink", "file": "src/db/invoices.ts", "line": 17,
"scope": "findInvoiceById", "description": "…" }
],
"evidence": [{ "file": "src/db/invoices.ts", "line": 17, "description": "…" }],
"conditions": [{ "kind": "authentication_level", "description": "Any logged-in user" }],
"execution": {
"attacker_perspective": "Dummy user of tenant A",
"payloads": ["GET /invoices/1002"],
"instructions": ["Run the dummy-tenant integration test inside the sandbox", "…"],
"observed_result": "The tenant B dummy invoice is returned with HTTP 200"
},
"remediation": { "strategy": "Scope the query by the session tenant_id", "code_changes": [] },
"severity": {
"likelihood": { "score": "high", "reason": "…" },
"impact": { "score": "high", "reason": "Cross-tenant read" },
"overall_severity": "high"
},
"confidence": { "score": "high", "reason": "…" }
}
]Because it’s plain JSON, triage is a one-liner. My jq to list confirmed findings with their severity:
jq -r '.[] | select(.verdict=="confirmed") | "\(.severity.overall_severity)\t\(.title)"' \ ~/security-audit-skill/my-api/run-1/findings.json
Validators prove format, not truth
validate-findings.cjs rejects malformed records (and refuses input beyond 5 MiB, 1,000 findings or 64 nesting levels), but VALIDATION-AND-REPORTING.md is blunt: “Validator success proves format and ledger consistency only.” The truth check is the chain of independent verifiers — and then you. Read FINDINGS-DETAIL.md for every medium, high and critical record before you open a ticket.
5. Cost, Usage Limits and Sandboxing
The skill is free; running it isn’t. There’s no official per-run price, but the files tell you how spend scales:
Budget is counted in agents
SKILL.md records an optional budget as a maximum number of agent invocations. One ledger unit is roughly one hunter assignment, and each surviving candidate costs one or two verifier assignments depending on the profile.
There’s a floor before any hunting
Before recon starts, the budget must cover the four baseline recon agents, the critic reserve (one for quick, two for standard and deep) and at least one verifier. If it can’t, nothing launches and the run is recorded as incomplete.
Sub-agents share your limits
Claude Code’s docs say each subagent’s requests count toward the same usage limits as your main conversation, and by default a session tops out at 20 concurrent subagents (CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS raises it). A standard run on a real codebase can eat a large share of a subscription window — my expectation, not a measured number.
An order of magnitude from Cloudflare
For the internal harness (not this skill), the post reports that a ~30K-line repo yields about 100 initial findings in a 3–4 hour run, and that each extra pass costs roughly half as much as the initial hunt. No token or dollar figures are published. On API billing, claude -p with --output-format json reports total_cost_usd as a client-side estimate.
Then the sandbox. SKILL.md’s “Universal execution safety” rules apply in both modes: source inspection is read-only, and any target-controlled build, test, process, browser, emulator, fuzzer or fixture runs only inside an OS-enforced sandbox with all of these controls:
Required controls (SKILL.md)
- • No external network; only an isolated loopback namespace when a check needs local client/server traffic.
- • An empty environment populated from an explicit allowlist, with scratch-local HOME, temp directories and caches.
- • A read-only target and toolchain; target code writes only inside its assigned scratch/ directory.
- • Explicit low CPU, memory, process, file-size, disk and wall-clock limits.
- • No dependency installs and no builds that fetch; dummy principals, fixtures and secrets only; never probing deployed endpoints or shared services.
How does Claude Code’s own sandbox compare? Per its docs, /sandbox uses Seatbelt on macOS and bubblewrap on Linux and WSL2, limits writes to the working directory (plus a temp directory and any you add) and routes network traffic through a proxy whose allowlist starts empty. But the docs don’t mention CPU, memory or process limits, environment variables are inherited unless you deny them (sandbox.credentials.envVars or CLAUDE_CODE_SUBPROCESS_ENV_SCRUB), and if the sandbox can’t start, commands run unsandboxed unless sandbox.failIfUnavailable is true. My reading: a useful layer, not the full set of controls the skill asks for.
My take
Run audits on a disposable VM or cloud dev box with no production credentials, no SSH agent and nothing mounted that you can’t lose. Cloudflare’s post notes its hunters used a sandbox built on unshare, and that running it in Docker needed seccomp=unconfined and apparmor=unconfined — one more reason I wouldn’t loosen my everyday container profile for this. If you can’t build the sandbox, accept static-only runs: more needs_validation and fewer confirmed is the skill being honest, not failing.
6. A Sensible Weekly or CI Routine
The repo documents no CI integration, no GitHub Action and no per-PR mode, and Cloudflare’s post is explicit that “The Fixer never merges code on its own; a human must review the branch.” What follows is my suggestion, not something the project ships:
- • A dedicated, disposable runner with read-only repo access and no production secrets in its environment.
- • A weekly quick, scoped run on the paths that changed; a standard run before major releases; deep only for the crown jewels.
- • A stable output root, so runs stay additive: the skill reads prior ledgers and findings to target gaps and revalidate changed source.
- • Gate the job on both validators passing — never on the number of findings.
- • Route confirmed records to your tracker and needs_validation records to their owners with the deployment plan; keep rejected ones as memory.
- • Humans review and merge every fix.
Headless, this is roughly how I’d run it with Claude Code. It’s an untested sketch: every flag comes from Claude Code’s headless docs, but tune the permissions to your setup — Bash(node *) is broad and only acceptable on a throwaway machine:
# Weekly sketch (mine, untested end to end): run it on a disposable VM, not your laptop mkdir -p ~/security-audit-skill cd ~/src/my-api && git pull --ff-only claude -p "/security-audit Full security audit of this codebase, quick profile, scoped to src/api" \ --add-dir ~/security-audit-skill \ --permission-mode acceptEdits \ --allowedTools "Bash(node *)" \ --max-budget-usd 30 \ --output-format json > ~/security-audit-skill/last-run.json RUN=$(ls -d ~/security-audit-skill/my-api/run-* | sort -V | tail -1) node .claude/skills/security-audit/validate-findings.cjs "$RUN/findings.json" node .claude/skills/security-audit/validate-coverage-ledger.cjs "$RUN/coverage-ledger.json" jq -r '.[] | select(.verdict=="confirmed") | "\(.severity.overall_severity)\t\(.title)"' "$RUN/findings.json"
Don’t add --bare here
Claude Code’s docs recommend --bare for scripts, but bare mode skips auto-discovery of skills and turns off background subagents — the two things this workflow depends on. Recent versions also start claude -p runs in Manual permission mode, where any call that needs approval is simply denied, so pre-approve what the run needs. A -p run waits for its background subagents before exiting, and --max-budget-usd stops the remaining work when the cap is hit.
7. Where It Shines: Use Cases
Where I think it earns its usage bill:
Pre-launch audit of your own SaaS
Tenant isolation, auth and data lifecycle are covered by dedicated companions, and a cross-tenant read is exactly the kind of “high” the severity anchors describe.
LLM and agent features
The AI-AND-LLM companion hunts prompt injection, agent and tool authority, and unsafe output handling — the layer generic static rules rarely understand.
Supply chain, CI and cloud config
Companions cover dependencies, CI, release, signing, updates and plugins, plus IAM, infrastructure-as-code, containers and serverless — as far as the repo shows them.
Inherited or rescued codebases
Even with zero confirmed findings, architecture.md and the ledger give you a trust-boundary map of code nobody on the team wrote.
Re-audits after fixes
Runs are additive: unchanged confirmations are re-verified, changed source is revalidated, and old needs_validation, deferred or blocked units become current work.
Native, desktop and mobile code
Memory-safety, binary, kernel and local-IPC companions exist — this is where a real sandbox matters most, because confirming those bugs means running code.
The pattern: code you own, boundaries that matter, and a human who will read the evidence. That’s the profile the skill’s rules were written for.
8. When NOT to Use It
It’s a strong method, not a magic button. Honest boundaries:
❌ Skip it when
- • You need a pentest of what’s deployed — it reads source and runs bounded local checks only; deployment facts become needs_validation, and it never sends audit traffic to a live system.
- • You want a deterministic per-PR gate — model runs vary, and the README’s own number is that a single run found roughly half of what repeated runs found in total.
- • You can’t provide an OS-enforced sandbox but need runtime-confirmed bugs in native code, parsers or fuzzing targets — those leads will stay unconfirmed.
- • Your agent can’t run parallel sub-agents, or your usage plan can’t absorb dozens of agent invocations per run.
- • Compliance needs a published false-positive rate — neither the README nor Cloudflare’s post gives one.
- • You expect patches applied for you — the skill describes the smallest fix but never modifies target source, and Cloudflare’s Fixer isn’t in this repo.
- • You’d run it on your daily laptop with cloud credentials sitting in the environment.
✅ Use it when
- • You own the source and want reasoning about trust boundaries, not only pattern matching.
- • Your agent supports parallel sub-agents and you can budget the usage.
- • You can run it more than once and compare runs.
- • You want machine-readable findings that a script can route.
- • Someone on the team will triage the confirmed and needs_validation records.
Golden rule
Treat every run as a sample, not a verdict. Vet the skill before you install it, run it in a box you can throw away, run it again, and let a human decide what ships.
Conclusion
The security-audit skill is the most interesting kind of trending repo: not a new tool but a written-down method — isolated hunters, adversarial verifiers, a coverage ledger and a strict schema — that any capable coding agent can follow. About 48K stars in just over four months, 15K of them in a single week, says many teams want exactly that discipline around AI-driven code review.
My suggestion: install it at project level, start with a quick, scoped run on one service you know well, check the confirmed records by hand, and see whether the needs_validation list matches the questions you’d ask yourself. If it earns its keep, move it to a disposable runner on a weekly schedule. And before you install any third-party skill — this one included — read it or scan it first.
Sources
- Repository and README (phases, install, usage, requirements) — github.com/cloudflare/security-audit-skill
- SKILL.md: modes, sandbox rules, profiles, budget, severity anchors — github.com/cloudflare/security-audit-skill
- report-schema.json: the findings.json contract — github.com/cloudflare/security-audit-skill
- Build your own vulnerability harness (18 June 2026) — blog.cloudflare.com
- Skills CLI supported agents and install paths — github.com/vercel-labs/skills
- Claude Code sandboxing — code.claude.com
- Claude Code subagents: parallelism and usage limits — code.claude.com
- Run Claude Code programmatically (claude -p) — code.claude.com



