vinsoc-cyber/VulnHunterX

GitHub: vinsoc-cyber/VulnHunterX

一个将 SAST 静态分析结果通过多轮 LLM 引导式提问进行误报过滤和漏洞验证的 Python 框架。

Stars: 6 | Forks: 3

# VulnHunterX **SAST (CodeQL, Semgrep, OpenGrep) + fuzzing + LLM 漏洞狩猎与验证** 一个 Python 框架,将静态分析与多轮 LLM 验证相结合,以抑制 SAST 发现中的误报,实现了 *Vulnhalla* 方法的引导式提问与证据锚定分类。 ![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg) ![License: MIT](https://img.shields.io/badge/license-MIT-green.svg) ![SAST](https://img.shields.io/badge/SAST-CodeQL%20%7C%20Semgrep%20%7C%20OpenGrep-orange.svg) ## 目录 - [概述](#overview) - [快速开始](#quick-start) - [流水线阶段](#pipeline-stages) - [CLI 参考](#cli-reference) - [Python API](#python-api) - [规则与覆盖范围](#rules--coverage) - [配置](#configuration) - [项目结构](#project-structure) - [开发](#development) - [基准测试](#benchmark) - [参考文献](#references) ## 概述 SAST 引擎有意进行过度近似——它们会标记每一个*可能*存在漏洞的程序点。在生产环境中运行它们的主要成本不在于分析时间,而在于人工分类。VulnHunterX 自动化了分类过程,方法是将每个 SARIF 发现提交给 LLM,LLM 必须回答特定于规则的证据锚定检查清单,在需要时请求额外的代码上下文(多轮),并输出带有置信度分数的结构化裁决。 ``` Source ──> Static Analysis ──> SARIF Findings ──> LLM Verification ──> Verdicts (prepare) (CodeQL/Semgrep/ (rule, file, (guided questions, (TP/FP/NMD + OpenGrep) line, severity) multi-turn context) confidence) ``` **Vulnhalla** 方法迫使 LLM: - 在做出裁决*之前*,回答特定于规则的引导式问题, - 通过固定的上下文词汇表,按需请求调用者、结构体、全局变量、释放点等, - 进行多轮推理,而不是对单个代码片段进行模式匹配。 ### 核心特性 | 特性 | 描述 | |---|---| | **语言** | C, C++, Python, JavaScript, PHP, Java, Go | | **SAST 引擎** | CodeQL, Semgrep, OpenGrep (`--tool codeql\|semgrep\|opengrep\|both\|all`) | | **安全规则配置** | `standard` → `extended` → `maximum` → `extended-registry` → `full` (见 [config/RULES.md](config/RULES.md)) | | **引导式问题** | 跨 6 个每种语言专属题库共 316 个规则特定模板,外加 1 个通用题库 | | **LLM 提供商** | OpenAI, Anthropic, Ollama (通过 [LiteLLM](https://github.com/BerriAI/litellm)) | | **多轮验证** | 动态上下文扩展(调用者、结构体、全局变量、宏、释放点) | | **输入** | Git URL、本地目录或批量列表 (`repos.yaml`) | | **报告** | Markdown,英文/越南文,执行摘要 + 每个发现的详细信息 | | **Fuzz 确认** | libFuzzer / Atheris / Jazzer / Jazzer.js / php-fuzzer harness 生成 + 崩溃分类 | | **基准测试** | 跨 6 个真实数据集的精确率/召回率 (见 [benchmarks/README.md](benchmarks/README.md)) | ## 快速开始 ### 前置条件 - Python 3.12+ - [CodeQL CLI 2.15+](https://codeql.github.com/docs/codeql-cli/getting-started-with-the-codeql-cli/) - [Semgrep](https://semgrep.dev/docs/getting-started/) 和/或 [OpenGrep](https://github.com/opengrep/opengrep#installation) — 可选 - 一个 LLM 提供商:OpenAI、Anthropic 或本地 Ollama ### 安装 ``` git clone https://github.com/vinsoc-cyber/VulnHunterX.git && cd VulnHunterX python3.12 -m venv .venv && source .venv/bin/activate pip install -e . cp env.example .env # add OPENAI_API_KEY / ANTHROPIC_API_KEY / OLLAMA_API_BASE vuln-hunter-x check-env # verify toolchain ``` ### 首次运行 最快的途径是使用 [examples/](examples/) 下针对特定语言的示例脚本之一,这些脚本会克隆一个真实目标、一个易受攻击的目标,并针对两者运行完整流水线,从而使 FP(误报)与 TP(真阳性)的对比一目了然: ``` python examples/pipeline_python.py # 通用 flags: --dry-run、--skip-clone、--api ;C/C++ 脚本也支持 --fuzz ``` | 脚本 | 语言 | 真实项目 | 易受攻击项目 | |---|---|---|---| | `pipeline_python.py` | Python | pyyaml | dvpwa | | `pipeline_javascript.py` | JavaScript | minimist | nodegoat | | `pipeline_c.py` | C | c-ares | dvcp | | `pipeline_cpp.py` | C++ | re2 | insecure-coding-examples | | `pipeline_java.py` | Java | commons-collections | webgoat | | `pipeline_php.py` | PHP | monolog | dvwa | | `pipeline_go.py` | Go | gin | govwa | ### 或直接运行各阶段 ``` vuln-hunter-x prepare --repo pyyaml vuln-hunter-x analyze --repo pyyaml --profile extended vuln-hunter-x verify --repo pyyaml --limit 5 vuln-hunter-x report --repo pyyaml --lang python ``` ### 添加您自己的仓库 ``` # 从 URL 执行 Single-shot vuln-hunter-x prepare --url https://github.com/org/app.git --lang python # 现有 checkout vuln-hunter-x prepare --local-path /path/to/app --lang python --name app # 编译型语言需要 build 命令 vuln-hunter-x prepare --url https://github.com/org/lib.git --lang c --build-command "make" ``` 或者将其列在 [config/repos.yaml](config/repos.yaml) 的 `repos:` 下,并运行 `vuln-hunter-x prepare --repo `。 ### 故障排除 | 症状 | 解决方法 | |---|---| | `CodeQL CLI not found` | 添加到 `PATH` 或在 `.env` 中设置 `CODEQL_PATH` | | `Semgrep CLI not found` | 在 `.env` 中设置 `SEMGREP_PATH` | | `OpenAI API key not configured` | 将 `OPENAI_API_KEY=sk-...` 添加到 `.env` | | `could not resolve module cpp` | `codeql pack install config/queries/tools/cpp` | | `Database is already finalized` | 正常现象 — 分析会自动继续 | ## 流水线阶段 | # | 命令 | 输入 | 输出 | |---|---|---|---| | 1 | `prepare` (别名 `clone`) | URL / 本地路径 / `repos.yaml` | 源代码 + CodeQL DB + 上下文 CSVs | | 2 | `analyze` | CodeQL DB 和/或源码树 | SARIF 发现结果 | | 3 | `verify` | SARIF + 上下文 CSVs | JSON 裁决 + 推理 | | 4 | `report` | 验证结果 | Markdown 报告 (英文/越南文) | | 5 | `build-sanitized` | 已验证的 C/C++ 发现 | ASan/UBSan 构建清单 | | 6 | `extract-fuzz-context` | C/C++ 源码 | 用于 harness 生成的函数签名 | | 7 | `generate-fuzz-drivers` | Fuzz 上下文 + 净化构建 | libFuzzer / Atheris / Jazzer harness | | 8 | `fuzz-run` | 编译好的 harness | 崩溃文件 + 分类结果 | | 目标 | 必需阶段 | 可选 | |---|---|---| | 仅静态分析 | 1, 2 | — | | LLM 验证 | 1, 2, 3 | 4 (`report`) | | Fuzz 确认 | 1, 2, 3, 5, 6, 7, 8 | 4 (`report`) | 阶段 2–3 接受 `--local-path` 以直接操作任意目录。 ## CLI 参考 ### `check-env` ``` vuln-hunter-x check-env ``` 验证 CodeQL CLI、Semgrep/OpenGrep 以及 LLM 提供商密钥。 ### `prepare` *(别名: `clone`)* 克隆仓库,创建 CodeQL 数据库,并提取上下文 CSVs(函数、调用者、结构体、全局变量、宏、类)。 ``` vuln-hunter-x prepare # batch from repos.yaml vuln-hunter-x prepare --url https://github.com/org/repo.git --lang go vuln-hunter-x prepare --local-path /path/to/repo --lang python vuln-hunter-x prepare --skip-clone --skip-db --force --repo libucl # re-extract context only ``` | 选项 | 描述 | 默认值 | |---|---|---| | `--config PATH` | `repos.yaml` 的路径 | — | | `--url URL` | 要克隆的 Git URL | — | | `--local-path PATH` | 现有的本地目录 | — | | `--name NAME` | 仓库名称(如省略则自动推导) | — | | `--lang LANG` | 语言 — 使用 `--url` 或 `--local-path` 时必需 | — | | `--build-command CMD` | 编译型语言的构建命令 | — | | `--repo NAME` | 过滤为一个仓库(配置模式) | All | | `--skip-clone` / `--skip-db` / `--skip-context` | 跳过各阶段 | false | | `--backend {auto,codeql,treesitter}` | 上下文提取后端 | `auto` | | `--ask-llm` | 如果构建失败,向 LLM 寻求帮助 | false | | `-f, --force` | 强制重新提取上下文 CSVs | false | | `--dry-run` | 预览操作 | false | #### 上下文提取后端 (`--backend`) 上下文 CSVs(函数、调用者、结构体/类、全局变量、宏)为多轮 LLM 验证提供数据。有两个后端可以生成它们: | 后端 | 何时使用 | 说明 | |---|---|---| | `auto` *(默认)* | 大多数工作流 | 在构建了数据库的地方使用 CodeQL;在数据库构建失败的仓库中以 tree-sitter 作为后备 | | `codeql` | 最高精度 | 需要有效的 CodeQL 数据库。语义级别的提取;增加被内存安全引导式问题使用的 C/C++ 特定上下文 (`free_sites`, `destructors`, `field_writes`) | | `treesitter` | 无 CodeQL DB,快速迭代 | 语法提取 — 快速,无需构建数据库。涵盖 C、C++、Python、JavaScript、Java、PHP、Go;跳过上面列出的 C/C++ 特定上下文类型 | Tree-sitter 语法 (`tree-sitter-c/cpp/python/javascript/java/php/go`,固定为 `>=0.23,<1.0`) 随标准的 `pip install -e .` 一起安装 — 无需额外设置。两个后端输出相同的 CSV 布局,因此无论使用哪个后端,下游阶段(`analyze`, `verify`, `report`)的工作方式都是相同的。`vuln-hunter-x check-env` 会与 CodeQL 一同验证 tree-sitter 的可用性。 ### `analyze` 针对准备好的仓库或本地路径运行 CodeQL、Semgrep 和/或 OpenGrep。 ``` vuln-hunter-x analyze --repo libucl vuln-hunter-x analyze --tool all --repo c-ares --profile full vuln-hunter-x analyze --tool semgrep --local-path /path/to/project --lang python --profile extended ``` | 选项 | 描述 | 默认值 | |---|---|---| | `--tool {codeql,semgrep,opengrep,both,all}` | 分析器 | `codeql` | | `--profile {standard,extended,maximum,extended-registry,full}` | 规则配置 (见 [config/RULES.md](config/RULES.md)) | `standard` | | `--category CAT` | 按安全类别过滤 (可重复) | All | | `--local-path PATH` | 分析一个本地目录 | — | | `--name NAME` | 仓库名称 | 自动推导 | | `--semgrep-config CFG` / `--opengrep-config CFG` | 覆盖规则包 | 来自配置 | | `--codeql-suite SUITE` | 覆盖 CodeQL suite | 来自配置 | | `--repo NAME` / `--lang LANG` | 过滤器 | All | | `-j, --jobs N` | 并行 CodeQL 分析 | 2 | | `--json` | 同时输出 JSON 格式的发现结果 | false | | `-f, --force` | 即使 SARIF 存在也重新运行 | false | | `--dry-run` / `-v` | 预览 / 详细输出 | false | ### `verify` 使用多轮 LLM 推理验证 SARIF 发现结果。 ``` vuln-hunter-x verify --repo libucl vuln-hunter-x verify --repo c-ares --lang c --category memory-safety vuln-hunter-x verify --provider ollama --model ollama/llama3.2 --repo libucl vuln-hunter-x verify --local-path /path/to/project --lang python --limit 20 ``` | 选项 | 描述 | 默认值 | |---|---|---| | `--config PATH` | 配置文件 | `config/confirm_findings.yaml` | | `--local-path PATH` | 验证本地目录的发现结果 | — | | `--name NAME` | 仓库名称 | 自动推导 | | `--repo NAME` / `--lang LANG` | 过滤器 | All | | `--sarif PATH` | 处理特定的 SARIF 文件 | — | | `--provider {openai,anthropic,ollama}` | LLM 提供商 | 来自配置 | | `--model NAME` | 模型名称 | 来自配置 | | `--temperature F` / `--max-tokens N` | LLM 调优 | 来自配置 | | `--max-iterations N` | 每个发现结果的最大对话轮数 | 3 | | `-j, --jobs N` | 并发验证的发现结果数量 (1 = 顺序执行) | 4 | | `--limit N` | 最大处理发现结果数量 | 无限制 | | `--category CAT` | 按类别过滤 (可重复,与 `analyze` 词汇表) | All | | `--include-tests` | 包括 `test/`, `tests/` 下的发现结果 | false | | `-v` / `-q` | 详细输出 / 静默输出 | normal | | `--log-file PATH` | 保存 LLM 对话日志 | — | | `--dry-run` | 预览发现结果 | false | ### `report` 从验证结果生成 Markdown 报告。`verify` 命令已经写入了 `report.md` 和 `report_vi.md`;使用此命令可重新生成或更改输出路径。 ``` vuln-hunter-x report --repo c-ares --lang c vuln-hunter-x report --results-dir output/c/c-ares/verification_results vuln-hunter-x report --repo libucl -o my-report.md --lang-report en ``` | 选项 | 描述 | 默认值 | |---|---|---| | `--results-dir PATH` | 指向 `verification_results/` 目录的路径 | 自动发现 | | `--repo NAME` / `--lang LANG` | 按仓库和语言自动发现 | — | | `-o, --output PATH` | 输出路径 | 结果目录中的 `report.md` | | `--lang-report {en,vi,all}` | 报告语言 | `all` | 报告部分:执行摘要 · 发现结果概览(裁决前/后) · 严重程度细分 · CWE 分布 · 每个发现的详细信息(裁决、置信度、推理、数据流)。 ### Fuzz 阶段 (仅限 C/C++) ``` vuln-hunter-x build-sanitized --repo libucl vuln-hunter-x extract-fuzz-context --repo libucl vuln-hunter-x generate-fuzz-drivers --repo libucl --build --llm-fix vuln-hunter-x fuzz-run --repo libucl --triage ``` 使用 `--help` 运行任何子命令以获取完整选项。 ### `info` ``` vuln-hunter-x info ``` 打印已解析的配置 — 提供商、模型、路径。 ## Python API ``` from pathlib import Path from vuln_hunter_x import VerificationEngine from vuln_hunter_x.reporting.markdown import MarkdownReportGenerator engine = VerificationEngine.from_config("config/confirm_findings.yaml") result = engine.verify_sarif("output/c/libucl/libucl.sarif", lang="c", repo_name="libucl") for verdict in result.verdicts: print(f"{verdict.finding.rule_id}: {verdict.verdict} ({verdict.confidence})") engine.save_results(result) MarkdownReportGenerator().generate( result, Path("output/c/libucl/verification_results/report.md") ) ``` ## 规则与覆盖范围 [config/RULES.md](config/RULES.md) 是权威清单 — 每个配置、每个自定义 CodeQL 查询、每个自定义 Semgrep 规则,以及 CWE 标签和严重性级别。快速摘要: | 指标 | 数量 | |---|---| | 规则配置 | 5 (`standard` → `full`) | | 安全类别 | 12 | | 路由映射中的 CWE 条目 | 103 | | 自定义 CodeQL 查询 | 6 (5 个 C/C++, 1 个 Go) | | 自定义 Semgrep 规则 | 14 (Python 4, JS/TS 3, Go 3, PHP 4) | | 内置 CodeQL 套件 | `security-extended` (~200), `security-and-quality` (~400) | | 内置 Semgrep 通用包 | 8 | | 内置 Semgrep 特定语言包 | 10 (django, flask, nodejs, gosec, …) | | 引导式问题模板 | 跨 6 个每种语言专属题库共 316 个,外加 1 个通用题库 | 从 `--profile standard` 到 `--profile full` 的覆盖范围增长约为每次扫描增加 **5×–10×** 的规则数量。特定语言的注册表包(`p/django`, `p/gosec`, …)仅应用于匹配的仓库,因此不会污染跨语言扫描。 要添加自定义规则: - **CodeQL** — 将 `.ql` 放入 `config/codeql-custom//src/` 中,使 `@id /` 与引导式问题的键相匹配。 - **Semgrep** — 将规则追加到 `config/semgrep-custom/.yaml` 中,带有 `metadata.cwe: ["CWE-NNN"]`,以便基于 CWE 的路由生效。 两者均通过 `--profile full` 激活。运行 `python scripts/audit_rule_coverage.py --fail-on-gaps` 以验证配置关联。 ## 配置 优先级:**CLI 参数 > 环境变量 > 配置文件 > 默认值**。 ### 环境变量 (`.env`) | 变量 | 描述 | |---|---| | `OPENAI_API_KEY` | OpenAI API 密钥 | | `ANTHROPIC_API_KEY` | Anthropic API 密钥 | | `OLLAMA_API_BASE` | Ollama 服务器 URL | | `LLM_PROVIDER` / `LLM_MODEL` | 覆盖默认提供商 / 模型 | | `CODEQL_PATH` / `SEMGREP_PATH` / `OPENGREP_PATH` | 工具路径(如果不在 `PATH` 中) | ### LLM / 验证设置 (`config/confirm_findings.yaml`) ``` provider: openai # openai | anthropic | ollama model: gpt-4o temperature: 0.2 max_tokens: 1500 max_iterations: 3 # conversation rounds per finding ``` ### 仓库列表 (`config/repos.yaml`) ``` repos: - name: pyyaml url: https://github.com/yaml/pyyaml.git language: python - name: libucl url: https://github.com/vstakhov/libucl.git language: c build_command: "mkdir -p build && cd build && cmake .. && make" ``` | 字段 | 描述 | |---|---| | `name` | 用于输出路径的短标识符 | | `url` | Git 克隆 URL | | `language` | `c` · `cpp` · `python` · `javascript` · `php` · `java` · `go` | | `build_command` | C/C++ 必需;解释型语言请省略 | ### 引导式问题 (`config/prompts/`) 特定于规则的问题库,迫使 LLM 一步步进行推理。 | 文件 | 语言 | 规则集 | |---|---|---| | `cpp_questions.yaml` | C/C++ | 59 | | `python_questions.yaml` | Python | 56 | | `javascript_questions.yaml` | JavaScript / TypeScript | 51 | | `go_questions.yaml` | Go | 50 | | `java_questions.yaml` | Java | 50 | | `php_questions.yaml` | PHP | 50 | | `default_questions.yaml` | 通用后备 | 1 | 验证器分三层匹配每个 SARIF `ruleId` — 精确匹配 → 前缀/规范化匹配 → CWE 映射 — 仅在没有命中时才回退到 `default_questions.yaml`。参见 [config/RULES.md § 7](config/RULES.md#7-guided-question-routing)。 ## 项目结构 ``` VulnHunterX/ ├── src/vuln_hunter_x/ │ ├── cli/ # CLI commands │ ├── codeql/ # Database creation, analysis, context extraction │ ├── context/ # Heuristic + tree-sitter context extraction │ ├── core/ # Types, config, constants │ ├── dyntest/ # Language backends for fuzz stages 5–8 │ ├── fuzz/ # C/C++ fuzz shims │ ├── llm/ # LLM client (LiteLLM) and prompt construction │ ├── opengrep/ # OpenGrep integration │ ├── questions/ # Guided-question loader │ ├── reporting/ # Markdown report generation │ ├── sarif/ # SARIF parsing │ ├── semgrep/ # Semgrep integration │ └── verification/ # Multi-turn verification engine ├── config/ │ ├── RULES.md # Authoritative rule inventory │ ├── rule_categories.yaml # Profiles, categories, CWE map │ ├── codeql-custom/ # Custom CodeQL queries (full profile) │ ├── semgrep-custom/ # Custom Semgrep rules (full profile) │ ├── prompts/ # Guided questions + system prompt │ ├── queries/ # CodeQL context queries (per language) │ ├── confirm_findings.yaml # LLM and verification settings │ └── repos.yaml # Repository definitions ├── benchmarks/ # Evaluation framework — see benchmarks/README.md ├── examples/ # Per-language pipeline scripts ├── scripts/ # audit_rule_coverage.py, etc. ├── tests/ └── output/ └── // ├── database/ # CodeQL database ├── *.sarif # SARIF results ├── context/ # Extracted CSVs ├── verification_results/ # Verdict JSON + report.md ├── sanitized_build/ # (C/C++) sanitizer build ├── fuzz_targets/ # (C/C++) harnesses └── fuzz_results/ # (C/C++) crashes ``` ## 开发 ``` pip install -e ".[dev]" pytest tests/ ruff check src/ ruff format src/ mypy src/ ``` 参见 [CONTRIBUTING.md](CONTRIBUTING.md) 和 [CHANGELOG.md](CHANGELOG.md)。 ## 基准测试 VulnHunterX 附带了一个独立的基准测试框架,在六个真实数据集(SecLLMHolmes, Juliet C/C++, DiverseVul, OWASP BenchmarkJava, OWASP BenchmarkPython, RealVuln)上将完整流水线与 `raw-sast` 和消融基线进行比较。 ``` python benchmarks/scripts/run_benchmark.py \ --dataset secllmholmes --approach all \ --model gpt-4o-mini --limit 50 ``` 完整文档 — 数据集、每个数据集的操作手册、指标、恢复语义 — 位于 [benchmarks/README.md](benchmarks/README.md)。文献综述和设计决策的理论依据位于 [benchmarks/RESEARCH.md](benchmarks/RESEARCH.md)。 ## 许可证 MIT — 详见 [LICENSE](LICENSE)。 ## 参考文献 - [Vulnhalla — CyberArk](https://www.cyberark.com/resources/threat-research-blog/vulnhalla-picking-the-true-vulnerabilities-from-the-codeql-haystack) — 原始方法论 - [CodeQL 文档](https://codeql.github.com/docs/) - [Semgrep 文档](https://semgrep.dev/docs/) - [SARIF 规范](https://sarifweb.azurewebsites.net/)
标签:AI风险缓解, CISA项目, CodeQL, DevSecOps, DLL 劫持, EDR, Fuzzing, IPv6支持, LLM, MIT开源协议, OpenGrep, Python, SARIF, SAST, Semgrep, Unmanaged PE, VulnHunterX, WordPress安全扫描, 上游代理, 代码分析, 代码安全, 凭证管理, 多轮对话, 大语言模型, 安全合规, 安全评估工具, 无后门, 漏洞枚举, 盲注攻击, 网络代理, 脆弱性评估, 自动化漏洞验证, 误报过滤, 逆向工具, 静态应用安全测试