CommunityCoding & Developmentgithub.com

trebaud/swarm-audit

Security-audit a large codebase or system with a swarm of agents: inventory its entry points (HTTP routes, GraphQL resolvers, webhooks, queue consumers, scheduled jobs, CLI commands, message handlers), split them into sections (fixed-size groups or themes), audit each section in its own git worktree with its own agent, collect every validated finding in the orchestrator worktree, then run a final chain audit that dedupes the findings and combines lower ones into higher-severity attack chains. Use when the scope is too big for one audit pass ("audit the whole backend", "split it up and audit each part", "security audit per section"). Options: `--by-group [N]` (groups of about N entry points, default 25) or `--by-theme`; asks when neither is given. Without a THREAT_MODEL.md it asks whether to build one first (recommended) or do a quick run. Keywords: sectioned audit, parallel security audit, vulnerability chaining, attack surface inventory.

What is swarm-audit?

swarm-audit is a Claude Code agent skill that security-audit a large codebase or system with a swarm of agents: inventory its entry points (HTTP routes, GraphQL resolvers, webhooks, queue consumers, scheduled jobs, CLI commands, message handlers), split them into sections (fixed-size groups or themes), audit each section in its own git worktree with its own agent, collect every validated finding in the orchestrator worktree, then run a final chain audit that dedupes the findings and combines lower ones into higher-severity attack chains. Use when the scope is too big for one audit pass ("audit the whole backend", "split it up and audit each part", "security audit per section"). Options: `--by-group [N]` (groups of about N entry points, default 25) or `--by-theme`; asks when neither is given. Without a THREAT_MODEL.md it asks whether to build one first (recommended) or do a quick run. Keywords: sectioned audit, parallel security audit, vulnerability chaining, attack surface inventory.

Works with✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/trebaud/swarm-security-audit/tree/HEAD/skills/swarm-audit

Installed? Explore more Coding & Development skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

Swarm audit

Inventory → split into sections → one worktree and one audit agent per section → each agent reports validated findings to the orchestrator → chain audit over all findings → one combined report. The orchestrator is the worktree you start in. Show the user each artifact before moving on; they decide scope and grouping.

0. Preflight

Before doing anything else, settle three things. Ask every open one in a single AskUserQuestion call (plainly if there is no question tool), then stop until the user answers.

Threat model. Find **/THREAT_MODEL.md, skipping vendored and installed dependency directories. If one exists with no template <…> placeholders, use it. Otherwise ask, unless the user already asked for a quick run:

  • Build a threat model first (Recommended): every section auditor and critic uses its controls and out-of-scope list, which cuts false positives across the whole swarm and surfaces business-logic bugs. Costs a few rounds of questions up front; later audits reuse it.
  • Quick run without one: no questions and no threat model; section auditors work from the inventory and the code alone. The fastest way to see what the swarm finds; expect more noise.

On Build, run the security-audit skill bundled with this plugin through the Skill tool in the orchestrator, asking for a threat model only, and wait for THREAT_MODEL.md before step 1.

Split strategy. If the arguments contain --by-group [N] or --by-theme, use it. Otherwise ask:

  • By theme (Recommended): sections follow what the code does (auth, account, payments, orders, admin, one per third-party integration). Each auditor sees a whole flow, so bugs that span several entry points are found. Sizes vary.
  • By group: fixed-size groups of about N entry points (ask N, default 25) in source order. Even workload per auditor, no judgement calls, but one flow can be cut across two sections; the chain audit (step 6) recovers some of that.

Scope. If the user named none, ask which services, directories or kinds of entry point to cover, and what to leave out.

1. Inventory the entry points

