diff --git a/solidity-auditor/README.md b/solidity-auditor/README.md index 4474e87..7e535bc 100644 --- a/solidity-auditor/README.md +++ b/solidity-auditor/README.md @@ -33,6 +33,21 @@ _Portrayed below: finding multiple high-confidence vulnerabilities in a codebase /solidity-auditor --file-output ``` +## Constraints (optional) + +Drop a `.pashov-skills-constraints.yaml` in your repo root to tell the skill what your codebase does and doesn't use. Agents will skip irrelevant attack vectors during triage, reducing noise and scan time. + +```yaml +tokens: [USDC, WETH] # skip exotic-token vectors +standards: [ERC20] # skip ERC721/ERC1155/ERC4626 vectors +cross_chain: false # skip LayerZero/bridge vectors +proxy_pattern: none # none | transparent | uups | diamond | beacon +oracle: chainlink # chainlink | twap | pyth | custom | none +account_abstraction: false # skip ERC-4337 vectors +``` + +All fields optional. Code overrides constraints. + ## Known Limitations **Codebase size.** Works best up to ~2,500 lines of Solidity. Past ~5,000 lines, triage accuracy and mid-bundle recall drop noticeably. For large codebases, run per module rather than everything at once. diff --git a/solidity-auditor/SKILL.md b/solidity-auditor/SKILL.md index 62967c5..ed124ea 100644 --- a/solidity-auditor/SKILL.md +++ b/solidity-auditor/SKILL.md @@ -19,6 +19,21 @@ You are the orchestrator of a parallelized smart contract security audit. Your j - `--file-output` (off by default): also write the report to a markdown file (path per `{resolved_path}/report-formatting.md`). Without this flag, output goes to the terminal only. Never write a report file unless the user explicitly passes `--file-output`. +## Constraints (optional) + +If a `.pashov-skills-constraints.yaml` file exists in the repository root, the orchestrator reads it during discovery and includes it in every agent bundle. Agents use declared constraints to fast-track **Skip** classification during triage. Constraints describe factual codebase properties, not security assumptions. Code overrides constraints. + +Supported fields (all optional, unknown fields ignored): + +```yaml +tokens: [USDC, WETH] # accepted token list (skip exotic-token vectors if set) +standards: [ERC20] # implemented standards (skip unlisted standard vectors) +cross_chain: false # no bridge/LayerZero/cross-chain logic +proxy_pattern: none # none | transparent | uups | diamond | beacon +oracle: chainlink # chainlink | twap | pyth | custom | none +account_abstraction: false # no ERC-4337 / smart account logic +``` + ## Version Check After printing the banner, run two parallel tool calls: (a) Read the local `VERSION` file from the same directory as this skill, (b) Bash `curl -sf https://raw.githubusercontent.com/pashov/skills/main/solidity-auditor/VERSION`. If the remote fetch succeeds and the versions differ, print: @@ -29,16 +44,16 @@ Then continue normally. If the fetch fails (offline, timeout), skip silently. ## Orchestration -**Turn 1 — Discover.** Print the banner, then in the same message make parallel tool calls: (a) Bash `find` for in-scope `.sol` files per mode selection, (b) Glob for `**/references/attack-vectors/attack-vectors-1.md` and extract the `references/` directory path (two levels up). Use this resolved path as `{resolved_path}` for all subsequent references. +**Turn 1 — Discover.** Print the banner, then in the same message make parallel tool calls: (a) Bash `find` for in-scope `.sol` files per mode selection, (b) Glob for `**/references/attack-vectors/attack-vectors-1.md` and extract the `references/` directory path (two levels up), (c) Read `.pashov-skills-constraints.yaml` from the repository root (if not found, continue without constraints). Use this resolved path as `{resolved_path}` for all subsequent references. -**Turn 2 — Prepare.** In a single message, make three parallel tool calls: (a) Read `{resolved_path}/agents/vector-scan-agent.md`, (b) Read `{resolved_path}/report-formatting.md`, (c) Bash: create four per-agent bundle files (`/tmp/audit-agent-{1,2,3,4}-bundle.md`) in a **single command** — each concatenates **all** in-scope `.sol` files (with `### path` headers and fenced code blocks), then `{resolved_path}/judging.md`, then `{resolved_path}/report-formatting.md`, then `{resolved_path}/attack-vectors/attack-vectors-N.md`; print line counts. Every agent receives the full codebase — only the attack-vectors file differs per agent. Do NOT read or inline any file content into agent prompts — the bundle files replace that entirely. +**Turn 2 — Prepare.** In a single message, make three parallel tool calls: (a) Read `{resolved_path}/agents/vector-scan-agent.md`, (b) Read `{resolved_path}/report-formatting.md`, (c) Bash: create four per-agent bundle files (`/tmp/audit-agent-{1,2,3,4}-bundle.md`) in a **single command** — if constraints were found in Turn 1, each bundle starts with a `## Constraints` section containing the raw YAML content; then concatenate **all** in-scope `.sol` files (with `### path` headers and fenced code blocks), then `{resolved_path}/judging.md`, then `{resolved_path}/report-formatting.md`, then `{resolved_path}/attack-vectors/attack-vectors-N.md`; print line counts. Every agent receives the full codebase — only the attack-vectors file differs per agent. Do NOT read or inline any file content into agent prompts — the bundle files replace that entirely. **Turn 3 — Spawn.** In a single message, spawn all agents as parallel foreground Agent tool calls (do NOT use `run_in_background`). Always spawn Agents 1–4. Only spawn Agent 5 when the mode is **DEEP**. - **Agents 1–4** (vector scanning) — spawn with `model: "sonnet"`. Each agent prompt must contain the full text of `vector-scan-agent.md` (read in Turn 2, paste into every prompt). After the instructions, add: `Your bundle file is /tmp/audit-agent-N-bundle.md (XXXX lines).` (substitute the real line count). -- **Agent 5** (adversarial reasoning, DEEP only) — spawn with `model: "opus"`. Receives the in-scope `.sol` file paths and the instruction: your reference directory is `{resolved_path}`. Read `{resolved_path}/agents/adversarial-reasoning-agent.md` for your full instructions. +- **Agent 5** (adversarial reasoning, DEEP only) — spawn with `model: "opus"`. Receives the in-scope `.sol` file paths and the instruction: your reference directory is `{resolved_path}`. If constraints were found in Turn 1, also include: the constraints file is at `.pashov-skills-constraints.yaml` in the repository root. Read `{resolved_path}/agents/adversarial-reasoning-agent.md` for your full instructions. -**Turn 4 — Report.** Merge all agent results: deduplicate by root cause (keep the higher-confidence version), sort by confidence highest-first, re-number sequentially, and insert the **Below Confidence Threshold** separator row. Print findings directly — do not re-draft or re-describe them. Use report-formatting.md (read in Turn 2) for the scope table and output structure. If `--file-output` is set, write the report to a file (path per report-formatting.md) and print the path. +**Turn 4 — Report.** Merge all agent results: deduplicate by root cause (keep the higher-confidence version), sort by confidence highest-first, re-number sequentially, and insert the **Below Confidence Threshold** separator row. Print findings directly — do not re-draft or re-describe them. Use report-formatting.md (read in Turn 2) for the scope table and output structure. If constraints were loaded, add a **Constraints** row to the scope table showing the declared values. If `--file-output` is set, write the report to a file (path per report-formatting.md) and print the path. ## Banner diff --git a/solidity-auditor/references/agents/adversarial-reasoning-agent.md b/solidity-auditor/references/agents/adversarial-reasoning-agent.md index 6216757..84901da 100644 --- a/solidity-auditor/references/agents/adversarial-reasoning-agent.md +++ b/solidity-auditor/references/agents/adversarial-reasoning-agent.md @@ -8,8 +8,9 @@ You communicate results back ONLY through your final text response. Do not outpu ## Workflow -1. Read all in-scope `.sol` files, plus `judging.md` and `report-formatting.md` from the reference directory provided in your prompt, in a single parallel batch. Do not use any attack vector reference files. -2. Reason freely about the code — look for logic errors, unsafe external interactions, access control gaps, economic exploits, and any other vulnerability you can construct a concrete attack path for. For each potential finding, apply the FP gate from `judging.md` immediately (three checks). If any check fails → drop and move on without elaborating. Only if all three pass → trace the full attack path, apply score deductions, and format the finding. -3. Your final response message MUST contain every finding **already formatted per `report-formatting.md`** — indicator + bold numbered title, location · confidence line, **Description** with one-sentence explanation, and **Fix** with diff block (omit fix for findings below 80 confidence). Use placeholder sequential numbers (the main agent will re-number). -4. Do not output findings during analysis — compile them all and return them together as your final response. -5. If you find NO findings, respond with "No findings." +1. Read all in-scope `.sol` files, plus `judging.md`, `report-formatting.md`, and `.pashov-skills-constraints.yaml` (if it exists) from the reference directory provided in your prompt, in a single parallel batch. Do not use any attack vector reference files. +2. If `.pashov-skills-constraints.yaml` was found, note the declared codebase properties and use them to focus your analysis on relevant attack surfaces. Constraints describe codebase properties, not security assumptions — code overrides constraints. +3. Reason freely about the code — look for logic errors, unsafe external interactions, access control gaps, economic exploits, and any other vulnerability you can construct a concrete attack path for. For each potential finding, apply the FP gate from `judging.md` immediately (three checks). If any check fails → drop and move on without elaborating. Only if all three pass → trace the full attack path, apply score deductions, and format the finding. +4. Your final response message MUST contain every finding **already formatted per `report-formatting.md`** — indicator + bold numbered title, location · confidence line, **Description** with one-sentence explanation, and **Fix** with diff block (omit fix for findings below 80 confidence). Use placeholder sequential numbers (the main agent will re-number). +5. Do not output findings during analysis — compile them all and return them together as your final response. +6. If you find NO findings, respond with "No findings." diff --git a/solidity-auditor/references/agents/vector-scan-agent.md b/solidity-auditor/references/agents/vector-scan-agent.md index 3d5ae15..453c1fe 100644 --- a/solidity-auditor/references/agents/vector-scan-agent.md +++ b/solidity-auditor/references/agents/vector-scan-agent.md @@ -9,7 +9,9 @@ You communicate results back ONLY through your final text response. Do not outpu ## Workflow 1. Read your bundle file in **parallel 1000-line chunks** on your first turn. The line count is in your prompt — compute the offsets and issue all Read calls at once (e.g., for a 5000-line file: `Read(file, limit=1000)`, `Read(file, offset=1000, limit=1000)`, `Read(file, offset=2000, limit=1000)`, `Read(file, offset=3000, limit=1000)`, `Read(file, offset=4000, limit=1000)`). Do NOT read without a limit. These are your ONLY file reads — do NOT read any other file after this step. -2. **Triage pass.** For each vector, classify into three tiers: +2. **Triage pass.** If a `## Constraints` section is present at the top of your bundle, use it to fast-track Skip classification. For example, if `cross_chain: false`, skip all cross-chain/bridge vectors without further analysis. If `standards: [ERC20]`, skip ERC721/ERC1155/ERC4626-specific vectors. Constraints describe codebase properties, not security assumptions. Code overrides constraints — classify based on what the code actually contains. + + For each vector, classify into three tiers: - **Skip** — the named construct AND underlying concept are both absent (e.g., ERC721 vectors when there are no NFTs at all). - **Borderline** — the named construct is absent but the underlying vulnerability concept could manifest through a different mechanism in this codebase (e.g., "stale cached ERC20 balance" when the code caches cross-contract AMM reserves; "ERC777 reentrancy" when there are flash-swap callbacks). - **Survive** — the construct or pattern is clearly present. diff --git a/solidity-auditor/references/report-formatting.md b/solidity-auditor/references/report-formatting.md index 54e13c8..9a40985 100644 --- a/solidity-auditor/references/report-formatting.md +++ b/solidity-auditor/references/report-formatting.md @@ -18,6 +18,7 @@ Save the report to `assets/findings/{project-name}-pashov-ai-audit-report-{times | **Mode** | ALL / default / filename | | **Files reviewed** | `File1.sol` · `File2.sol`
`File3.sol` · `File4.sol` | | **Confidence threshold (1-100)** | N | +| **Constraints** | _if `.pashov-skills-constraints.yaml` found, list declared values; otherwise omit this row_ | ---