rndhouse/vcamper
GitHub: rndhouse/vcamper
一款用于在 Git 提交范围内识别静默安全补丁的概念验证 CLI 工具。
Stars: 2 | Forks: 0
# VCamper
VCamper ("Version Camper") 是一个用于在 Git 提交范围内查找可能静默安全补丁的概念验证 CLI 工具。
公共代码与公共安全通告并不总是一同发布。有些修复以普通提交形式合并,没有 CVE 或明确的安全标签,有些则安静地发布,以便用户在问题广泛传播前升级。但一旦补丁公开,仓库历史中可能已向任何研究变更的人透露了漏洞信息。
VCamper 利用这种不对称性工作。它不是在整个系统中搜索未知漏洞,而是分析更小的近期代码变更面,逐个让代理评估提交候选,并高亮最可能是漏洞修复的提交。
关注更新:[x.com/rndhouse](https://x.com/rndhouse)
## 示例
### curl CVE-2025-0725
curl 在提交 [`76f83f0db23846e254d940ec7fe141010077eb88`](https://github.com/curl/curl/commit/76f83f0db23846e254d940ec7fe141010077eb88) 中修复了 `CVE-2025-0725`,标题为 `content_encoding: drop support for zlib before 1.2.0.4`。该标题看起来像是兼容性维护。修复于 2025 年 1 月 24 日在 curl 的 GitHub 仓库中公开,当时 [PR #16079](https://github.com/curl/curl/pull/16079) 被打开并于当天合并。curl 在 2025 年 2 月 5 日发布了安全公告。这留下了大约 12 天的代码到公告公开窗口。来源:[curl 安全公告](https://curl.se/docs/CVE-2025-0725.html),[curl PR #16079](https://github.com/curl/curl/pull/16079)。
VCamper 独立分析该修复提交,单次端到端运行完成:
```
cargo run -- analyze \
--repo /path/to/curl \
--from 76f83f0db23846e254d940ec7fe141010077eb88 \
--to 76f83f0db23846e254d940ec7fe141010077eb88 \
--provider codex \
--model gpt-5.4 \
--screen-effort medium \
--verify-effort high \
--out /tmp/vcamper-curl-cve-2025-0725
```
在分析结果中,VCamper 以置信度 `0.95` 标记该提交与安全相关,并得出结论:移除的旧 zlib gzip 回退允许远程服务器在内存耗尽前,让 curl 客户端持续缓冲攻击者控制的 gzip 头部字节。该验证器推断旧解析器停留在 `GZIP_UNDERFLOW` 状态,而可选 gzip 头部字段缺少终止的 NUL,导致 curl 在不进行解压的情况下不断重新分配并向 `z->next_in` 追加攻击者提供的字节。最强支持的当前流水线后果是远程客户端内存耗尽型 DoS。
该结果仍仅基于公开修复提交本身定位到正确的漏洞路径,未在分析中使用 CVE 文本。当前流水线对后果类别的判断比 curl 的公开安全公告更保守:curl 将其归类为 `CWE-680`,而 VCamper 止步于一个得到良好支持的远程资源消耗错误。
### wolfSSL CVE-2026-5194
wolfSSL 在提交 [`abce5be989ccd0665e2b9445abb856886975dfd1`](https://github.com/wolfSSL/wolfssl/commit/abce5be989ccd0665e2b9445abb856886975dfd1) 中修复了 [`CVE-2026-5194`](https://app.opencve.io/cve/CVE-2026-5194),来自 [PR #10131](https://github.com/wolfSSL/wolfssl/pull/10131),标题为 `20260403-WC_FIPS_186`。这比 curl 更复杂。该提交混合了 FIPS 186 合规工作、测试更新、签名 OID 检查和摘要长度检查,涉及 `wolfcrypt/src/asn.c`、`wolfcrypt/src/ecc.c`、`src/pk_ec.c`、`src/internal.c` 和 `wolfcrypt/src/pkcs7.c`。
该提交是一个典型例子,说明为何 VCamper 采用分阶段 Codex 传递。单一宽泛提示容易偏离到错误的本地错误故事。分阶段流水线从同一提交中识别出三个不同的已验证发现:
- `ConfirmSignature` 中共享的 ASN.1 `signatureAlgorithm` / 密钥族绑定缺陷
- 直接的前哈希 ECDSA 验证错误(公共包装路径)
- 将算法绑定与共享 ECDSA 摘要策略执行关联的复合签名对象验证理论
复合候选尤为有趣。在最终分阶段运行中,VCamper 确认了一个 `0.90` 的发现,即签名对象验证允许攻击者控制的签名 OID 将 ECDSA 验证导向不匹配或低于策略的摘要。这并非对已发布 CVE 文本的精确复述(CVE 同时强调混合 EdDSA / ML-DSA 启用),但它落在同一修复家族中,并在嘈杂的加密提交中展现出有用的行为:VCamper 保留多个理论、独立验证它们,并恢复共享验证边界,而不是过早地强行选择一个胜出者。
仅一条端到端命令就足以展示当前原型在该提交上的行为:
```
cargo run -- analyze \
--repo /path/to/wolfssl \
--from abce5be989ccd0665e2b9445abb856886975dfd1 \
--to abce5be989ccd0665e2b9445abb856886975dfd1 \
--provider codex \
--model gpt-5.4 \
--screen-effort xhigh \
--verify-effort xhigh \
--inventory-focuses 0,1,3,4,9 \
--out /tmp/vcamper-wolfssl-cve-2026-5194
```
该命令仍使用经过筛选的热点短列表,因为该提交异常嘈杂。示例的重点并非让 VCamper 精确复现 CNA 文本。重点在于它仍能从首次阅读看似合规变更的提交中恢复正确的修复家族和有用的复合签名对象验证理论。这是当前原型在复杂加密提交上的上限:它可以恢复共享信任边界和多个已验证的安全故事,但精确的 CVE 叙述匹配仍依赖于后续阶段更强的混合特性推理。
## 用法
```
cargo run -- analyze \
--repo /path/to/repo \
--from \
--to \
--provider codex \
--model gpt-5.4 \
--screen-effort medium \
--verify-effort high \
--out /tmp/vcamper-run
```
常用标志:
- `--dry-run`:收集 Git 证据并渲染提示,而不调用代理 CLI
- `--model `:为所选提供程序传递明确的模型名称
- `--effort `:同时设置筛选和验证的强度
- `--screen-effort `:设置首轮筛选器强度
- `--verify-effort `:设置第二轮验证器强度
- `--max-commits `:当提交范围超出预期时快速失败
- `--max-patch-bytes `:限制存储在截断提交工件和行内回退提示中的差异字节数
- `--out `:将工件写入特定运行目录
- `--start-at-stage `:从特定分阶段 Codex 边界开始,并重用同一 `--out` 目录中的早期阶段工件
- `--stop-after-stage `:在分阶段 Codex 边界后停止,以便独立检查某一阶段
- `--inventory-focuses `:在保留原始焦点索引的同时,将 Codex 筛选限制到特定的热点焦点短列表
- `--rerun-stages `:清除指定阶段及其下游阶段,然后从同一 `--out` 目录继续
- `--verbose`:打印详细的内部日志和流式提供程序输出
在中断后,使用相同的 `--out` 目录重新运行同一命令可继续执行。VCamper 会复用已完成的提交候选,从第一个未完成的候选重新开始,并继续前进。对于 Codex 运行,VCamper 还会复用同一 `--out` 目录中已完成阶段的工件,因此可以在不重复已完成工作的情况下,分别执行筛选、合成、交互审查、复合合成、到达性检查与最终验证,除非传递 `--rerun-stages`。
默认情况下,VCamper 在终端中抑制提供程序事件输出。默认终端视图仅显示候选进度和提供程序工作时的活动旋转器。
未完成的候选保存在 `wip/` 目录下,位于输出目录内。完成的候选会存储在 `progress.json` 中并从 `wip/` 提升,以便在运行结束后仍可检查提示、提供程序和分析工件。
对于 Codex 运行,VCamper 会保留每个 pass 本地的证据包,并将模型指向文件而非在初始提示中嵌入完整补丁。每个 pass 会生成未截断的 `evidence/patch.diff`、`evidence/changed-files.txt`、`evidence/hotspots.json` 以及变更文件的前后快照。Codex 筛选现在以五个分阶段调用运行,并在每个候选内独立执行最终验证:
- `inventory`:从完整补丁派生加权热点计划,每个热点文件运行一个窄焦点提示,使第一阶段的理论不竞争于同一个宽泛提示
- `synthesis`:合并相关的 inventory 结果,在后续阶段剪枝或排序前形成更强的共享理论
- `interaction review`:检查每个假设是否存在混合特征、共享流程或编译期交互信号,这些是普通到达性审查可能遗漏的
- `composite synthesis`:将保留的交互理论组合成更广泛的混合特征或共享验证最终方案,同时保留更窄的源理论
- `reachability`:对每个 inventory 假设进行独立的利用路径审查,使用紧凑的数据包评估其暴露面,避免过早丢弃依赖交互的理论
- `verify:对每个到达性幸存者进行独立最终验证,并将仍通过验证的候选保留为潜在安全修复
这样可以保持每个提示更狭窄,使阶段进展可检查,避免因提示大小截断而丢失差异上下文,保留交互密集型加密理论(当直接调用路径不完整时),并允许最终验证从单个嘈杂提交中确认多个独立理论,而不是强制它们在单个提示中竞争。可使用 `--stop-after-stage` 仅执行一个分阶段边界以检查 inventory、synthesis、interaction review、composite synthesis 或 reachability;使用 `--start-at-stage` 从后续边界继续;使用 `--inventory-focuses` 仅对热点焦点短列表重新运行后续阶段。
VCamper 还在运行根目录下写入 `progress.json`。它以 `count_pending` 和 `count_complete` 开头,随后列出 `pending` 中的未完成候选和 `complete` 中的已完成候选。未完成的候选现在包含 `active_stage`,因此长 Codex 运行会显示候选处于 inventory、synthesis、interaction、composite synthesis、reachability 或 finalist verification 中的哪一阶段。
分析流程仍报告为 `screen` 然后 `verify`,但 Codex 内部将其扩展为:
- `screen/inventory`:代码优先的聚焦假设库存,隐藏提交信息
- `screen/synthesis`:类别级综合,将相关 inventory 结果合并为更强的共享理论
- `screen/interaction`:对共享验证流程、特性组合和编译期分支的单假设交互审查
- `screen/composite_synthesis`:跨类别综合,在保留的交互假设之上添加更广泛的复合理论
- `screen/reachability`:单假设利用路径审查,使用紧凑的数据包
- `verify`:对到达性幸存者逐一进行最终验证,并在验证后恢复提交信息作为二级上下文
## 要求
- Rust 工具链
- `git`
- 一个代理 CLI:
- `codex`
- `claude`
## 输出
VCamper 要求每个运行都必须提供 `--out`。每个输出目录包含:
- `manifest.json`:选定的仓库、提交范围、CLI 设置以及本次运行使用的库存焦点短列表
- `progress.json`:格式化的待处理和已完成候选列表,包含顶级计数器和每个候选的 `active_stage`
- `wip/candidate-*`:尚未完成的候选中间工件
- `candidate-*/input.json`:已完成候选的收集提交证据工件
- `candidate-*/screen/prompt-input.json`:提供给提供程序提示的代码优先筛选证据
- `candidate-*/screen/prompt.txt`:渲染后的筛选提示
- `candidate-*/screen/evidence/patch.diff`:筛选 pass 的完整未截断补丁
- `candidate-*/screen/evidence/changed-files.txt`:筛选 pass 的变更文件列表
- `candidate-*/screen/evidence/hotspots.json`:从完整补丁派生的加权热点文件和筛选焦点单元
- `candidate-*/screen/evidence/file-snapshots.json`:变更文件的 before/after 快照清单
- `candidate-*/screen/evidence/before/*` 和 `candidate-*/screen/evidence/after/*`:筛选期间可供 Codex 使用的文件快照
- `candidate-*/screen/inventory/cluster-*/prompt-input.json` 和 `prompt.txt`:焦点特定的库存证据和提示
- `candidate-*/screen/inventory/cluster-*/evidence/*`:单个库存焦点的过滤补丁、热点计划和快照
- `candidate-*/screen/inventory/cluster-*/analysis.json`:该焦点的单一主要库存结果
- `candidate-*/screen/inventory/analysis.json`:合并库存结果(综合前)
- `candidate-*/screen/synthesis/category-*/prompt-input.json` 和 `prompt.txt`:类别级综合证据和提示
- `candidate-*/screen/synthesis/category-*/evidence/*`:分组后的补丁子集、热点计划及快照
- `candidate-*/screen/synthesis/category-*/analysis.json`:单一合成判断及任何共享替代理论
- `candidate-*/screen/synthesis/analysis.json`:综合前合并的筛选结果
- `candidate-*/screen/interaction/hypothesis-*/prompt-input.json` 和 `prompt.txt`:单假设交互审查证据和提示
- `candidate-*/screen/interaction/hypothesis-*/evidence/*`:假设本地的补丁子集、热点计划及快照
- `candidate-*/screen/interaction/hypothesis-*/analysis.json`:单一交互审查判断、保留决策及精炼后的发现
- `candidate-*/screen/interaction/analysis.json`:合并交互审查摘要(综合合成前)
- `candidate-*/screen/composite_synthesis/group-*/prompt-input.json` 和 `prompt.txt`:分组后的复合综合证据和提示
- `candidate-*/screen/composite_synthesis/group-*/evidence/*`:分组后的补丁子集、热点计划、源假设上下文及快照
- `candidate-*/screen/composite_synthesis/group-*/analysis.json`:单一复合综合判断及任何附加的发现
- `candidate-*/screen/composite_synthesis/analysis.json`:综合后合并的筛选结果
- `candidate-*/screen/reachability/hypothesis-*/prompt-input.json` 和 `prompt.txt`:单假设到达性审查证据和提示
- `candidate-*/screen/reachability/hypothesis-*/evidence/*`:假设本地的补丁子集、热点计划及快照
- `candidate-*/screen/reachability/hypothesis-*/analysis.json`:单一到达性审查判断及精炼后的发现
- `candidate-*/screen/reachability/analysis.json`:综合到达性过滤后的筛选结果
- `candidate-*/screen/stdout.txt` 和 `candidate-*/screen/stderr.txt`:筛选器提供程序输出
- `candidate-*/screen/analysis.json`:完成筛选后的最终结果(包含分阶段库存、复合综合和到达性)
- `candidate-*/verify/hypothesis-*/prompt-input.json` 和 `prompt.txt`:单最终候选验证证据和提示
- `candidate-*/verify/hypothesis-*/evidence/*`:验证候选本地的补丁子集、热点计划及快照
- `candidate-*/verify/hypothesis-*/analysis.json`:单一最终验证判断及任何已确认发现
- `candidate-*/verify/stdout.txt` 和 `stderr.txt`:验证器提供程序输出
- `candidate-*/verify/results.json`:每个最终候选的合并验证记录
- `candidate-*/verify/analysis.json`:完成验证结果
- `candidate-*/stage-state.json`:候选已完成的最高内部阶段及完整流水线是否结束
- `candidate-*/outcome.json`:跨两个 pass 的最终候选结果
- `report.json`:所有已分析提交候选的合并可疑发现
- `summary.md`:可读的最终摘要
标签:AI代理, Cargo, CVE, Git, Git历史分析, PoC, Rust, 代码变更分析, 代码审查, 可视化界面, 安全补丁, 安全通告, 异步披露, 提交分析, 数字签名, 暴力破解, 漏洞修复, 漏洞披露, 版本分析, 网络安全培训, 网络安全研究, 网络流量审计, 通知系统, 静默补丁