{"id":23153,"date":"2009-05-21T01:01:11","date_gmt":"2009-05-21T01:01:11","guid":{"rendered":"https:\/\/scannn.com\/evilsocket-audit-an-8-stage-vulnerability-discovery-agent-%c2%b7-github\/"},"modified":"2009-05-21T01:01:11","modified_gmt":"2009-05-21T01:01:11","slug":"evilsocket-audit-an-8-stage-vulnerability-discovery-agent-%c2%b7-github","status":"publish","type":"post","link":"https:\/\/scannn.com\/lv\/evilsocket-audit-an-8-stage-vulnerability-discovery-agent-%c2%b7-github\/","title":{"rendered":"evilsocket\/audit: An 8-stage vulnerability-discovery agent. \u00b7 GitHub"},"content":{"rendered":"\n<div id=\"\">\n<p dir=\"auto\">An 8-stage vulnerability-discovery agent, driven by your <strong>Claude Pro \/ Max<br \/>\nsubscription<\/strong> through the official Claude Code Agent SDK. Many narrow agents,<br \/>\ndeliberate disagreement, and an explicit reachability gate.<\/p>\n<p dir=\"auto\">MIT-licensed. No API key needed if you already use <code>claude login<\/code>.<\/p>\n<p dir=\"auto\">This project is a from-scratch reimplementation of the pipeline described in<br \/>\nCloudflare&#8217;s <a href=\"https:\/\/blog.cloudflare.com\/cyber-frontier-models\/\" rel=\"nofollow\">Project Glasswing<\/a><br \/>\npost, which tested Anthropic&#8217;s Mythos preview LLM against Cloudflare&#8217;s own<br \/>\ncodebase. The blog argues that real-world vulnerability discovery does <strong>not<\/strong><br \/>\ncome from asking one big model &#8220;find bugs here&#8221; \u2014 it comes from:<\/p>\n<ol dir=\"auto\">\n<li><strong>Many narrow agents<\/strong> working in parallel on tightly-scoped questions<br \/>\n(&#8220;Look for command injection in this specific function, with this trust<br \/>\nboundary above it&#8221;) rather than one exhaustive agent.<\/li>\n<li><strong>Deliberate disagreement<\/strong> \u2014 a second agent, on a different model, that<br \/>\ntries to <em>disprove<\/em> the first agent&#8217;s findings.<\/li>\n<li><strong>A reachability trace<\/strong> as the gating step \u2014 most &#8220;is this code buggy?&#8221;<br \/>\nfindings are noise unless an attacker-controlled input can actually reach<br \/>\nthe sink from outside the system.<\/li>\n<li><strong>A feedback loop<\/strong> so reachable bugs in one place automatically seed<br \/>\nhunts for the same pattern elsewhere.<\/li>\n<\/ol>\n<p dir=\"auto\">This repo packages that pipeline into a runnable agent. The Cloudflare post<br \/>\nshowed the architecture; this codebase ships the prompts, schemas, state<br \/>\nstore, and orchestrator.<\/p>\n<p dir=\"auto\"><a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https:\/\/raw.githubusercontent.com\/evilsocket\/audit\/main\/docs\/pipeline.png\"><\/a><\/p>\n<p dir=\"auto\"><sub>Diagram from Cloudflare&#8217;s <a href=\"https:\/\/blog.cloudflare.com\/cyber-frontier-models\/\" rel=\"nofollow\">Project Glasswing<\/a> post, reproduced here for reference.<\/sub><\/p>\n<p><markdown-accessiblity-table><\/p>\n<table>\n<thead>\n<tr>\n<th>#<\/th>\n<th>Stage<\/th>\n<th>Default model<\/th>\n<th>Purpose<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>1<\/td>\n<td>Recon<\/td>\n<td>Opus 4.7<\/td>\n<td>Map the repo, emit narrowly-scoped Hunt tasks<\/td>\n<\/tr>\n<tr>\n<td>2<\/td>\n<td>Hunt<\/td>\n<td>Sonnet 4.6<\/td>\n<td>One attack class per agent; compile\/run PoCs<\/td>\n<\/tr>\n<tr>\n<td>3<\/td>\n<td>Validate<\/td>\n<td>Opus 4.7<\/td>\n<td>Adversarial re-read; tries to <strong>disprove<\/strong> (different model from Hunt)<\/td>\n<\/tr>\n<tr>\n<td>4<\/td>\n<td>Gapfill<\/td>\n<td>Sonnet 4.6<\/td>\n<td>Re-queue under-covered areas<\/td>\n<\/tr>\n<tr>\n<td>5<\/td>\n<td>Dedupe<\/td>\n<td>Sonnet 4.6<\/td>\n<td>Cluster findings by root cause<\/td>\n<\/tr>\n<tr>\n<td>6<\/td>\n<td>Trace<\/td>\n<td>Opus 4.7<\/td>\n<td>Prove attacker-controlled input reaches the sink<\/td>\n<\/tr>\n<tr>\n<td>7<\/td>\n<td>Feedback<\/td>\n<td>Sonnet 4.6<\/td>\n<td>Turn reachable traces into new Hunt tasks<\/td>\n<\/tr>\n<tr>\n<td>8<\/td>\n<td>Report<\/td>\n<td>Sonnet 4.6<\/td>\n<td>Schema-validated structured report<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><\/markdown-accessiblity-table><\/p>\n<p dir=\"auto\">Each stage is one markdown prompt in <code>prompts\/<\/code> + one JSON Schema in<br \/>\n<code>schemas\/<\/code>. The orchestrator passes the schema into the system prompt so<br \/>\nevery output is shape-stable on the first try.<\/p>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"# 1. Install&#10;python -m venv .venv &amp;&amp; source .venv\/bin\/activate&#10;pip install -e .&#10;&#10;# 2. Auth (pick one)&#10;#    (a) Already logged in via claude login? You're done.&#10;#    (b) Or generate a 1-year OAuth token for CI \/ non-interactive use:&#10;claude setup-token&#10;echo &quot;CLAUDE_CODE_OAUTH_TOKEN=&lt;paste&gt;&quot; &gt; .env&#10;&#10;# 3. Verify&#10;audit auth-check&#10;&#10;# 4. Run&#10;audit run --repo \/path\/to\/target --run-id my-run&#10;audit status --run-id my-run&#10;audit report --run-id my-run --format md &gt; report.md\">\n<pre><span class=\"pl-c\"><span class=\"pl-c\">#<\/span> 1. Install<\/span>\npython -m venv .venv <span class=\"pl-k\">&amp;&amp;<\/span> <span class=\"pl-c1\">source<\/span> .venv\/bin\/activate\npip install -e <span class=\"pl-c1\">.<\/span>\n\n<span class=\"pl-c\"><span class=\"pl-c\">#<\/span> 2. Auth (pick one)<\/span>\n<span class=\"pl-c\"><span class=\"pl-c\">#<\/span>    (a) Already logged in via claude login? You're done.<\/span>\n<span class=\"pl-c\"><span class=\"pl-c\">#<\/span>    (b) Or generate a 1-year OAuth token for CI \/ non-interactive use:<\/span>\nclaude setup-token\n<span class=\"pl-c1\">echo<\/span> <span class=\"pl-s\"><span class=\"pl-pds\">\"<\/span>CLAUDE_CODE_OAUTH_TOKEN=&lt;paste&gt;<span class=\"pl-pds\">\"<\/span><\/span> <span class=\"pl-k\">&gt;<\/span> .env\n\n<span class=\"pl-c\"><span class=\"pl-c\">#<\/span> 3. Verify<\/span>\naudit auth-check\n\n<span class=\"pl-c\"><span class=\"pl-c\">#<\/span> 4. Run<\/span>\naudit run --repo \/path\/to\/target --run-id my-run\naudit status --run-id my-run\naudit report --run-id my-run --format md <span class=\"pl-k\">&gt;<\/span> report.md<\/pre>\n<\/div>\n<p dir=\"auto\">By default the agent uses <strong>subscription billing<\/strong> via your Claude.ai<br \/>\nlogin \u2014 it does <strong>not<\/strong> call the metered Anthropic API. The on-disk auth<br \/>\nmodule scrubs <code>ANTHROPIC_API_KEY<\/code> from the environment so it can&#8217;t<br \/>\nsilently route around the OAuth flow.<\/p>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Using a different model \/ provider<\/h2>\n<p><a id=\"user-content-using-a-different-model--provider\" class=\"anchor\" aria-label=\"Permalink: Using a different model \/ provider\" href=\"#using-a-different-model--provider\"><svg data-component=\"Octicon\" class=\"octicon octicon-link\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\/><\/svg><\/a><\/div>\n<p dir=\"auto\">The auth module picks one of three modes, in this order:<\/p>\n<ol dir=\"auto\">\n<li><strong>LLM gateway<\/strong> (OpenRouter, custom proxy, etc.) \u2014 when<br \/>\n<code>ANTHROPIC_BASE_URL<\/code> points away from <code>anthropic.com<\/code> AND<br \/>\n<code>ANTHROPIC_AUTH_TOKEN<\/code> is set. The gateway env is left intact;<br \/>\nonly <code>ANTHROPIC_API_KEY<\/code> is scrubbed (it would otherwise outrank the<br \/>\ngateway token).<\/li>\n<li><strong>Subscription OAuth (headless)<\/strong> \u2014 <code>CLAUDE_CODE_OAUTH_TOKEN<\/code> from<br \/>\n<code>claude setup-token<\/code>. Best for CI.<\/li>\n<li><strong>Subscription OAuth (interactive)<\/strong> \u2014 <code>~\/.claude\/.credentials.json<\/code><br \/>\nfrom <code>claude login<\/code>. Best for local dev.<\/li>\n<\/ol>\n<p dir=\"auto\">OpenRouter exposes Claude-compatible Anthropic-API endpoints behind its<br \/>\nown credit system; that lets you spend OpenRouter credits instead of an<br \/>\nAnthropic subscription, and gives you access to Sonnet\/Opus <em>and<\/em> other<br \/>\nmodels through the same SDK path. See <a href=\"https:\/\/openrouter.ai\/docs\/guides\/community\/anthropic-agent-sdk\" rel=\"nofollow\">OpenRouter&#8217;s Agent SDK guide<\/a>.<\/p>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"export ANTHROPIC_BASE_URL=&quot;https:\/\/openrouter.ai\/api&quot;&#10;export ANTHROPIC_AUTH_TOKEN=&quot;$OPENROUTER_API_KEY&quot;&#10;export ANTHROPIC_API_KEY=&quot;&quot;           # must be explicitly empty \/ unset&#10;# optional: pick a non-Anthropic model&#10;export ANTHROPIC_MODEL=&quot;anthropic\/claude-sonnet-4-6&quot;&#10;# or e.g.: ANTHROPIC_MODEL=&quot;openai\/gpt-5&quot;&#10;#         ANTHROPIC_MODEL=&quot;google\/gemini-2.5-pro&quot;&#10;#         ANTHROPIC_MODEL=&quot;qwen\/qwen3-coder-480b&quot;&#10;&#10;audit auth-check                       # confirms &quot;using LLM gateway at https:\/\/openrouter.ai\/api&quot;&#10;audit run --repo \/path\/to\/target --run-id orun --max-cost-usd 30\">\n<pre><span class=\"pl-k\">export<\/span> ANTHROPIC_BASE_URL=<span class=\"pl-s\"><span class=\"pl-pds\">\"<\/span>https:\/\/openrouter.ai\/api<span class=\"pl-pds\">\"<\/span><\/span>\n<span class=\"pl-k\">export<\/span> ANTHROPIC_AUTH_TOKEN=<span class=\"pl-s\"><span class=\"pl-pds\">\"<\/span><span class=\"pl-smi\">$OPENROUTER_API_KEY<\/span><span class=\"pl-pds\">\"<\/span><\/span>\n<span class=\"pl-k\">export<\/span> ANTHROPIC_API_KEY=<span class=\"pl-s\"><span class=\"pl-pds\">\"<\/span><span class=\"pl-pds\">\"<\/span><\/span>           <span class=\"pl-c\"><span class=\"pl-c\">#<\/span> must be explicitly empty \/ unset<\/span>\n<span class=\"pl-c\"><span class=\"pl-c\">#<\/span> optional: pick a non-Anthropic model<\/span>\n<span class=\"pl-k\">export<\/span> ANTHROPIC_MODEL=<span class=\"pl-s\"><span class=\"pl-pds\">\"<\/span>anthropic\/claude-sonnet-4-6<span class=\"pl-pds\">\"<\/span><\/span>\n<span class=\"pl-c\"><span class=\"pl-c\">#<\/span> or e.g.: ANTHROPIC_MODEL=\"openai\/gpt-5\"<\/span>\n<span class=\"pl-c\"><span class=\"pl-c\">#<\/span>         ANTHROPIC_MODEL=\"google\/gemini-2.5-pro\"<\/span>\n<span class=\"pl-c\"><span class=\"pl-c\">#<\/span>         ANTHROPIC_MODEL=\"qwen\/qwen3-coder-480b\"<\/span>\n\naudit auth-check                       <span class=\"pl-c\"><span class=\"pl-c\">#<\/span> confirms \"using LLM gateway at https:\/\/openrouter.ai\/api\"<\/span>\naudit run --repo \/path\/to\/target --run-id orun --max-cost-usd 30<\/pre>\n<\/div>\n<p dir=\"auto\">Caveats:<\/p>\n<ul dir=\"auto\">\n<li>Per-stage model overrides in <code>config\/stages.yaml<\/code> are model <strong>names<\/strong><br \/>\n(e.g. <code>claude-opus-4-7<\/code>); OpenRouter accepts slash-prefixed forms like<br \/>\n<code>anthropic\/claude-opus-4-7<\/code>. Edit the YAML if you want different<br \/>\nproviders per stage. Otherwise <code>ANTHROPIC_MODEL<\/code> forces every stage<br \/>\nonto one model.<\/li>\n<li>Non-Claude models may not produce schema-compliant JSON as reliably.<br \/>\nThe runner&#8217;s schema-validation + repair turn still applies; quality<br \/>\nvaries by model.<\/li>\n<li>Tool-use semantics (Read\/Grep\/Glob\/Bash) are part of the Claude Code<br \/>\nCLI, not the model \u2014 they work as long as the gateway speaks the<br \/>\nAnthropic Messages API.<\/li>\n<\/ul>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Other gateways \/ cloud providers<\/h3>\n<p><a id=\"user-content-other-gateways--cloud-providers\" class=\"anchor\" aria-label=\"Permalink: Other gateways \/ cloud providers\" href=\"#other-gateways--cloud-providers\"><svg data-component=\"Octicon\" class=\"octicon octicon-link\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\/><\/svg><\/a><\/div>\n<p dir=\"auto\">Same recipe \u2014 anything that exposes the Anthropic Messages API at a URL<\/p>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"export ANTHROPIC_BASE_URL=&quot;https:\/\/your-proxy.example.com&quot;&#10;export ANTHROPIC_AUTH_TOKEN=&quot;$YOUR_TOKEN&quot;&#10;unset ANTHROPIC_API_KEY\">\n<pre><span class=\"pl-k\">export<\/span> ANTHROPIC_BASE_URL=<span class=\"pl-s\"><span class=\"pl-pds\">\"<\/span>https:\/\/your-proxy.example.com<span class=\"pl-pds\">\"<\/span><\/span>\n<span class=\"pl-k\">export<\/span> ANTHROPIC_AUTH_TOKEN=<span class=\"pl-s\"><span class=\"pl-pds\">\"<\/span><span class=\"pl-smi\">$YOUR_TOKEN<\/span><span class=\"pl-pds\">\"<\/span><\/span>\n<span class=\"pl-c1\">unset<\/span> ANTHROPIC_API_KEY<\/pre>\n<\/div>\n<p dir=\"auto\">For Amazon Bedrock \/ Google Vertex \/ Microsoft Foundry, Claude Code has<br \/>\nfirst-class env-var flags (<code>CLAUDE_CODE_USE_BEDROCK=1<\/code> etc.) that<br \/>\noutrank everything else. See the <a href=\"https:\/\/code.claude.com\/docs\/en\/authentication\" rel=\"nofollow\">Claude Code auth docs<\/a>.<\/p>\n<p dir=\"auto\">A real production codebase can produce 15-50 Hunt tasks and 25+ findings to<br \/>\nvalidate. At default concurrency this gets expensive. Flags to keep it sane:<\/p>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"audit run --repo \/path\/to\/target \\&#10;  --max-concurrency 1 \\           # one claude subprocess at a time&#10;  --max-recon-tasks 15 \\          # cap initial Hunt fanout&#10;  --max-cost-usd 30               # abort cleanly if exceeded\">\n<pre>audit run --repo \/path\/to\/target \\\n  --max-concurrency 1 <span class=\"pl-cce\">\\ <\/span>          <span class=\"pl-c\"><span class=\"pl-c\">#<\/span> one claude subprocess at a time<\/span>\n  --max-recon-tasks 15 <span class=\"pl-cce\">\\ <\/span>         <span class=\"pl-c\"><span class=\"pl-c\">#<\/span> cap initial Hunt fanout<\/span>\n  --max-cost-usd 30               <span class=\"pl-c\"><span class=\"pl-c\">#<\/span> abort cleanly if exceeded<\/span><\/pre>\n<\/div>\n<p dir=\"auto\">The budget guard fires between <em>and<\/em> within stages \u2014 a per-task check in<br \/>\nHunt cooperatively aborts rather than running 30 more tasks past the cap.<\/p>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\">Live-target reproduction (optional)<\/h2>\n<p><a id=\"user-content-live-target-reproduction-optional\" class=\"anchor\" aria-label=\"Permalink: Live-target reproduction (optional)\" href=\"#live-target-reproduction-optional\"><svg data-component=\"Octicon\" class=\"octicon octicon-link\" viewbox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\/><\/svg><\/a><\/div>\n<p dir=\"auto\">If the target has a running deployment, point the agents at it. Hunt now<br \/>\n<strong>reproduces<\/strong> each finding against the live service instead of compiling<br \/>\na local PoC, Validate <strong>rejects<\/strong> findings that don&#8217;t reproduce, and Trace<br \/>\n<strong>confirms<\/strong> reachability with real HTTP round-trips. The static path<br \/>\nremains available \u2014 these flags are opt-in.<\/p>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"audit run --repo \/path\/to\/target --run-id live \\&#10;  --max-concurrency 1 --max-cost-usd 30 \\&#10;  --target-url http:\/\/server.local:8888 \\&#10;  --target-creds email=admin@system.com \\&#10;  --target-creds password=changechangeme\">\n<pre>audit run --repo \/path\/to\/target --run-id live \\\n  --max-concurrency 1 --max-cost-usd 30 \\\n  --target-url http:\/\/server.local:8888 \\\n  --target-creds email=admin@system.com \\\n  --target-creds password=changechangeme<\/pre>\n<\/div>\n<p dir=\"auto\">Rules the agents follow when <code>--target-url<\/code> is set:<\/p>\n<ul dir=\"auto\">\n<li>Network egress is restricted to that host + <code>127.0.0.1<\/code>. No other external<br \/>\nhosts.<\/li>\n<li>A finding that doesn&#8217;t reproduce against the live target is dropped or<br \/>\nrejected (depending on stage) \u2014 &#8220;no fabrication&#8221;.<\/li>\n<li>Credentials flow into every relevant stage&#8217;s user_input as a dict.<\/li>\n<\/ul>\n<p dir=\"auto\">Targets often have intentionally-loose-by-design surfaces that aren&#8217;t bugs<br \/>\n(e.g. plaintext API keys when that&#8217;s a feature, test-only Mailpit endpoints,<br \/>\nanonymous-analytics ingest). Drop them in a text file and pass it in \u2014 the<br \/>\nnotes are appended verbatim to every stage&#8217;s user_input, and Recon \/ Hunt \/<br \/>\nValidate honor exclusions you list.<\/p>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"audit run --repo \/path\/to\/target --scope-notes target_scope.md\">\n<pre>audit run --repo \/path\/to\/target --scope-notes target_scope.md<\/pre>\n<\/div>\n<p dir=\"auto\">Example <code>target_scope.md<\/code>:<\/p>\n<div class=\"highlight highlight-text-md notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"- Mailpit (port 1025) is test-only; ignore.&#10;- Plaintext API keys in the database are a required feature.&#10;- Don't flag rate-limit absence on anonymous \/ping endpoints.&#10;- Only consider critical\/high severity.\">\n<pre><span class=\"pl-v\">-<\/span> Mailpit (port 1025) is test-only; ignore.\n<span class=\"pl-v\">-<\/span> Plaintext API keys in the database are a required feature.\n<span class=\"pl-v\">-<\/span> Don't flag rate-limit absence on anonymous \/ping endpoints.\n<span class=\"pl-v\">-<\/span> Only consider critical\/high severity.<\/pre>\n<\/div>\n<p dir=\"auto\">Recon greps the git history for past security patches<br \/>\n(<code>CVE<\/code>, <code>sec:<\/code>, <code>fix.*auth<\/code>, <code>sanitize<\/code>, \u2026) \u2014 patched files are hardened,<br \/>\nbut <strong>sibling files with the same idiom often aren&#8217;t<\/strong>. Findings get seeded<br \/>\nagainst the unpatched copies. Adds zero cost on repos without that pattern;<br \/>\ncatches real cross-component bugs on repos that have it.<\/p>\n<p dir=\"auto\">The pipeline&#8217;s default is one-attack-class-per-task (the Cloudflare paper&#8217;s<br \/>\nnarrow-scope rule). Recon can also emit <code>logic_chain<\/code> tasks for high-impact<br \/>\nmulti-component paths (auth-bypass + IDOR + path-traversal that compose into<br \/>\nRCE, etc.) \u2014 one chain per task, with the <code>scope_hint<\/code> naming the specific<br \/>\nchain. This is the one allowed exception to single-attack-class scoping.<\/p>\n<div class=\"snippet-clipboard-content notranslate position-relative overflow-auto\" data-snippet-clipboard-copy-content=\"prompts\/        8 stage prompts (markdown, loaded as system prompts)&#10;schemas\/        9 JSON schemas \u2014 every agent output is validated&#10;config\/         stages.yaml \u2014 model + concurrency + tool allowlist per stage&#10;audit\/          Python package&#10;  auth.py       OAuth check + ANTHROPIC_API_KEY scrubbing&#10;  state.py      SQLite DAO (runs, tasks, findings, traces, dedupe, costs)&#10;  runner.py     claude-agent-sdk wrapper with schema validation + repair turn&#10;  orchestrator.py pipeline driver&#10;  stages\/       one module per stage&#10;work\/           per-Hunt-task scratch dirs (sandbox for PoC compile\/run)&#10;results\/        JSONL artifacts per stage + final report.json&#10;state.db        SQLite (gitignored)\">\n<pre class=\"notranslate\"><code>prompts\/        8 stage prompts (markdown, loaded as system prompts)\nschemas\/        9 JSON schemas \u2014 every agent output is validated\nconfig\/         stages.yaml \u2014 model + concurrency + tool allowlist per stage\naudit\/          Python package\n  auth.py       OAuth check + ANTHROPIC_API_KEY scrubbing\n  state.py      SQLite DAO (runs, tasks, findings, traces, dedupe, costs)\n  runner.py     claude-agent-sdk wrapper with schema validation + repair turn\n  orchestrator.py pipeline driver\n  stages\/       one module per stage\nwork\/           per-Hunt-task scratch dirs (sandbox for PoC compile\/run)\nresults\/        JSONL artifacts per stage + final report.json\nstate.db        SQLite (gitignored)\n<\/code><\/pre>\n<\/div>\n<p dir=\"auto\">Hunt agents have Bash and run inside per-task scratch dirs. They are <strong>not<\/strong><br \/>\nsandboxed at the OS level. Run the audit inside a disposable VM or container<br \/>\nwhen you don&#8217;t trust the target source \u2014 a target with malicious build<br \/>\nscripts could otherwise execute on your host during PoC compilation.<\/p>\n<p dir=\"auto\">The agent reads everything you <code>--add-dir<\/code>, including any <code>.env<\/code> or<br \/>\n<code>secrets\/<\/code> directories in the target. Outputs land in <code>results\/&lt;run-id&gt;\/<\/code><br \/>\nwhich is <code>.gitignore<\/code>d but <strong>not<\/strong> scrubbed of those reads.<\/p>\n<p dir=\"auto\"><a href=\"https:\/\/github.com\/evilsocket\/audit\/blob\/main\/LICENSE\">MIT<\/a>. Reuse freely. No warranty.<\/p>\n<\/div>\n<p><a href=\"https:\/\/github.com\/evilsocket\/audit?utm_source=tldrinfosec\">Source link <\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>An 8-stage vulnerability-discovery agent, driven by your Claude Pro \/ Max subscription through the official Claude Code Agent SDK. Many narrow agents, deliberate disagreement, and an explicit reachability gate. MIT-licensed. No API key needed if you already use claude login. This project is a from-scratch reimplementation of the pipeline described in Cloudflare&#8217;s Project Glasswing post, [&hellip;]<\/p>\n","protected":false},"author":16,"featured_media":23154,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[143],"tags":[],"class_list":["post-23153","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai"],"_links":{"self":[{"href":"https:\/\/scannn.com\/lv\/wp-json\/wp\/v2\/posts\/23153","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/scannn.com\/lv\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/scannn.com\/lv\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/scannn.com\/lv\/wp-json\/wp\/v2\/users\/16"}],"replies":[{"embeddable":true,"href":"https:\/\/scannn.com\/lv\/wp-json\/wp\/v2\/comments?post=23153"}],"version-history":[{"count":0,"href":"https:\/\/scannn.com\/lv\/wp-json\/wp\/v2\/posts\/23153\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/scannn.com\/lv\/wp-json\/wp\/v2\/media\/23154"}],"wp:attachment":[{"href":"https:\/\/scannn.com\/lv\/wp-json\/wp\/v2\/media?parent=23153"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/scannn.com\/lv\/wp-json\/wp\/v2\/categories?post=23153"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/scannn.com\/lv\/wp-json\/wp\/v2\/tags?post=23153"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}