arcuru/vuln-scanner

GitHub: arcuru/vuln-scanner

一个基于 LLM 的多阶段漏洞扫描器,通过对代码仓库构建持续累积的调查目录来实现深度安全审计。

Stars: 0 | Forks: 0

# vuln-scanner LLM 驱动的漏洞扫描器,为每个扫描目标构建一个 **调查目录** ,随着目标的演进和模型的改进,跨运行积累历史记录。 ``` recon → hunt → validate → dedupe → consolidate (per run) ``` ## 前置条件 - Python 3.12+ - 用于依赖和环境管理的 [`uv`](https://docs.astral.sh/uv/) - `$PATH` 中的 `git` - 针对所选后端的 agent CLI,需通过身份验证: - [`claude`](https://github.com/anthropics/claude-code) — 默认后端 - [`pi`](https://github.com/anthropics/oh-my-pi) — 备选后端 - 你通过自定义 `[agent.backends.*]` 条目接入的其他任何后端 ## 安装 ``` # 在不全局安装的情况下从 checkout 运行 uv run vuln-scanner --help # 或者安装为 uv tool(将 `vuln-scanner` 放入 $PATH) uv tool install . ``` ## 快速开始 为调查创建一个文件夹,针对目标进行构建,运行扫描,检查状态。 ``` mkdir cool-project-scan && cd cool-project-scan # 将 target 克隆到 ./target/,写入 vuln-scanner.toml + MANIFEST.toml uv run vuln-scanner init https://github.com/user/cool-project # 运行扫描(使用 target 当前的 HEAD;传递 --sha 以固定 commit) uv run vuln-scanner run -j 8 # 稍后重新运行(target 可能有新的 commit,或者有更新的 model 可用); # 下一次 recon 会读取之前的运行记录并提议全新的调查 uv run vuln-scanner run --sha # 查看运行历史 uv run vuln-scanner status ``` 调查文件夹是自包含的。你可以移动它、归档它,或者将其提交到自己的 git 仓库中 —— 它始终保持一致。 ## 扫描归档 此仓库还通过位于 [`scans/`](scans/) 的 git 子模块([`arcuru/vuln-scans`](https://github.com/arcuru/vuln-scans))对扫描记录进行归档。每个子文件夹都是一个调查目录:配置 + 清单 + 每次运行的输出。克隆的目标和临时的 worktree 被 gitignore 忽略,因此提交的内容就是审计追踪记录。 使用 `--recurse-submodules` 进行克隆,以便在工具旁边拉取扫描归档。 | 目标 | 源 | |---|---| | [`cmprss`](scans/cmprss/) | | 从仓库根目录,扫描现有目标或添加一个新目标: ``` # 对 target 运行扫描(位于树中的任何位置) vuln-scanner run -C scans/cmprss -j 8 # 添加新的 target mkdir scans/ && cd scans/ vuln-scanner init https://github.com/owner/repo vuln-scanner run -j 8 ``` ## CLI 参考 ``` $ vuln-scanner --help usage: vuln-scanner [-h] {init,run,status} ... Multi-phase LLM vulnerability scanner over a single target investigation. positional arguments: {init,run,status} init Initialize an investigation directory in cwd (clones target, writes config). run Execute one scan run against target/ in cwd. status List runs in this investigation. $ vuln-scanner init --help usage: vuln-scanner init [-h] [-c CONFIG] target_url positional arguments: target_url Git URL of the target repo to clone options: -c, --config CONFIG Path to a vuln-scanner.toml to copy in (default: minimal built-in) $ vuln-scanner run --help usage: vuln-scanner run [-h] [-C DIR] [--sha SHA] [-j JOBS] [-v] options: -C, --dir DIR Investigation directory to operate on (default: cwd) --sha SHA Target commit SHA to pin (default: keep current target HEAD) -j, --jobs JOBS Parallel workers (default: 4) -v, --verbose $ vuln-scanner status --help usage: vuln-scanner status [-h] [-C DIR] options: -C, --dir DIR Investigation directory to operate on (default: cwd) ``` ## 调查目录 `init` 用于构建,`run` 生成不可变的单次运行目录,顶层的 `SUMMARY.md` 始终指向最新的一次运行: ``` my-investigation/ vuln-scanner.toml # config (committed) MANIFEST.toml # target URL, latest-run pointer target/ # cloned scan target (gitignored) worktrees/ # ephemeral worktrees (gitignored) .vuln-scanner.lock # concurrency guard runs/ 2026-05-20T14-30-abc1234/ # ISO timestamp + short target SHA manifest.toml # tool version, target SHA, status, summary config.toml # effective config snapshot for this run logs/.log # agent stdout (or SDK event stream) transcripts/.jsonl # full Claude transcript per task recon/ HUNT_QUEUE.json task.toml # backend, model, session_id, timings hunt// FINDING.md task.toml validate// VERIFICATION.md task.toml dedupe/FINDINGS.md consolidate/ SUMMARY.md # cumulative across all runs task.toml SUMMARY.md → runs//consolidate/SUMMARY.md ``` 每个运行目录都是自描述的:`config.toml` 是运行时对 `vuln-scanner.toml` 解析后的视图,而每个任务的 `task.toml` 记录了确切的后端调用(argv 或 SDK 选项)、session UUID、使用的模型、持续时间和成本。匹配的 `transcripts/.jsonl` 是从 `~/.claude/projects/` 中复制出来的完整 Claude session 日志。 `init` 写入的 `.gitignore` 涵盖了 `target/`、`worktrees/` 和 lockfile —— 因此你可以在调查文件夹中运行 `git init` 并跟踪配置 + 运行情况,而无需将目标的完整历史记录一并拖入。 ## 工作原理 每个阶段都在脱离 `target/` 的独立 git worktree 中运行,从而按任务隔离 agent 产生的制品: 1. **recon** — 单个任务。映射架构并生成 `HUNT_QUEUE.json`。在后续的延续运行中,还会读取先前运行的 `SUMMARY.md` 以及自上次目标 SHA 以来的 git diff,随后生成一个包含全新调查和值得重新审查的队列。 2. **hunt** — 从队列中进行发散。每个条目代表特定范围内的一个攻击类别。每个任务生成一个 `FINDING.md`。 3. **validate** — 从 hunt 任务中进行发散。对每个发现进行对抗性审查。每个任务生成一个 `VERIFICATION.md`。 4. **dedupe** — 单个任务。按根本原因对确认的发现进行分组,记录被拒绝的调查以便未来的 recon 可以跳过它们,并记录*失败*的调查(即 agent 在产生输出前崩溃或超时的任务 —— 结果未知,代码路径未被排除)以便未来的运行重新尝试它们。生成 `FINDINGS.md`。 5. **consolidate** — 单个任务。生成累积的 `SUMMARY.md`,其中每个发现都相对于先前的运行被标记为 **NEW** / **PERSISTS** / **FIXED** / **REGRESSED**,并且包含一个“失败调查”部分,列出了本次运行中结果未知的任务。 每次运行都会从 `.done` 标记处恢复 —— 如果中断,重新运行 `run`(不带 `--sha`)会在相同的运行目录中从上次中断的地方继续。 同一调查文件夹中并发的 `run` 调用会通过 lockfile 拒绝执行。 如果 recon 判定没有新的内容可供调查(在未更改目标上的延续运行),它会写入一个空队列,流水线将提前退出。 ## 配置 分为两层:一个 **prompt profile**(包含 prompt 函数的 Python 模块,以及 markdown 内容)和一个 **TOML config**(设置覆盖)。 ### Prompt profile(Python + markdown) 内置的 profile 是 `vuln-scan`(位于 `src/vuln_scanner/configs/vuln_scan.py`)。Prompt 内容与其同存于 `src/vuln_scanner/configs/prompts/` —— 每个阶段一个 `.md` 文件,在渲染时替换 `$variable` 占位符: ``` configs/ vuln_scan.py # settings + glue (loads + renders the .md files) prompts/ _environment.md # shared snippet injected into every prompt recon.md # uses $prior_runs_path for continuation runs hunt.md # uses $attack_class, $scope, $entry_point, … validate.md dedupe.md consolidate.md # uses $prior_runs_path ``` 要微调发送给 agent 的内容,只需编辑 markdown —— 无需更改 Python。profile 模块上所需的 prompt 函数: - `recon_prompt(*, prior_runs_path: str = "") -> str` - `hunt_prompt(*, attack_class, scope, function, entry_point, rationale, arch_summary) -> str` - `validate_prompt() -> str` 可选:`dedupe_prompt()`、`consolidate_prompt(output_dir, *, prior_runs_path="")`。 通过复制 `vuln_scan.py`(以及 `prompts/` 目录)来编写你自己的 profile,并在 `vuln-scanner.toml` 中通过 `[scan] prompt_profile = "..."` 指向它。 ### 设置 (TOML) `init` 会将一个最小化的 `vuln-scanner.toml` 写入调查文件夹(除非你传入 `-c ` 来复制你自己的配置): ``` [scan] prompt_profile = "vuln-scan" [agent] backend = "claude" # [agent.models] # recon = "claude-sonnet-4-6" # hunt = "claude-sonnet-4-6" # validate = "claude-opus-4-7" ``` 请参阅 [`vuln-scanner.example.toml`](vuln-scanner.example.toml) 获取带有注释的完整选项集合。关键部分: | 部分 | 用途 | |---|---| | `attack_classes` (顶层) | 要扫描的漏洞类别 | | `[scan]` | Profile、分支前缀、并行度、超时 | | `[scan.task_timeouts]` | 每个阶段的超时覆盖(秒) | | `[agent]` | 后端名称和标志 | | `[agent.models]` | 每个阶段的模型名称 | | `[agent.backends.]` | 在配置中定义自定义后端 | | `[output]` | 每个阶段的输出文件名 | | `[files]` | 文件扩展名和排除目录 | ### 后端 内置后端: - `claude` — 以子进程方式运行 Claude Code CLI (`claude -p`);默认后端。 - `claude-sdk` — 使用进程内的 [`claude-agent-sdk`](https://pypi.org/project/claude-agent-sdk/) Python 库。使用与 `claude` 相同的模型和工具,但会将结构化事件(assistant 轮次、工具调用、带有 token 和成本信息的最终 `ResultMessage`)流式传输到每个任务的日志文件中。 - `pi` — Oh My Pi agent CLI。 通过 `[agent] backend = "..."` 进行设置。 可以直接在 TOML 中定义自定义后端 —— 无需 Python 代码: ``` [agent] backend = "gemini" [agent.backends.gemini] executable = "gemini-cli" model_flag = "--model" prompt_flag = "--prompt" extra_args = ["--yes"] ``` 字段:`executable`(必需)、`prompt_flag`(必需)、`model_flag`(可选)、`extra_args`(可选)。生成的命令如下: ``` gemini-cli --yes --model --prompt ``` 对于需要超越标志的自定义逻辑的后端,请在 `src/vuln_scanner/claude.py` 中实现 `Backend` 协议,并将其添加到 `BACKENDS` 注册表中。 ### 超时 `task_timeout` 设置全局默认值(0 = 无超时)。`task_timeouts` 会覆盖每个阶段的设置: ``` [scan] task_timeout = 0 # global default: no timeout [scan.task_timeouts] hunt = 900 # 15 minutes per hunt task validate = 600 ``` 当触发超时时,agent 子进程会先收到 SIGTERM,然后在 5 秒后收到 SIGKILL。 ## 开发 ``` # 安装 dev dependencies uv sync --extra dev # 运行 tests uv run pytest tests/ -v # Type check uv run pyright src/ ``` ## 致谢 多阶段的 recon → hunt → validate → dedupe → consolidate 架构改编自 Cloudflare 在 ["Cyber frontier models: Claude's strengths in software security"](https://blog.cloudflare.com/cyber-frontier-models/) 中描述的设计,该文章阐述了本项目在 Claude Code(或任何其他 agent CLI)之上重新实现的 agentic 漏洞研究流水线。Cloudflare 进程内的 gapfill / hunt2 / validate2 第二轮检查,在这里的实现方式是*再次运行该工具* —— 下一次运行的 recon 会读取先前运行的发现,并在生成队列时参考它们。 ## 许可证 AGPL-3.0-or-later。请参阅 [`LICENSE.txt`](LICENSE.txt)。
标签:DLL 劫持, Python, Python安全, 大语言模型, 无后门, 网络安全研究, 逆向工具