VCamper(“版本露营者”)是一个概念验证的命令行工具,用于在Git提交范围中发现潜在的静默安全补丁。
公开的代码和安全通报并不总是同步发布。有些修复以普通提交的形式合并,没有CVE或明确的安全标签;另一些则悄然发布,以便用户在问题被广泛披露之前升级。然而,一旦补丁公开,仓库历史可能已经向任何研究该变更的人揭示了漏洞。
VCamper正是利用这种不对称性工作。它并非在整个系统中搜索未知漏洞,而是分析近期代码变更这一小得多的区域,每次让一个Agent评估一个候选提交,并突出显示最可能是漏洞修复的提交。
关注更新:x.com/rndhouse
curl 在提交 76f83f0db23846e254d940ec7fe141010077eb88 中修复了 CVE-2025-0725,该提交标题为 content_encoding: drop support for zlib before 1.2.0.4。标题看起来像是兼容性维护。该修复于2025年1月24日在curl的GitHub仓库中公开,当时 PR #16079 被创建并于当天合并。curl 于2025年2月5日发布了安全公告。这留下了大约12天的公开代码到公告的空窗期。来源:curl 公告,curl PR #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,而没有进行解压缩进度。当前流程中支持的最强后果是远程客户端内存耗尽拒绝服务。
这一结果仅从公开的修复提交中正确地定位了有漏洞的路径,而在分析过程中并未使用CVE文本。当前流程在后果分类上比curl发布的公告更为保守:curl 将该问题归类为 CWE-680,而 VCamper 目前止步于同一旧zlib后备解析器中一个充分支持的远程资源消耗漏洞。
wolfSSL 在提交 abce5be989ccd0665e2b9445abb856886975dfd1 中修复了 CVE-2026-5194,该提交来自 PR #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 / 密钥族绑定缺陷复合最终候选者是有趣的。在最后的阶段运行中,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 <older-release-commit> \
--to <newer-release-commit> \
--provider codex \
--model gpt-5.4 \
--screen-effort medium \
--verify-effort high \
--out /tmp/vcamper-run
有用的标志:
--dry-run:收集Git证据并渲染提示,而不调用Agent CLI--model <name>:向所选提供者传递显式模型名称--effort <low|medium|high|xhigh>:用一个标志同时设置筛选和验证的工作量--screen-effort <low|medium|high|xhigh>:设置第一遍筛选的工作量--verify-effort <low|medium|high|xhigh>:设置第二遍验证的工作量--max-commits <n>:当范围大于预期时快速失败--max-patch-bytes <n>:限制存储在截断提交工件和内联后备提示中的差异字节数--out <dir>:将工件写入特定的运行目录--start-at-stage <inventory|synthesis|interaction|composite_synthesis|reachability|verify>:从特定的阶段性Codex边界开始,并重用来自同一 --out 目录的早期阶段工件--stop-after-stage <inventory|synthesis|interaction|composite_synthesis|reachability|verify>:在特定的阶段性Codex边界后停止,以便单独检查一个阶段使用相同的 --out 目录重新运行同一命令,可在中断后恢复。VCamper 重用已完成的候选提交,从第一个未完成的候选开始重新启动,并继续向前推进。阶段范围的Codex运行也会重用来自同一 --out 目录的早期阶段工件,因此你可以在单独的调用中执行清单、综合、交互、复合综合、可达性和最终验证,而不重复已完成的工作,除非你传递 --rerun-stages。
默认情况下,VCamper 在终端中抑制提供者事件输出。默认终端视图显示候选进度和活动旋转器,同时提供者正在工作。
未完成的候选位于输出目录内的 wip/ 下。已完成的候选在 progress.json 中检查点,并从 wip/ 中提升出去,因此提示、提供者和分析工件在运行后仍可用于检查。
对于Codex运行,VCamper 持久化一个传递本地的证据包,并将模型指向文件,而不是将完整补丁直接嵌入初始提示。每次传递获得一个未截断的 evidence/patch.diff、evidence/changed-files.txt、evidence/hotspots.json 以及变更文件的前/后快照。Codex筛选现在作为五次阶段性调用加上每个候选内部的独立最终候选验证运行:
这使每个提示更窄,使阶段进展可检查,避免因提示大小截断而丢失差异上下文,在直接调用路径不完整时保留依赖交互的加密理论,并让最终验证从单个嘈杂提交中确认多个不同理论,而不是强迫它们在一个提示内竞争。当你希望在继续之前仅检查清单、综合、交互审查、复合综合或可达性时,使用 --stop-after-stage 仅执行一个阶段性边界。使用 --start-at-stage 从同一 --out 目录的后续边界继续。当你只想将热点焦点单元的一个短名单重新运行到后续阶段时,使用 --inventory-focuses。
VCamper 还在运行根目录写入 progress.json。它以 count_pending 和 count_complete 开头,然后在 pending 下列出未完成的候选,在 complete 下列出已完成的候选。待定候选现在包含 active_stage,因此长时间的Codex运行显示候选是否处于清单、综合、交互、复合综合、可达性或最终候选验证中。
分析流程仍报告为 screen 然后 verify,但Codex内部将其扩展为:
screen/inventory:代码优先的重点假设清单,提交消息被暂扣screen/synthesis:类别级综合,将相关的清单结果合并为更强的共享理论screen/interaction:单假设交互审查,针对共享验证流程、特征组合和编译时分枝screen/composite_synthesis:跨类别综合,在存活的交互假设之上添加更广泛的复合理论screen/reachability:单假设利用路径审查,使用紧凑包verify:逐个最终候选验证,对可达性幸存者进行验证,提交消息作为次级上下文恢复gitcodexclaudeVCamper 每次运行都需要 --out。每个输出目录包含:
manifest.json:选定的仓库、范围、CLI设置以及任何用于运行的热点焦点简表progress.json:格式化打印的待定和已完成候选列表,包含顶级计数器和每个候选的 active_stagewip/candidate-*:尚未完成的进行中候选工件candidate-*/input.json:已完成候选的收集提交证据工件candidate-*/screen/prompt-input.json:暴露给提供者提示的代码优先筛选器证据candidate-*/screen/prompt.txt:渲染的筛选器提示candidate-*/screen/evidence/patch.diff:用于筛选传递的完整未截断补丁candidate-*/screen/evidence/changed-files.txt:用于筛选传递的变更文件列表candidate-*/screen/evidence/hotspots.json:从完整补丁派生的排名热点文件和筛选焦点单元candidate-*/screen/evidence/file-snapshots.json:变更文件前后快照的清单candidate-*/screen/evidence/before/* 和 :筛选期间Codex可用的文件快照--inventory-focuses <i,j,...>:将Codex清单限制为特定的热点焦点短名单,同时保留工件中的原始焦点索引--rerun-stages <inventory,synthesis,interaction,composite_synthesis,reachability,verify>:清除指定阶段及其所有下游阶段,然后从同一 --out 目录继续--verbose:打印详细的内部日志和流式提供者输出candidate-*/screen/evidence/after/*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/hypothesis-*/stdout.txt 和 stderr.txt:一个最终候选的验证器提供者输出candidate-*/verify/results.json:合并的每个最终候选验证记录candidate-*/verify/analysis.json:完成的验证器结果candidate-*/stage-state.json:候选完成的最高内部阶段,以及完整流程是否完成candidate-*/outcome.json:两个传递的最终合并候选结果report.json:所有已分析提交候选中的合并可疑发现summary.md:可读的最终摘要