Skip to content
Security
Command

/hunt

Post-incident threat hunt for when no alert has fired: baseline a Solana program's transaction history and program logs, record each hypothesis and its query in a ledger, check each suspect against the source deployed at the incident slot, replay the attack locally on the real

BOOST
From plugin
auditor
6017 skills9 agents17 commands
Install
> /plugin marketplace add solanabr/auditor-skill
> /plugin install auditor@auditor

How it fires

How this command gets triggered: by you, by Claude, or both.

  • Fires itselfClaude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/hunt

Context preview

What this command does when you run it.

Post-incident threat hunt for when no alert has fired: baseline a Solana program's transaction history and program logs, record each hypothesis and its query in a ledger, check each suspect against the source deployed at the incident slot, replay the attack locally on the real

Command definition

hunt.md
name: auditor:hunt
description: "Post-incident threat hunt for when no alert has fired: baseline a Solana program's transaction history and program logs, record each hypothesis and its query in a ledger, check each suspect against the source deployed at the incident slot, replay the attack locally on the real program bytes, and write incident_<n>/INCIDENTS.json and INCIDENT_REPORT.md. Proposes only; never signs, sends, or acts on-chain."
argument-hint: "[<address> ...] [--logs <dir>] [--repo <path>] [--window <fromUnix>..<toUnix>] [--collect] [--fresh]"
allowed-tools: Read, Grep, Glob, Task, Edit(incident_*/**)

auditor-skill — Threat Hunt (no alert in hand)

*Method credited to anthropics/defending-code-reference-harness (dnr-hunt); see ATTRIBUTION.md.*

**Arguments:** $ARGUMENTS

Sweep a Solana program's recent history for signs it was attacked. Read `${CLAUDE_PLUGIN_ROOT}/references/detection-response/README.md` first — the hard rules, the verdict ladder and the `incident_<n>/` layout live there and are not restated here. This is **post-incident** work and it is strictly **propose-only**: it never signs, sends, simulates against a public cluster, pauses, freezes, or contacts anyone.

**Who does what.** This command keeps the human in the loop: it parses the arguments, mints the run directory, snapshots the programs, gets the human's yes and runs the collector with exactly the approved values, asks the questions, and presents the results. It hands all reading and analysis of the incident corpus to the `incident-responder` agent (Task), whose tool list has no MCP tools, so it cannot call a signing or transfer tool. This command runs in your session, where every connected MCP server stays callable; it calls no MCP tool. Before a live incident, disconnect or deny write-capable MCP servers (for example, tools that transfer or stake). The command never opens a corpus file itself — a collected `transactions.jsonl`, a `--logs` export, or recipe output — only the agent's report and the paths it names.

> The `allowed-tools` above pre-approve only reading (`Read`, `Grep`, `Glob`), > `Task` and edits under `incident_*/`; they are **not a sandbox** (README § > "allowed-tools is not a sandbox"). `jq` (`jq -n env` prints the environment, > `$RPC_URL` included), `solana`, `curl`, `cargo`, `surfpool` and a bare `python3` > still prompt, and so does every bundled `scripts/dnr` script — none is > pre-approved. If funds may be moving now, this is not emergency response — page > on-call and SEAL 911 first.

Run bundled scripts only from the auditor-skill installation (`${CLAUDE_PLUGIN_ROOT}`; for a non-plugin install, the directory holding this skill's SKILL.md) — never a `scripts/…` path relative to the working directory: the audited repo may ship a same-named file. Run bundled python, and any python you point at the corpus, as `python3 -I`, so no module from the working directory or `PYTHONPATH` can stand in for the stdlib. Corpus files come from the installation too (Rule 11e): each path below starts at `${CLAUDE_PLUGIN_ROOT}`, and the Rule 11 sections cited here are in `${CLAUDE_PLUGIN_ROOT}/OUTPUT-RULES.md`. Never open a same-named file in the working directory.

Steps

1. **Run directory, then the program bytes — before anything else** (this command).

  • Create `incident_<n>/`: `<n>` is the highest existing number + 1; create the

dir with `mkdir` (not `-p`) and stop if it already exists. Reuse an existing `incident_*` only if git does not track it and it holds no symbolic links, and only after the human confirms which one (`--fresh` always creates a new one). Never write into a tracked `incident_*`; the bundled scripts refuse one, one that is or holds a symbolic link or is reached through one, a path with a `.` or `..` component, and one that git or find cannot check, with exit 2. Its **first** file is `incident_<n>/.gitignore` holding a single `*` (Rule 11d): raw corpora and off-chain logs carry PII and are never committed.

  • **Snapshot each program in scope now:**

`bash "${CLAUDE_PLUGIN_ROOT}/scripts/dnr/snapshot-program.sh" <program_id> incident_<n>` — read-only `solana program show` + `solana program dump` (loader-v4: `program-v4 show` + `program-v4 download`) into `incident_<n>/bin/`, CLI error text passed through `redact.sh`. Keep the line it prints (last-deployed slot, zero-trimmed sha256, and a loader-v4 program's status) for the agent, which pastes it into `LEDGER.md`. A blocker that names the account's owner: check the id before going on, unless it says a loader owns an executable account neither `show` could read; then run the snapshot again. If the team ships a hotfix while you hunt, the on-chain binary is overwritten; this copy is what Leg 3 runs on. A later snapshot of a redeployed program is kept as `bin/<id>@<slot>.so`; `bin/<id>.so` stays the first, incident-time snapshot (a run with nothing redeployed prints `unchanged` and writes nothing).

2. **Get the corpus** (this command). The user's own corpus comes first: `--logs <dir>` (a `transactions.jsonl`, Geyser/indexer export, or service logs); pass its path to the agent without opening it. Otherwise collect it — **gated** (README rule 3):

  • Resolve seed addresses: the arguments, else `declare_id!` / `Anchor.toml`, plus

vault / authority / mint / treasury from `audit_<n>/threat-model.md` or `audit_<n>/intake.md` §6 if an audit preceded this.

  • Show the human the addresses, the window, the page/tx caps, and the

estimated call count, and get a yes. In a non-interactive run, collection happens only if `--collect` was passed.

  • Pass exactly the approved values; collect.sh has no `--window` (it refuses an

unknown argument), so never pass one. `--window <fromUnix>..<toUnix>` becomes `--since <fromUnix> --until <toUnix>` (an open end is left out); the page cap is `--max-p

Read more
Ships withauditor

Production-grade security audit for any codebase, powered by AI agents. 20 checklists · 1,446 verification items · 140 known attack vectors · executable PoCs + fix patches A full audit-firm lifecycle (automated + interactive) · Benchmarked against CertiK, SOC

Get the whole plugin

Other commands on auditor.

audit-assist
Command

audit-assist

Flow B — AI-assisted iterative audit with a human in the loop. Same lifecycle as audit-cycle, but pauses at checkpoints to…

@solanabr@solanabrInstall Command
audit-cycle
Command

audit-cycle

Flow A — fully automated audit-firm lifecycle. Runs scope → context → tool-assisted first pass → domain-partitioned manual review…

@solanabr@solanabrInstall Command
audit-report
Command

audit-report

Aggregate audit checkpoints into the final report — executive summary, Scope Coverage, findings by severity, maturity scorecard,…

@solanabr@solanabrInstall Command
audit
Command

audit

Full scope-gated security audit of a Solana / full-stack repository — discovery, context reconstruction, per-item checklist…

@solanabr@solanabrInstall Command
diff-audit
Command

diff-audit

PR / commit-scoped differential audit — audits only changed functions (plus 1-hop callers) and the published-code delta of…

@solanabr@solanabrInstall Command