RemleyGHooker/vulnscan

GitHub: RemleyGHooker/vulnscan

LLM 辅助的漏洞扫描与对抗性评估研究框架,用于量化和研究大语言模型在安全分析中的鲁棒性、失败模式及类依赖脆弱性。

Stars: 0 | Forks: 0

# vulnscan LLM 辅助的漏洞扫描与对抗性评估框架,用于研究 LLM 安全分析中的鲁棒性、失败模式和类依赖的脆弱性。 ## 问题所在(简述) 现代代码库规模庞大且迭代迅速,仅靠纯人工安全审查已无法满足需求,因此团队越来越多地使用 LLM 来协助查找漏洞。核心问题在于可靠性:一个 LLM 可能在某种提示词或代码视角下表现优异,但当上下文被精简、摘要或进行对抗性构造时,却可能忽略掉完全相同的 bug。 ## 本工作如何解决此问题 `vulnscan` 将这一可靠性问题转化为可度量的研究工作流。它不再仅仅关注“模型是否发现了 bug?”,而是在各种上下文条件和攻击性扰动下运行受控实验,记录机器可读的产物,并按类别比较检测行为。 ## 基础与扩展 本代码库基于 4 月 9 日的预印本论文《语义悬崖:上下文摘要下 LLM 漏洞检测的类依赖脆弱性》(Hooker, 2026) 构建,并将其从单一核心实验扩展为更广泛的评估套件。4 月 9 日的框架确立了上下文敏感性假设;本代码库则通过对抗性抑制测试、扫描器投毒试验、多轮自我审计检查、跨语言移植以及可复现的聚合/绘图工具,进一步扩展了该项工作。 ## 核心研究贡献 - 统一的扫描/评估管道,同时支持实际的代码仓库扫描和受控的对抗性实验。 - 类条件上下文隔离协议,对比了完整文件、隔离窗口、模板摘要和 LLM 安全摘要条件。 - 成对的抑制/投毒实验,用于分离出类似提示注入的注释是否会显著改变检测结果。 - 用于保证可复现性的结构化产物(`manifest` JSON 文件、聚合 CSV/JSON 输出以及图表生成脚本)。 ## 研究发现概览 - **语义悬崖:** 在隔离/模板上下文中,缓冲区溢出的检测率从 **100% 降至 17%**,随后在使用 LLM 安全摘要上下文时恢复至 **100%**。 - **类条件鲁棒性:** 在同一次运行中,SQL 注入在完整、隔离、模板和 LLM 摘要条件下的检测率始终保持 **100%**。 - **内存泄漏模式:** 内存泄漏的检测率在 完整 -> 隔离/模板 -> LLM 摘要 过程中呈现 **100% -> 67% -> 100%** 的波动。 - **该设定下的注释攻击:** 注释抑制效果平直(**0.96 -> 0.96**),扫描器投毒效果也呈平直状态(**0.36 -> 0.36**)。 ## 持续进展 - 从探索性运行扩展到大样本评估(`N >= 200`),以获得更窄的置信区间。 - 扩展跨模型和跨语言的比较,同时保持 manifest 和提示词的可复现性。 - 通过更明确的标签标准和更强的人工审核工作流来提升评估质量。 - 将论文相关产物转换为可用于公开发布的图表和表格。 ## 演示 **丰富的表格输出**(扫描后在终端中看到的内容):

vulnscan CLI: Rich vulnerability table

