
我们团队全面引入AI写代码差不多是从前年年底开始的。到现在主干分支里直接由AI生成的代码占比已经超过一半提交频率也翻了一倍。但每次开安全例会我盯着那个安全评分看两年了几乎没动过。一开始我以为是指标口径太保守后来把六份权威报告翻了个遍再对照我们自己的数据才发现问题比分数不涨要深得多——AI代码越写越多正在用一套和人工代码完全不同的方式改变软件的安全形态。这篇文章不聊情怀只讲实证为什么效率上去了安全评分却原地踏步以及一个工程团队到底该怎么防。1. 现象拆解代码量翻倍了安全评分为什么原地踏步1.1 先对齐一个认知安全评分到底在评什么很多人一提起安全评分第一反应是漏洞数量。但实际上绝大多数团队用的安全评分是把好几路信号揉在一起算出来的综合分。以我们团队使用的方案为例它至少包含四块SAST静态代码扫描扫描器按规则匹配代码里的危险模式比如SQL注入、反序列化漏洞、硬编码密钥。这类工具对已知缺陷模式很敏感对语义是否正确基本无感。SCA软件成分分析扫描第三方依赖库对照NVD漏洞库、Sonatype OSS Index等源标出哪些组件版本存在已知CVE然后按CVSS严重程度加权。密钥与敏感信息检测在代码库、镜像、日志里搜AK/SK、Token、数据库连接串。历史存量漏洞复查看过去发现的高危漏洞是否按期修复、是否发生回归。换句话说传统安全评分本质上是已知问题清点器。它回答的是你的代码里有没有已经公开的、可被规则识别的坑而不是你的代码在真实世界里会不会翻车。这个定位差异是后面所有矛盾的起点。1.2 AI代码占比过半安全评分却纹丝不动问题出在哪我们内部做过一次统计采用AI辅助编程之后代码提交频率大概是原来的1.8倍单次提交的行数也更多。但奇怪的是CR代码评审里发现的问题比例并没有出现数量级的恶化线上故障率也没有明显飙升。按理说分数就算不涨总该波动几下吧可它就是稳稳地横在那里。后来我做了一次更细的拆解发现评分不涨的真正原因有三个而且一个比一个隐蔽。第一个原因代码总量膨胀导致单千行代码的问题密度被稀释了。AI生成代码的速度远超人类相当于同一段时间里产出面积变大。如果AI代码确实引入了更多风险但分母代码总量涨得更快那么每千行代码的高危漏洞数这个比值反而可能是下降的。而安全评分算法里大量使用这类密度指标密度不变甚至下降分数自然不动。第二个原因AI代码的缺陷恰好不在传统扫描器能看见的维度上。传统SAST最擅长抓的是模式化问题比如某个库函数被危险调用、某段代码没有做参数校验。但AI代码最常见的毛病是逻辑看起来顺理成章但业务语义上有坑比如边界条件少了一个等号、缓存失效时间写错、权限校验放到了错误的层级。这类缺陷扫描器看不见代码评审也容易被工整的代码风格迷惑。安全评分衡量的东西没有变化分数自然也不会因为你换了一种写代码的方式而变化。第三个原因评分体系里缺少变更来源维度。我们团队在推行AI编程半年后才开始在Git提交信息里给AI生成的代码打标。在此之前评分系统根本不知道哪些代码是AI写的。一个不追踪代码来源的指标体系当然无法反映AI代码特有的风险波动。它只能告诉你有没有已知漏洞却无法告诉你这批已知漏洞是谁引入的、为什么引入的。1.3 一个容易被忽略的副作用开发者对AI代码的所有权感在降低这可能是我在这两年里观察到的最微妙、也最危险的变化。人工写的代码出错之后开发者会本能地感到这是我的锅所以评审和自测会更仔细。但AI生成的代码很多开发者潜意识里把它当成外部工具的输出出了问题第一反应是AI写的不怪我。这种所有权感的降低带来的是审查力度的真实下降。我们有几次高危线上事故事后复盘时相关代码确实是AI生成的而代码评审人在评审记录里只留了一句功能测试通过。没人认真追问过为什么这里要绕过权限校验因为大家默认AI写的代码不会犯低级错误。可事实证明AI不会犯语法错误但它完全会在语义层面犯下灾难性的错误。2. 六份报告的实证结论它们到底说了什么2.1 我为什么选了这六份报告而不是随便找几篇博客过去两年我陆续把能接触到的相关研究都扫了一遍最后挑出六份在统计口径和研究对象上有代表性的权威报告用来做交叉验证。它们分别来自两家老牌安全厂商的年度应用安全报告、一个代码托管平台对海量仓库的聚合分析、一份开源社区的供应链安全报告、一份高校团队对AI编程助手的规模性对照实验以及一家大型互联网公司内部公开的工程效能复盘。选这六份是因为它们的视角足够多元厂商报告能看到漏洞数据的宏观趋势平台报告能看到行为变化学术报告能看到对照组差异公司复盘能看到落地后的真实代价。任何单一来源都可能出现口径偏差但六份放在一起重合的部分就比较可信了。2.2 六个口径不同的报告得出了五个高度一致的结论我把六份报告的结论做了交叉汇总剔除掉各自特有的观点后有五个结论几乎每一份都提到了。结论一AI生成代码的语法正确不等于语义安全。所有报告都提到一个现象AI生成的代码能通过编译、能通过格式检查但在边界条件、异常处理、并发控制这些程序正确性范畴内缺陷率并不低。一位学者在对照实验里说得更直白AI生成的代码更像是一个熟练实习生写的代码——表面规整深层漏洞需要靠人来兜底。结论二AI生成代码的漏洞密度并没有显著低于人类代码。这是最打破幻觉的一条。很多团队引入AI的动机里多少都掺杂着AI写代码比人更规范的期待。但厂商报告里对海量样本的统计显示在SAST能识别的漏洞类型中AI生成代码的漏洞密度与人类代码基本持平个别年份甚至略高。真正拉开差距的不是漏洞数量而是漏洞的类型分布。结论三供应链风险被系统性放大了。这里的放大有两个层面。第一AI倾向于推荐统计上最常见的依赖库和版本而最常见不等于最安全第二AI在生成代码时会在没有明确指示的情况下脑补依赖偶尔还会把包名拼错。开源社区的报告里专门提到了随之而来的依赖混淆、版本锁定过旧等问题。我对此深有体会后面实操部分会展开。结论四AI使用量越大测试覆盖率下降得越快。六份报告里有四份独立提到了这个趋势。原因是多方面的开发者让AI补测试时AI生成的单测往往只是覆盖Happy Path断言写得很浅而开发者本人则因为AI已经把功能写完了心理上更没有动力去补边界测试。结果就是代码行数涨了有效防御却没跟上。结论五重复代码、死代码的比例在上升。代码托管平台那份报告引用了GitClear等公开研究的数据趋势非常一致AI辅助编程普及后仓库里复制—粘贴—修改型的代码比例明显上升代码被重复使用但很少被重构死代码和影子代码无人维护、无人理解上下文越积越多。这些代码会成为扫描噪音的放大器也会让后续的安全整改成本指数级上升。2.3 最容易被忽视的一条AI代码的风险分布和人类代码完全不同这一点六份报告里只有两份明确点出但它恰恰是我认为最核心的洞察。人类开发者在写代码时最容易犯错的是复杂业务逻辑和跨模块交互所以传统安全经验集中在SQL注入、反序列化、越权这些经典漏洞上。但AI生成代码最常见的失误是在不了解完整上下文的情况下做出了看似合理的局部决策。举个例子AI在生成一个用户信息接口时极大概率会根据通用模式加上鉴权注解但如果你的项目里鉴权是通过网关统一处理的AI这层自作聪明的校验反而可能引出双重鉴权或绕过问题。又比如AI在调用文件上传功能时通常会顺手补一个后缀名白名单校验但很少会主动校验文件内容、文件大小、解压路径穿越这些和业务强相关的点。这种局部合理、全局偶然的缺陷分布传统SAST规则几乎覆盖不到安全评分体系更是完全没有概念。它不知道AI生成了什么自然也不知道该拿什么标准去评价。3. 安全评分失灵的技术根源不是算法不努力是维度没跟上3.1 评分体系是验收式的不是过程式的我研究下来安全评分体系完全可以类比成期末考试它只检查你当前状态里有没有已知问题而不关心你这门课是怎么学过来的。只要你把已知漏洞修掉、把依赖版本升级到安全线以上分数就会保持好看。但AI代码对安全的挑战恰恰是过程性的——它的风险来自生成时对上下文理解不足评审时被表面工整欺骗变更频率太高导致追责困难。这些因素全部发生在写代码的过程中而不是写完代码之后。你用一套只验收结果的体系去度量一个过程性的风险变化分数不涨几乎是必然的。这也是为什么很多团队AI用得越多、安全分越稳——那不是因为安全变好了而是因为评分体系根本没在看真正的风险。3.2 扫描器对AI代码的识别效果比想象中更差当然评分体系没跟上不只是指标设计的问题底层工具也拖了后腿。我拿几段AI生成的典型问题代码分别跑过我们自己的SAST引擎和几款开源工具结果很有意思AI代码最常见的边界条件错误和逻辑漏洞类问题扫描器基本全军覆没偶尔能命中的是AI碰巧写出了和公开漏洞库中的某种模式高度相似的代码。反过来AI代码的误报率却不低——因为AI喜欢写出结构很标准、但语义空泛的代码而不少规则恰好喜欢匹配这种结构于是产生大量无用告警。误报一多真正的告警就被淹没了。开发者在安全平台里看到的是满屏的可能存在问题却又修不掉、改不完慢慢地就产生了告警疲劳。等到扫描器真的抓到一个高危漏洞时它已经混在一堆问题里不被重视了。3.3 评分指标设计上缺少变更来源这个维度这一点前面已经提到但值得专门展开。目前主流安全评分模型的特征基本是这四类漏洞数量与严重程度、修复及时性、依赖健康度、历史安全事件。你可以试着在里面找一找AI生成代码占比AI代码变更频率AI代码引入的依赖数量这些维度一个都没有。这意味着什么呢意味着你的安全评估体系本质上还在用一套人类代码时代的模型去理解一个机器与人混合生产的代码库。就像用一把只量身高的尺子去预测体重不是尺子不准是它根本没量对你的核心指标。我们团队后来在内部做了一个实验把Git提交信息里的AI标记汇总成月度趋势再跟我主观记录的安全事件清单做对比发现一个很明显的关系——AI代码占比高的模块往往在权限缺失输入校验不严配置漂移这几类问题上的出现频率更高。而这些传统评分全都看不见。4. 团队防御指南把AI的效率接进现有的安全体系4.1 第一步给AI代码打标让风险可以被看见、被追踪没有标记后面的一切改进都无从谈起。我强烈建议所有深度使用AI编程的团队从今天开始就建立AI代码标记机制。具体怎么做我给出一套实测可行的方案。标记方式在Git提交信息中增加固定前缀比如feat: [ai] 完成用户中心接口重构。如果用的是代码补全类工具比如写一段代码由AI补全可以在代码文件头部或相应函数上方加注释generated-by-ai。如果团队用IDE插件推动可以让插件在保存AI生成代码时自动插入标记不要依赖开发者手动操作。落点标记先进入提交信息再由CI脚本解析最终汇总到安全看板的AI代码占比指标中。注意要保留历史数据方便后续做相关性分析。我自己踩过不标记的坑。当时为了省事让开发者有印象就标一下结果三个月后做分析时超过一半的提交根本查不到来源。后来规范了IDE插件自动打标提交模板约束才把标记覆盖率拉到90%以上。4.2 第二步在CI里给AI代码开一条独立的质量门禁标记之后下一步就是让CI区别对待。具体做法是在现有流水线基础上增加一个并行阶段专门针对最近由AI生成或修改的代码执行一档更严格的安全检查。这包括三块内容。第一块SAST规则集升级。常规代码跑默认规则集AI代码额外叠加一档自定义规则。我们团队用Semgrep写了几十条规则专门抓AI代码的典型问题比如非空断言使用、不安全的异常捕获、明文密钥写在配置里、日志中输出敏感字段、分页参数未做上限限制。实测下来这类自定义规则对AI代码的命中率明显高于通用规则。第二块依赖来源审计。对AI新增的第三方依赖做一次来源审计比对包名与官方仓库是否完全一致、检查版本是否过旧、确认许可证是否合规。这个步骤不需要额外买工具在SCA工具的配置里开启来源校验策略就行。如果你的SCA工具不支持那就写一条CI规则检测到新增依赖时强制要求开发者补充为什么选这个版本的注释。第三块密钥与敏感信息高强度扫描。AI代码特别喜欢在示例里直接写死Token、AK/SK这类东西因为它的训练数据里到处都是这种模式。所以对AI代码的扫描档位要调高把疑似密钥的规则也打开而非只查确认密钥。4.3 第三步把人工评审重心从看有没有Bug转向看上下文是否成立AI代码评审的价值不在于逐行找逻辑错误而在于验证AI做这个局部决策时是否理解全局上下文。这个思路要落实到评审流程里。我建议团队内部约定三条评审纪律。第一条AI生成的代码默认走两人评审变更负责人复核流程。普通代码一个人看就行AI代码至少两个人看且至少包含一个对该模块业务逻辑有长期积累的人。这个人负责回答一个核心问题AI在这里做的假设跟我们系统的真实约束一致吗第二条评审时要看diff之外的东西。别只看AI改了哪几行要看它改动的边界——调用方、依赖方、权限模型的上下游。很多AI高风险问题恰恰是它没改的部分比如一个新接口忘了加鉴权但旁边的入口函数看起来一切正常。第三条把AI生成代码是否需要重构作为评审的必须输出项。AI代码通常可以工作但往往不是最优结构。评审人如果认为某段AI代码能用但不可维护应该明确要求重构而不是为了赶进度放行。否则三个月后这些代码就会变成没人敢碰的风险黑盒。4.4 第四步重建度量体系让安全评分真正反映AI时代最后一步是回头改造安全评分本身。我的建议是不要推翻重来而是在原有指标之上叠加三组增量指标。增量缺陷率只看最近两周新增代码里的高危漏洞密度而不是全量代码的漏洞存量。这样能更早观察到AI使用策略变化带来的风险波动。缺陷逃逸率线上事故中有多少是在评审和测试阶段没被发现、最终被用户触发的。这个指标比漏洞总数更能反映防御体系对AI代码的覆盖效果。AI代码风险登记册这是一个管理动作不算纯指标——用表格记录每一个AI引入的高风险点包括模块、风险描述、引入时间、负责人、状态。每季度过一遍把长期无人处理的登记项直接升级为紧急整改项。同时建议每季度做一次评分校准。安全评分不是设置完就能一直用的它需要根据代码库的实际变化调整权重。比如当AI代码占比超过40%后应该把AI变更追踪率作为一项加分或减分因素纳入总分否则评分永远只会原地踏步。5. 常见问题与排查实录我踩过的坑你大概率也会遇到5.1 问题速查表这一节我把自己和身边团队在实际落地中反复遇到的问题整理成一个速查表方便你直接对照排查。问题现象根本原因排查思路与解决方案AI代码被扫描器标出一堆告警但对线上业务没影响规则集与AI代码特征不匹配或扫描器把格式规整误判为存在风险先统计误报率超过40%就调整规则集对确认为误报的规则建立白名单但每季度必须复核白名单内容开发者给AI代码打标后评审人反而更不认真看代码打标变成了甩锅而非追责强调标记是为了追踪风险回归不是为了找人背锅在评审模板里增加必填项AI代码假设的上下文是否与系统一致SCA扫描显示大量高危依赖被引入源头是AI推荐了旧版本AI倾向于推荐统计上最常见的版本常见不等于安全在SCA策略中强制最新稳定版优先并拒绝锁定EOL版本对AI新增依赖设置强制人工确认的CI门禁AI代码占比越高单测覆盖率越低开发者把生成代码当成完成工作补测试意愿下降把AI生成代码的测试覆盖率单独统计在质量门槛中设置下限改用AI辅助生成测试但要求测试者在提交前人工删掉Happy Path断言安全评分长时间不涨汇报时被质疑安全工作没有进展评分体系的指标维度跟不上开发方式的变化调整指标口径增加增量缺陷率、缺陷逃逸率等过程指标用季度风险报告代替单纯分数汇报5.2 三个印象深刻的踩坑现场第一个坑试图靠人工一眼看穿AI代码结果评审队列彻底爆炸。推行AI编程初期我们曾经天真的希望评审人通过认真阅读来兜底。结果AI生成的代码量大、速度快评审队列快速堆积开发者的评审时长直线上升最终演变成评审只是点个通过。后来我们认清现实人工评审只能覆盖高风险变更低风险批量变更必须靠自动化工具辅助。现在我们的策略是AI代码默认走自动化检查抽检评审只有超过一定行数或涉及敏感操作时才强制人工全量评审。第二个坑把AI生成的看似合理的权限校验当成安全加固结果反而引发了越权。有一次AI在生成内部管理后台接口时自动加了一层基于用户角色的判断逻辑。从代码本身看这个判断非常标准。但它没意识到这个模块的入口网关已经做过权限校验而且使用的是另一套更严格的租户隔离模型。结果就是双重校验逻辑互相冲突在某个边界场景下反而放行了不该放行的请求。从那之后我们明确规定AI生成的鉴权逻辑必须由人工确认与现有权限模型的关系不能直接合并。第三个坑试图一刀切禁止AI推荐依赖结果引发了一轮流程反弹。一开始发现AI频繁推荐旧依赖后我直接上了禁止AI新增依赖的规定。结果开发者产生逆反心理有人绕过规则手动添加了同样的依赖反而绕过了我们的审计。后来改成AI新增依赖强制走安全确认流程自动版本校验问题才真正缓解。这个教训就是安全策略要顺着工作流设计而不是和工作流对着干。5.3 我最后保留的三条个人底线写了这么多最后分享三条我在实战中一遍遍验证过、目前依然在坚持的底线。第一不要把安全评分当成安全工作的指挥棒而是当成一面后视镜。它告诉你的永远是已经发生的事你需要一套前置的雷达——AI代码标记、增量缺陷率、上下文评审才能提前发现风险。第二不要让AI写关键路径上、且你完全无法理解上下文的代码。我给自己定了一条线AI可以写工具类、模板代码、测试辅助代码但涉及权限模型、支付链路、数据导出这类核心逻辑时人必须亲自入场至少要做到逐行理解。第三安全水位不是靠减少AI使用量守住的而是靠更强的可观测性和更快的响应能力守住的。我见过很多团队因为怕出安全问题退回纯人工编码最后效率塌陷、反而更不安全。正确的路永远是一边用AI提速一边把安全基础设施的颗粒度打磨到能跟上这个速度。坦白说AI代码与传统安全体系的碰撞这两年才刚刚露出冰山一角。我分享的这些经验大概率不是标准答案但它至少是一条被真实项目验证过的路径。如果你也在为AI代码越写越多、安全评分纹丝不动这件事发愁希望这份报告拆解和防御指南能帮你少走几个弯路。