An entry point is any place outside input reaches the code: HTTP routes, GraphQL/RPC handlers, webhooks, queue and event consumers, scheduled jobs that read external data, CLI commands, file or upload processors, client-side message, deep-link or IPC handlers.

  • Find them with a parser for the repo's language (its compiler or language-server API, or tree-sitter), not regex: registrations span lines and take arrays. Keep the script in the scratchpad so it can be re-run.
  • Per entry point record: kind, name or method + path, who can reach it (public, logged-in, admin, internal, signed webhook), guards (auth, MFA, captcha, rate limit, input schema, signature check), handler, the whole middleware, decorator, filter or interceptor chain, file:line.
  • Easy to miss:
    • nested routers, controllers or handler groups registered under a prefix, and helper functions that register on an object passed in
    • handlers registered globally inside a helper: no prefix
    • middleware, filters or guards inherited from an earlier prefix-level or catch-all registration
    • one handler group registered twice: list once, note the alias
    • environment-only entry points (staging, debug, feature flags): mark them
    • entry points a dependency registers (auth servers, admin panels, health checks, job dashboards): read the package source, add them by hand
  • Find what is missing: grep client code (web app, mobile app, proxy, other services) for every path or message it sends, and list everything registered at the top level. Ask the user which to add; say which you left out and why.
  • Write the inventory to entry-points.md (or the name the user gives) in the orchestrator worktree.

2. Split into sections

  • By theme: group by what the code does, not by size, and never mix two trust boundaries (public, partner, internal, worker) in one section. Split a theme that is too big for one auditor.
  • By group: cut the inventory in order into groups of about N; keep entry points of one file together when that changes a group by only a few.
  • Show the proposed split (name, count, one line of contents, judgement calls) and wait for approval before writing it to the inventory file.

3. One worktree per section

Cut each section's worktree from the orchestrator's current commit, so every section audits the code the user is on. Use mori when command -v mori finds it, otherwise plain git:

morigit
Createmori new sec-audit-NN-<name> --from <current branch>; it prints the worktree path (under ~/.mori/worktrees/<repo>/) — record itgit worktree add ../<repo>-sec-audit-NN-<name> -b sec-audit-NN-<name>
Dependenciesinstalled by the repo's .mori.json post_create steps if it has them; otherwise install them yourselfinstall them yourself
Removecheck dirty in mori list --json, then mori remove <branch> -f; delete the branch if it remainscheck git status in it, then git worktree remove <dir> and git branch -D <branch>

