npx skills add ...
npx skills add cloudflare/security-audit-skill --skill security-audit
Security guidance and vulnerability review for codebases, APIs, services, CLI tools, libraries, and daemons. Use for security questions, focused reviews, vulnerability research, security audits, or pen tests. Run the complete workflow only for explicit codebase audit or pen-test requests, full/comprehensive/end-to-end reviews, or requested report artifacts.
npx skills add cloudflare/security-audit-skill --skill security-audit
Find vulnerabilities that violate a real trust boundary, then give owners the source evidence, safe reproduction, priority, and smallest effective fix. This is a defensive, source-first workflow. A candidate without a concrete affected principal, resource, or security outcome is not a confirmed finding.
This skill is guidance by default. Loading it does not authorize the complete audit workflow or file creation.
If the request could mean either mode, ask one focused question before creating files or starting the complete workflow.
This skill is agent-neutral:
research agent is a delegated agent for focused source exploration and factual verification.general agent is a delegated agent for broad investigation and bounded local execution.subagent_type: in a heading names which of these two delegated agent roles runs that work.Use equivalent platform capabilities while preserving role, write-isolation, prompt, and independence boundaries.
These rules apply in both operating modes. Source inspection is read-only. Run target-controlled builds, tests, processes, browsers, emulators, fuzzers, and fixture processing only inside an OS-enforced sandbox that provides all of these controls:
HOME, temporary directories, and caches;scratch/ directory; andThe agent, outside the target-controlled process, may make a disposable source copy in an assigned scratch/ directory when a build must write beside source. In guidance mode, do not retain target-controlled files. In full audit mode, only trusted parent-side code may promote the minimum non-secret result to retained artifacts/ using the procedure under Write isolation. Never expose a retained output directory (other than the agent's own assigned scratch/), another agent's directory, the host home directory, credentials, sockets, or shared services to target code. Do not install dependencies or let builds fetch them. Use only tools and dependencies already available locally. If every control cannot be enforced, do not execute target code: report the missing sandbox capability as a needs-validation blocker and give a safe validation plan.
Use dummy principals, fixtures, and secrets. Do not probe deployed endpoints, external services, shared infrastructure, production identities, other users' data, or live control planes. Do not test availability against a live or shared process, publish artifacts, alter releases, spend paid API quota, or continue beyond the minimum local effect needed to establish a defect. If the decisive fact is outside source or the sandboxed fixture, report it as needing validation.
In full audit mode, resolve these values before reconnaissance:
SKILL.md.~/security-audit-skill/<repo-name>/run-<N>, where <N> is the next unused integer. Use a directory inside the target only when the user explicitly selects it and the parent verifies that version control ignores the whole directory. Otherwise stop and request an external path.The parent creates and is the only writer of shared run files:
run-metadata.jsonarchitecture.mdcoverage-ledger.jsonfindings.jsonREPORT.mdFINDINGS-DETAIL.mdNEEDS-VALIDATION.mdEach hunter or verifier receives a unique root under <output-dir>/agents/<agent-id>/, with separate scratch/ and artifacts/ directories. Canonical agent IDs match ^[a-z0-9][a-z0-9_-]{0,63}$ and must not equal a Windows device name such as con, prn, aux, nul, com1 through com9, or lpt1 through lpt9. Lowercase IDs prevent case-fold collisions. The agent and every target-controlled process may write only to scratch/; retained artifacts/ is parent-owned, is never exposed to the sandbox, and is writable only by trusted parent-side promotion code. Agents may not change shared files, target source, retained artifacts, or another agent's directory. Do not use /tmp or the host home directory as a writable fallback.
Before execution, the parent opens and retains trusted, non-inheritable directory descriptors for the agent's scratch/ and artifacts/ roots, and records an allowlist of expected scratch-relative artifact files plus explicit per-file and cumulative byte limits. Never pass those descriptors to the agent or sandbox. After the sandbox and all its processes terminate, trusted parent-side code promotes each allowlisted file separately:
., .., or symlinked components.fstat that it is a regular file with link count exactly one and within the recorded per-file and cumulative byte limits.fstat, and reject a changed identity, type, link count, or size.needs_validation with the exact promotion blocker.HUNTING.md and VALIDATION-AND-REPORTING.md carry this procedure as one identical fenced block for hunter and verifier prompts; it states the same rules in the same order as this list.
For a reproduced check, record the command, exact test input, sandbox limits, and only the allowlisted environment variable names plus safe non-secret values needed to reproduce it. Never capture or copy the ambient environment, inherited variables, credential values, authentication state, or unrelated host paths. Launch from an empty environment rather than trying to redact one after execution.
Before delegation, the parent writes run-metadata.json with at least run_id, repo, target, source_ref, profile, scope_paths, budget (null if unset), execution_policy: "sandboxed-source-and-local-only", selected companion files, prior-run paths, shared-file owners, and run_status: "in_progress". Update metadata only when those facts change; candidate state belongs in the coverage ledger and findings.json.
The coverage, prior-run, profile, and budget requirements in this section apply only in full audit mode.
No one pass is complete. Build a deterministic coverage plan before hunting and update it after every agent result. RECONNAISSANCE.md defines the stable coverage units and HUNTING.md defines coverage-critic waves. The parent alone updates the ledger.
If prior runs exist, read every compatible coverage-ledger.json and findings.json before planning the current run:
confirmed record into the current candidate set only when its relevant source and conditions are unchanged and its evidence still meets the current contract. Link it to a current ledger unit seeded planned, preserve its fingerprint, exclude only that carried root cause from hunters, and send the carried record through the current final verification path; the Phase 3 verifier that re-checks it becomes that unit's assignment owner and moves it to candidate.confirmed record changed, create a current planned revalidation unit. Do not put that record on the hunter exclusion list. It remains confirmed only if current independent validation establishes the current path and result.needs_validation, deferred, blocked, out_of_scope, and any changed-source unit current work. A still-external needs_validation record may be carried only after the current source trace is checked and linked by fingerprint to a current planned unit whose verifier re-check supplies its owner and evidence; the record keeps the unresolved blocker. These prior states never suppress a current unit.rejected record suppresses only the unchanged failed claim, not coverage of its unit; changed evidence creates current work.quick or scoped ledger contributes only its recorded evidence and gaps, never an implied "rest is fine."If no prior ledger exists, say so in the final coverage statement. Never imply that one run exhausts the target.
During full audit setup, pick a profile from the user's request or propose one from the target's size and stakes. Record it in run-metadata.json (profile, scope_paths) and state it in the report. The default is standard.
quick — a bounded pass for small targets, re-runs, or a fast first look. Coarsen ledger units to surface × boundary × attack class (subsystem uses the fixed canonical profile/quick/all-in-scope-subsystems identifier), run exactly one hunter wave followed by exactly one final coverage-critic pass, and use one fresh verifier per candidate for both candidate validation and final record verification. Do not launch a follow-up hunter wave: record the critic's accepted discoveries and reassignments as deferred.standard — the workflow as written.deep — for high-stakes or large targets. Split ledger units per subsystem and lifecycle mode, run critic waves to a clean pass, keep candidate validation and final record verification as separate fresh agents, and give prior_covered_same_source units an independent second pass.A scoped run audits a subset: named paths, one subsystem, one companion domain, or the diff between two source refs. Seed ledger units only for in-scope surfaces and record everything else as out_of_scope — never as covered. A scoped or quick run must present itself as partial coverage.
Profiles change breadth and redundancy, never the evidence bar. Do not scale away the candidate gate, the source/local execution boundary, needs_validation discipline, schema validation, or independent verification of confirmed records.
The ledger makes spend countable: one unit is roughly one hunter assignment, and one surviving candidate is one or two verifier assignments depending on profile. When the user sets a budget — or the parent proposes one for a large target — record budget in run-metadata.json as a maximum number of agent invocations across all phases.
Apply the strict budget gate before launching any reconnaissance agent. Reserve the four baseline reconnaissance calls, one final post-wave critic for quick or one post-wave plus one distinct final-clean critic for standard/deep, and at least one verifier call. Add focused reconnaissance only after repeating this gate for each extra call. If the requested budget cannot fund that minimum, launch no agent: ask for a larger budget, narrower scope, or different profile. If the request remains unchanged, set run_status: "incomplete" with incomplete_reason: "budget_cannot_fund_reconnaissance_and_reserves" and report that no audit pass ran.
Spend it in this order:
quick, reserve its one post-wave final critic. Before every standard or deep hunter wave, reserve one immediate post-wave critic plus one distinct final-clean critic. Also reserve verifier cost from the profile (about 1 or 2 agents per expected candidate; when in doubt reserve 30% of the balance after critic reservation). Never assign hunters into either reserve.deferred with reason budget_cannot_reserve_critics_and_validation, and use the retained final-clean critic to record the resulting gap.Before wave 1, update the pre-recon estimate with seeded units, implied hunter count, mandatory critic calls, validation reserve, and whether the remaining budget covers the plan. If it clearly cannot, say so and propose either a tighter scope or a coarser profile instead of silently thinning evidence. If later facts consume the required final-critic reserve, launch no hunters, mark all planned work deferred, set the run incomplete with reason critic_budget_exhausted, and make no complete-coverage claim.
A strict total-agent budget can still be exceeded by an unexpectedly large candidate set or by a material Phase 5 replacement that needs another independent verifier. If the remaining budget cannot validate every candidate, stop hunting, validate candidates in fingerprint order while the budget permits, and set run_status: "incomplete" plus incomplete_reason: "validation_budget_exhausted". Keep each unvalidated fingerprint linked to a candidate ledger unit with that unresolved reason. Do not put an unvalidated candidate in findings.json, relabel it needs_validation, or report the run as complete. Phase 6 may produce a partial report only if its first section states that candidate validation is incomplete and lists the affected fingerprints and units. Never exceed a user-set strict budget silently.
For every candidate, name the lower-trust principal, accepted input or action, intended control, crossed boundary, affected principal or resource, and concrete observed or owner-observable result. Do not elevate a missing best practice, guessed deployment behavior, generic parser crash, or self-impact into a security finding.
Static analysis establishes the source path. Sandboxed local tests resolve behavior when all execution controls are available: a minimal function harness, existing unit test, small parser fixture, dummy-tenant integration test, locally rendered configuration, or bounded isolated-loopback client. Stop at a wrong return value, unauthorized dummy record, sanitizer finding, policy difference, or other minimum effect. Do not extend the local check beyond the minimum boundary result or produce persistence, post-fault, or concealment material.
Deployment controls, proxy behavior, provider settings, browser headers, identity policy, broker ACLs, packaging, and topology are real controls. If they are required and absent from the repository, do not assume either presence or absence. Use needs_validation with the exact missing fact and a safe owner-observed or local plan.
Only confirmed records receive severity. Likelihood and impact must reflect the demonstrated conditions and result; overall severity cannot exceed demonstrated impact. needs_validation means a specific source-grounded boundary hypothesis is blocked, not a low-confidence confirmed vulnerability, and it has no severity.
Calibrate overall severity with these anchors:
The high/medium discriminator: does the demonstrated result fully defeat an explicit control for an action with real consequences, or only weaken it? If you cannot state the concrete damage, the severity is lower than it feels.
For each confirmed finding, identify the invariant the code must enforce and the narrowest source change that enforces it at the last trusted decision point. Prefer specific repository-relative changes and regression tests over generic hardening advice. The audit describes fixes; it does not modify target source.
In full audit mode, follow all six phases in order:
confirmed, needs_validation, and rejected records to findings.json; validate it with report-schema.json and validate-findings.cjs, and validate the coverage claim with validate-coverage-ledger.cjs.REPORT.md, FINDINGS-DETAIL.md, and NEEDS-VALIDATION.md from the final records, with no live-probe instructions.Do not end the run before one of exactly two terminal states: (a) all Phase 6 artifacts are written and both validators pass, or (b) run_status: "incomplete" is recorded with its exact reason and the gap is disclosed in the report. Never stop mid-phase.
needs_validation records.