*CLI 的风格化截图。要获取**真实**的录制,请针对故意包含漏洞的应用(如 **[vulnado](https://github.com/ScaleSec/vulnado)** (Java) 或 **[DVWA](https://github.com/digininja/DVWA)** (PHP))运行扫描,然后录制终端。* ## 研究图表 ### 研究设计概览 ``` flowchart TD RQ[Research questions] --> E1[Context isolation] RQ --> E2[Comment suppression] RQ --> E3[Scanner poison] RQ --> E4[Self-knowledge / transplant / sleeper] E1 --> M[Unified metrics + manifests] E2 --> M E3 --> M E4 --> M M --> A[Aggregate JSON + CSV] A --> P[Paper tables + figures] ``` ### 语义悬崖直觉 ``` flowchart LR F[Full context] -->|Summarize/trim context| I[Isolated or template context] I -->|Class-dependent drop| C[Detection cliff] C -->|Add LLM security summary| R[Recovery for fragile classes] ``` ## 论文(预印本) **语义悬崖:上下文摘要下 LLM 漏洞检测的类依赖脆弱性** - **LaTeX 源码:** [`paper.tex`](paper.tex) - **PDF:** 在发布构建版本时(如通过 GitHub Release、arXiv、OpenReview Archive 等),请将 [`paper.pdf`](paper.pdf) 添加到仓库根目录;在此之前,请在本地运行 `pdflatex paper.tex`(需要安装 TeX 发行版)。 ## 主要研究发现 本代码仓库包含用于生成 [`paper.tex`](paper.tex) 中总结的结果的管道。主要的定量运行使用了每个实验套件 **\(N = 50\)** 的样本量(聚合的 Wilson 置信区间见 `runs/aggregate_50_all_llm.json`);扩展到每个套件 **\(N \geq 200\)** 可以进一步缩小区间,以满足期刊提交要求。 ### 新颖的实证发现 - **语义悬崖(类依赖的崩溃):** 在上下文隔离条件下,**缓冲区溢出**的检测率在隔离/模板摘要下从 **100% 降至 17%**,随后在带有 LLM 安全重点摘要前缀的情况下**恢复至 100%**。 - **类条件鲁棒性:** 在同一次运行中,**SQL 注入**在完整、隔离、模板和 LLM 摘要条件下的检测率始终保持 **100%**。 - **伴随恢复的部分脆弱性:** **内存泄漏**的检测率波动为 **100% -> 67%**(隔离/模板)-> **100%**(LLM 摘要)。 - **压缩质量比压缩本身更重要:** 聚合的上下文正确率分别为完整文件 **0.96**、隔离 **0.84**、模板 **0.84** 以及 LLM 摘要 **0.98**,这表明语义感知的摘要能够超越原始完整上下文的基线表现。 - **提示式注释攻击在本设定中无效:** 注释抑制效果平直(**0.96 -> 0.96**),扫描器投毒的成对条件在报告的聚合运行中也呈平直状态(**0.36 -> 0.36**)。 相关产物:`runs/ctx_50_llm/context_isolation_manifest.json`,`runs/aggregate_50_all_llm.json`,`runs/aggregate_50_all_llm.csv`,图表 `runs/results_semantic_cliff_llm.png`。 ## 架构 ``` flowchart LR subgraph scan["Scan mode"] A[GitHub URL or local repo] --> B[Discover .py .js .ts .c …] B --> C[Chunk files + line prefixes] C --> D[Claude: JSON findings] D --> E[Normalize + filter by severity] E --> F[Rich table + vulnscan_report.json] end ``` ``` flowchart LR subgraph research["Research mode"] G[Generator prompt + tier] --> H[Synthetic vulnerable file] H --> I[Same chunk → LLM scan pipeline] I --> J[Match vs intended class + extras] J --> K[adversarial_report.json + manifest] end ``` 提示词位于 **`prompts.py`** 中(用于扫描的 `VULN_SCAN_*`,用于对抗样本的 **`ADV_SYNTH_*`**)。 ## 示例 JSON (`vulnscan_report.json`) ``` { "version": 1, "findings": [ { "file_path": "src/LoginServlet.java", "line_number": 42, "vulnerability_type": "sql_injection", "severity": "high", "description": "User-controlled input concatenated into a SQL string before execution.", "suggested_fix": "Use parameterized queries / PreparedStatement exclusively." } ], "summary": { "total": 1, "by_severity": { "critical": 0, "high": 1, "medium": 0, "low": 0 } } } ``` **对抗性运行** (`-o adversarial_report.json`):每个条目包含 `intended_class`、`obfuscation_tier`、`detected_intended`、`findings`、`extra_findings` 以及聚合的 `summary.recall_on_intended_class`。 ## 研究模式:对抗性样本生成 本代码库不仅是一个“带有 API 的 linter”。**对抗性**路径使用结构化提示词(参见 **`prompts.py`** 中的 `ADV_SYNTH_SYSTEM` / `ADV_SYNTH_USER_TEMPLATE`),使 LLM 生成包含以下特征的**合成漏洞代码**: - 声明的**漏洞类别**(如 `sql_injection`,`prompt_injection`), - **混淆层级**(`obvious` → `subtle` → `disguised`), 然后,**`vulnscan` 使用与扫描真实代码仓库相同的管道扫描该文件**。您将获得机器可读的标签,以及**扫描器是否报告了预期的漏洞类别**——这对于召回率曲线、多模型比较和人工审核误报非常有用。*此处的召回率是启发式的(基于标签匹配);只有在具备冻结的评分标准和人工标签的情况下,才应将发布的数字视为严谨的数据。* ``` python3 main.py adversarial --samples 8 --language python -v -o adversarial_report.json ``` 参数标志:`--vulnerability-class`,`--tier`,`--generator-model` / `--scanner-model`(分割模型用于分歧研究)。请参阅 **`python3 main.py adversarial --help`**。 **论文风格的层级表格:** 生成 *每个混淆层级 N 个样本*(例如,50 × obvious / subtle / disguised = 150 次生成)。报告中包含 `summary.detection_rate_by_tier`,可直接作为结果表格使用。 ``` python3 main.py adversarial --per-tier 50 --language python -o tier_eval.json -v ``` ## 多模型比较 (Claude + Groq) 相同的代码块会并行发送至 **Anthropic** 和 **Groq**;JSON 记录了 `claude_findings`、`groq_findings`、`claude_only`、`groq_only` 以及贪婪匹配的 `agreed_pairs`(类型 + 附近的代码行)。需要 **`GROQ_API_KEY`**。 ``` export GROQ_API_KEY="…" python3 main.py scan ./vulnado --compare -v -o compare.json ``` `--parallel-workers` 适用于正常扫描模式下的**文件级**并发;比较模式会将文件级工作线程数上限设得更低(因为每个文件在每个代码块上已经运行了两个模型)。 ## 新颖 / 高影响力的研究模式 | 命令 | 测试内容 | |---------|----------------| | `self-knowledge` | 同一模型:**多轮**(它编写了代码,然后审核该对话记录)与对同一文件**全新的独立扫描**对比 —— *自我认知盲点*。 | | `transplant` | **C + Python 配对**保持同一缺陷类别;扫描器分别对两者进行检测 —— *跨语言泛化能力*。 | | `scanner-poison` | 基线漏洞与添加了**明确指示审查者**(输出为空 / 预审计)注释的同一漏洞对比 —— *源代码中激进的提示注入*。 | | `sleeper` | 第 N 行**之后**的漏洞 + 仅扫描**前缀**与**完整文件**对比;对完整文件**重复相同的扫描**以获取计数的方差 —— *隐藏分支 + 随机稳定性*。 | 示例: ``` python3 main.py self-knowledge --samples 40 -v -o sk.json python3 main.py transplant --samples 25 -v -o tp.json python3 main.py scanner-poison --samples 30 --language python -v -o poison.json python3 main.py sleeper --samples 20 --surface-lines 45 --repeat-scans 8 -o sleeper.json ``` 每种模式都会写入一个 JSON 报告、一个工作区 manifest,并打印汇总表(`print_manifest_kv`)。**成本随样本量而增加**(每次设计对应的 API 调用)。 ## 注释抑制实验(源代码中的提示注入) **研究问题:** *对抗性构造的源代码注释是否能抑制基于 LLM 的漏洞检测?* `comment-suppress` 命令要求生成器生成一个**成对**的程序:(A) 没有误导性注释的漏洞基线,以及 (B) 带有旨在说服审查者该漏洞点是安全的注释的**相同漏洞**。随后,**同一个**扫描器模型分析这两个文件;报告包含基线与处理组的检测率、**抑制事件**(基线检出 → 处理组漏报)以及 **P(suppress | baseline hit)**。 ``` python3 main.py comment-suppress --samples 100 --language python -v -o suppression_report.json ``` 输出:`-o` JSON,位于 `--outdir` 下的 `comment_suppression_manifest.json`,以及成对的源文件(`*_baseline.py`,`*_suppressed.py`)。这是一项实证探测——在宣称达到可发布级别的效应量之前,请使用大样本 **N**,记录模型 ID 和日期,并加入人工审核。 ## CVE 风格的基准真相测试 `data/cve_ground_truth.json` 列出了公开的**故意包含漏洞**的代码仓库及粗略的 `expected_families`。该命令将浅克隆每个仓库,最多扫描 `--max-files-per-repo`,并报告是否有任何发现与预期相符(**基于启发式**;在宣称复现了 CVE 之前,请进一步严格确定标签)。 ``` python3 main.py cvebench --manifest data/cve_ground_truth.json -o cvebench.json --max-files-per-repo 25 ``` ## 其他扫描标志 | 标志 | 行为 | |------|----------| | `--parallel-workers 8` | 并发扫描多个文件(默认为 4) | | `--diff` | 解析 git 仓库根目录,仅扫描**上一次提交**中修改过的文件 | | `--no-secrets-files` | 跳过 `.env` / 小型 `config.yaml` 风格的候选文件 | | `-v` / `--verbose` | 在扫描时记录每个文件(或合成文件) | ## 安装与运行 ``` cd vulnscan python3 -m venv .venv && source .venv/bin/activate pip install -r requirements.txt # or: pip install -e . export ANTHROPIC_API_KEY="…" ``` **扫描代码仓库**(详细模式:在扫描时打印每个文件): ``` python3 main.py scan /path/to/vulnado -v -o report.json # legacy: python3 main.py /path/to/repo -o report.json ``` **安装 CLI 入口点:** 运行 `pip install -e .`,然后即可在任何目录下运行 **`vulnscan scan …`**。 **Pre-commit:** 参见 `contrib/pre-commit-config.example.yaml`。 **测试**(无需 API): ``` python3 -m unittest discover -s tests -p 'test_*.py' -v ``` ### 批量评估 (`eval_pipeline.py`) 全网格对抗性生成 + 扫描 + 四种注释变体(在**每个**样本后写入 **`eval_results_raw.json`**,然后生成 **`eval_results_summary.json`**)。该模块已在 **`pyproject.toml`** (`eval_pipeline`) 中注册,因此 `pip install -e .` 会包含它。 **成本 / 模型:** 评估管道默认为 **`claude-haiku-4-5-20251001`**(可通过 `--model` 覆盖)。对于合成漏洞代码及扫描,Haiku 通常已足够,并且在相似 token 量下的成本远低于 Sonnet 级别的模型。默认网格为 `×3×3×samples_per_combo`,**`--samples-per-combo` 默认为 1** → 完整运行需 **72** 个样本(若需配对重复,请使用 `2`)。每个样本执行 **phase2 + 4 phase3** 次扫描;**`scan_file` 会对每个代码块调用一次 API**,而不是对每个文件调用一次 —— 因此“样本数 × 5”只是一个**下限**。**`--dry-run`** 会生成代码,并为每条记录写入 **`dry_run_chunk_counts`** / **`dry_run_estimated_scanner_api_calls`**,最后还会提供聚合的提示信息。 **冒烟测试网格(18 个样本):** `data/eval_manifest_smoke_18.json` 将类别限制为跨所有层级和语言的 **sql_injection** 和 **command_injection** —— 在运行完整的 72 样本网格之前,请先运行此网格(可选择结合 `--dry-run`)。 **断点续传:** **`--resume`** 会跳过已存在于 **`eval_results_raw.json`** 中的组合键,因此您可以中断操作并继续,而无需重做已完成的样本。 **局限性:** `misleading_name` 使用了脆弱的启发式方法(查找首个 `def foo(` → `def safe_query(`),不支持类方法、lambda 等;请将其视为探索性使用。 ``` # 18-sample 接线检查 (仅估算 chunk) python3 eval_pipeline.py --manifest data/eval_manifest_smoke_18.json --dry-run # 完整默认网格 (72 samples), 真实扫描 python3 eval_pipeline.py --delay 1.5 # 中断后恢复 python3 eval_pipeline.py --resume --delay 1.5 ``` `--manifest` 接受 `{"combinations":[{"vulnerability_class":"sql_injection","obfuscation_tier":"obvious","language":"python"}]}` 或由这些对象组成的 JSON 数组。 ## 引用 如果您使用了 **vulnscan** 或**语义悬崖**相关实验,请引用(当最终仓库或 DOI 确定后,请更新 `url`): ``` @misc{hooker2026semanticcliff, title = {The Semantic Cliff: Class-Dependent Fragility of LLM Vulnerability Detection under Context Summarization}, author = {Hooker, Remley}, year = {2026}, month = apr, note = {Preprint. Independent researcher.}, url = {https://github.com/remleyhooker/vulnscan} } ``` **APA 格式(纯文本):** Hooker, R. (2026). *The Semantic Cliff: Class-dependent fragility of LLM vulnerability detection under context summarization* [Preprint]. https://github.com/remleyhooker/vulnscan ## 伦理声明 合成的漏洞代码仅供**评估和教育**使用。仅扫描您获得授权测试的系统。LLM 的输出不能替代专业的安全审查。
标签:AI安全, AI鲁棒性, Chat Copilot, CISA项目, CSV, DNS 反向解析, Homebrew安装, JSON, Python, Sysdig, 上下文隔离, 代码安全分析, 反取证, 多轮自检, 安全评估, 对抗性评估, 无后门, 自动化漏洞检测, 语义悬崖, 逆向工具, 鲁棒性测试