On a detached HEAD, use git (git worktree add <dir> -b <branch> HEAD). Create the worktrees in the background.

  • Copy into each: AUDIT_SCOPE.md (the section's table, the column notes, "audit only these entry points"), the full inventory, and, if the threat model was built but isn't committed yet, a copy of it at the same path.
  • Create the inbox in the orchestrator: <orchestrator>/.security-audit/swarm/<section>/.
  • To redo the split: remove the old worktrees and their branches as above (never force-remove one with changes you haven't looked at), then recreate.

4. Run the section audits in parallel

Write one brief to the scratchpad and spawn one background agent per section pointing at it. The brief must say:

  • Work only in WORKTREE; read its agent instructions (CLAUDE.md, AGENTS.md). The only writes outside WORKTREE go to INBOX (absolute path to the section's inbox in the orchestrator).
  • Use the security-audit skill bundled with this plugin (or another the user names), through the Skill tool, scoped to @AUDIT_SCOPE.md; on a quick run, tell it this is a quick run so it never stops to ask. Without one: trace each input from entry point to sink with file:line, prove it is reachable past every control, drop anything not reachable.
  • With a threat model: read it in full before tracing; use its entry points, controls and out-of-scope list; never rewrite it. Quick run: no threat model, don't create one. Never ask questions.
  • Every candidate goes to a fresh critic sub-agent that assumes a false positive; if one can't be spawned, self-critique and say so per finding.
  • Critical/High: a failing test through the real entry point, run with the repo's test runner, left in the tree.
  • Report each finding to INBOX as soon as its critic returns, one file per finding (NN-<slug>.md), so nothing is lost if the agent's output is cut off. Format below.
  • Also report blocked candidates: a flow that reaches a sink but needs something the section can't supply (an id, a token, a victim action, a leaked value, a race). Use status: blocked and name exactly what is missing; another section may supply it.
  • Also write the section report to WORKTREE/.security-audit/<section>-<date>.md.
  • Hard rules: follow the repo's safety rules; no migrations or database scripts, no git writes, no calls to external services.
  • Final message: verdict line, one line per finding, how many files went to INBOX, unverified items, and how the audit skill was invoked.

Finding file format:

---
id: <section>-NN
status: validated | blocked
severity: critical | high | medium | low | info
critic: independent | self
entry_point: <method + path or handler name>
needs: <what the attacker must have before: account type, id, token, victim click, timing>
gives: <what the attacker has after: leaked value, write access, session, money, code execution>
test: <path or none>
---
One-line claim.

Trace: source `file:line` → … → sink `file:line`.
Repro: exact input (request, message, file) in a code block.
Controls checked: what was looked at and why it does not stop this.

needs and gives are what the chain audit joins on: write them concretely ("a victim's order id", not "some data").

You may audit one section inline yourself. Expect the concurrent sub-agent limit to block some critics.

5. Re-check before chaining

When every section agent has finished, read the inbox and compare file counts with each agent's final message. Then run a fresh critic yourself on:

  • any High or Critical with critic: self
  • any finding marked provisional, conditional or "depends on ": read that service's code if you have it and settle the question. Bugs at the boundary between two services are the ones each section misses alone.

Update the finding file with the critic's severity and keep the original in a was: line.

6. Chain audit

One last audit in the orchestrator over the whole inbox, with the inventory and threat model (if any) at hand. Run it inline or as one agent with the full inbox in its brief.

  1. Dedupe. Merge findings with the same root cause (same sink and same missing control) into one, listing every section and entry point that hits it. Two entry points into one bug are one finding with a wider blast radius, not two findings.
  2. Join. For every pair, check whether one finding's gives satisfies another's needs, including blocked candidates. Also look for the usual escalations:
    • information leak (id, email, token, internal URL) → IDOR, account takeover or SSRF that needed it
    • user enumeration + missing rate limit → credential stuffing or OTP brute force
    • self-XSS or HTML injection + CSRF or login CSRF → stored XSS on a victim
    • open redirect + OAuth or magic-link flow → token theft
    • mass assignment or weak validation + a privileged consumer downstream (worker, admin view, webhook)
    • race condition + balance, coupon, limit or one-time action → repeat gain
    • two low-impact business-logic gaps that together move money or bypass a limit
  3. Prove each chain. Trace it end to end with file:line at every link and the exact input at every step. A link that is not in the code is not a chain: don't invent one, and don't count a link that needs a precondition no finding or public action supplies.
  4. Critic each chain with a fresh sub-agent, in parallel. It assumes the steps don't connect in practice (different users, different sessions, expired tokens, ordering, one step already fixed by another control) and returns the chain's severity: impact of the final gain × likelihood of every step together, or "cleared".
  5. Test each Critical or High chain with one failing test that drives every step through the real entry points, in the orchestrator worktree.
  6. Write each chain to <orchestrator>/.security-audit/swarm/chains/NN-<slug>.md in the finding format, with links: listing the finding ids. Keep the component findings too.

7. Combined report

Write .security-audit/<scope>-combined-<date>.md in the orchestrator:

  1. Verdict line with counts after dedupe, chains counted separately ("3 chains, 2 raise severity"). On a quick run, open with the quick-run line from the security-audit skill's references/REPORT_FORMAT.md.
  2. Chains first: the steps as a numbered list with input and file:line, final gain, severity before and after chaining, critic, test path. Say which single fix breaks each chain.
  3. Critical/High write-ups: repro with the exact input, trace with file:line, gain and prerequisites, fix, critic, test path and what the test does not prove.
  4. Medium table, Low list (collapsed), blocked candidates that nothing unblocked (collapsed: they are leads, not findings).
  5. Patterns across sections.
  6. Coverage gaps and unverified items (cut-off agents, inbox count mismatches, production config, third-party behaviour, self-reviewed critics).
  7. Section table with the report path in each worktree.

Nothing is committed. Lead the chat summary with the chains and the Critical/High table, and say which fix to ship first: prefer the one that breaks the most chains.

Related Skills