GitHub AI Scan:绿色检查不等于完整扫描
GitHub AI Scan的结果是建议,不是自动合并门禁。看到PR检查通过,也不能据此推断AI扫描已完成且没有问题;“不适用、还在排队、执行失败、已完成但无发现”必须分开记录。
文章目录
GitHub在2026年10月15日宣布AI Scan for pull requests正式可用。本篇围绕一个更实际的问题:把新的AI检测接入现有审查后,怎样避免用一个绿色状态掩盖覆盖缺口?下面用十条合成PR记录,分别计算适用范围、完成覆盖和无发现比例。Read in English。
公告增加的是检测信号
正式发布公告将AI Scan定位为CodeQL的补充,面向部分CodeQL尚未覆盖的语言和框架,例如PHP、Shell/Bash和Dockerfile。发现会出现在PR讨论和文件差异页面,并标注AI来源,也可能附带修复建议。
同一公告明确:这些发现是建议性的,不会让code scanning检查失败,也不能通过ruleset要求阻止合并;来自fork的PR和Dependabot创建的PR不运行AI Scan。这里讨论的是10月15日公开的能力边界,不是对所有未来版本的保证,也没有实际启用任何仓库设置。
新信号对已有审查链的价值,在于提供额外待判断线索。它不自动替代代码语义检查、项目测试或发布责任。团队首先要决定发现由谁处理、何时需要进一步证据,而不是把“出现AI图标”当成完整安全策略。
没有发现,至少可能代表四种状态
官方文档说明AI Scan针对PR而非全仓扫描,发现也可能有误报。它的工作范围本就不能被解释为对整个仓库作出无漏洞结论。以下状态记录方法是本文的工程建议,不是声称GitHub提供完全相同的API字段。
第一类是不适用:例如本次PR不在产品运行范围内。第二类是适用但没有可用结果:可能等待、失败或尚未确认完成。第三类才是已完成且没有发现。第四类是已完成并产生发现,接下来还要人工确认有效性。把前两类的空值转成空数组,会制造本来不存在的“已检查且无发现”。
“无发现”也不是“没有漏洞”。它只说明在记录的代码版本、分析范围与运行条件下,该次分析没有报告问题。没有独立参考答案,就无法从这个数推算漏报率或召回率。把覆盖记清,是评估检测效果之前的基础,而不是检测效果本身。
十条PR记录,三个不同分母
设有十条明显虚构的PR,其中六条适用;六条里四条完成、一条排队、一条失败;四条完成记录中,三条没有发现,一条报告了一个教学占位问题。剩下四条不适用。这里没有真实仓库、漏洞或用户信息。
完成覆盖相对于适用PR是4/6,即2/3;相对于全部PR则是4/10,即2/5。两个数都能回答合理问题,但分母不同:前者问“该跑的有多少完成”,后者问“总变更中有多少获得了这类分析”。不能只选更大的数字来描述覆盖。
三条无发现记录占已完成结果的3/4。若把另外六条没有结果的记录都当作无发现,就会得到错误的9/10。这个90%并非乐观估计,而是改变了状态含义。对于一次审查,最先该问的常常不是“发现了几个”,而是“这一条到底有没有有效分析结果”。
如果观察窗口内没有适用PR,完成覆盖的分母为零,应标成不适用并保留计数,不能写成0%或100%。较早提交已完成的结果,也不能在缺乏适用证据时算作新head提交的完成覆盖。
八项检查保留空结果与缺结果的区别
以下标准库代码把已完成无发现写成空列表,把缺少结果写成None。字段名和状态值都是本文的教学约定,不是GitHub REST响应示例,也不会联网。它只核验记账逻辑,没有扫描代码或测量产品检出能力。
# Synthetic coverage bookkeeping, not GitHub API or vulnerability scanning.
from fractions import Fraction as F
rows=[
{"id":"a","eligible":True,"status":"complete","findings":[]},
{"id":"b","eligible":True,"status":"complete","findings":[]},
{"id":"c","eligible":True,"status":"complete","findings":[]},
{"id":"d","eligible":True,"status":"complete","findings":["demo-1"]},
{"id":"e","eligible":True,"status":"queued","findings":None},
{"id":"f","eligible":True,"status":"failed","findings":None},
*[{"id":i,"eligible":False,"status":"not_applicable","findings":None}
for i in ["g","h","i","j"]],
]
eligible=[r for r in rows if r["eligible"]]
complete=[r for r in eligible if r["status"]=="complete"]
no_findings=[r for r in complete if r["findings"]==[]]
assert len(rows)==10
assert len(eligible)==6
assert len(complete)==4
assert len(no_findings)==3
assert F(len(complete),len(eligible))==F(2,3)
assert F(len(complete),len(rows))==F(2,5)
assert F(len(no_findings),len(complete))==F(3,4)
assert sum(r["findings"] is None for r in rows)==6
print("8 scan-state bookkeeping checks passed")
本地八项断言通过,分别核对总数、适用数、完成数、无发现数以及三个比例,最后确认六条缺结果记录仍保持None。若生产系统使用自己的分析任务,应以它真实可用的完成信号和版本标识为准,不能只从“评论数为零”反推分析已完成。
绿色检查和人工决策要各有证据
既然官方明确AI发现不自动阻断合并,一个绿色code scanning检查只能按其自身规则解释。团队若要求某类变化必须经过人工复核,应在现有审查流程中明确责任人和依据,不能假定建议性发现已经变成强制门禁。
处理一个发现时,先确认它指向当前PR提交,而不是较早提交;再定位相关代码路径、输入条件和可能后果。确认问题后,修复应有相应回归证据;认为误报时,也应记录具体理由。简单写“AI错了”或“AI说有问题”,都没有提供可复用判断。
修复建议同样是待评审改动。它可能改善被指出的局部,却引入兼容性或业务语义变化。阅读实际差异并运行相关测试,比仅确认原评论不再出现更有意义。本文没有提供漏洞利用步骤,也没有用人为攻击结果替代代码审查证据。
不要把覆盖范围差异误认成质量差异
不同团队的PR组成可能不同:语言、变更规模、fork贡献比例和自动依赖更新数量都会影响适用集合。直接比较“每百条PR的发现数”,可能主要是在比较工作负载,无法单独证明哪一方模型更准。
更可用的记录是按适用类别分层,保留完成状态、分析版本或可取得的配置、处理结论与人工耗时。初期可以用固定观察窗口核对记录是否完整,再决定是否开展带参考答案的效果评估。没有参考答案时,结果应停留在覆盖与工作量描述。
这与此前ReviewBench的评论与缺陷覆盖区别相连:发现条数不是已确认缺陷数,完成覆盖也不是缺陷召回率。把这些量放在同一图表里时,名称和分母必须明确,避免读者把不同层次的指标当成同一件事。
接入之前先问成本与处理能力
公告说明无需单独的Copilot许可证,但AI Scan消耗Code Security AI Credits;可用性与仓库归属、可见性及相应安全产品有关。正式接入前应核对自己的账户与有效设置,不把“无需Copilot许可证”理解成无成本运行。
这里没有读取账单或替用户启用功能,也不提供未经核验的单次扫描价格。团队应同时考虑扫描用量和处理发现的人工成本。一个产生更多建议的工具,若没有人判断、复现和修复,并不会仅凭建议数量自动形成工程收益。
可以先给一个明确范围的观察窗口:哪些PR预期适用、谁负责确认任务完成、谁处理发现、遇到缺结果如何说明。先把这四个问题回答清楚,再讨论是否扩大范围,能减少“有工具、无闭环”的投入。
把未知状态留在记录里
AI Scan正式可用带来了新的检测入口,但合并决策仍需要明确证据。对没有运行或没有完成的分析,保留未知比填成“通过”更准确;对已经完成的无发现结果,也只按其实际范围解释。
若这组状态划分、分母计算与记录示例帮你避免把绿色检查误读成完整覆盖,欢迎通过文末支持区自愿支持。它们的用途,是让每次审查都能说明“检查了什么、还不知道什么”。
来源与补发说明
先经Google News发现,再核对10月15日原始公告与官方文档。采用的产品事实在原计划时段前的公告已有依据;账本与图示为原创。本篇保留2026年10月19日11:30文章日期,实际于当晚补发。未运行真实扫描器或GitHub API。
支持
如果文中的解释或示例帮你解决了问题、节省了时间,欢迎自愿打赏支持本站。
二维码可点击放大。更多支持方式见支持页面。


