尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

AI代码审查实战:打造可复用的安全审计技能security-audit-skill

AI代码审查实战:打造可复用的安全审计技能security-audit-skill 最近半年我一直在折腾一件事让AI给我写过的代码做安全审查而且不是那种随便问一句“这里有没有坑”而是真正能当团队安全评审纪要用的结果。从最早用通用聊天式问法到后来把审查流程、漏洞判断标准、报告模板全部固化成一套可复用的技能包也就是标题里这个security-audit-skill中间踩了不少坑。这篇就把踩过的坑和最终能用的方案都摊开来聊给同样在做AI代码审查、AI工程实践、或者想把AI Agent真正落到开发流程里的朋友一个参考。1. 为什么需要一个独立的代码安全审查技能1.1 通用AI问答做安全审查的三个痛点我自己一开始也没有单独做技能就是开一个聊天窗口把代码贴给AI说“帮我看看有没有安全问题”。结果来回试了十几轮发现三个特别烦的问题。第一个痛点是标准不统一。同一个函数今天问AI可能说“存在SQL注入风险”明天换一种问法它又变成“建议对输入做类型校验同时注意日志中不要输出敏感字段”。不是它说得完全不对而是你根本没法把前后结果放在一起对比因为每次它评价的维度都不一样。团队里其他同事拿同一份代码去问得到的安全结论五花八门代码评审会开成了猜谜会。第二个痛点是没有上下文。一段代码安全不安全很多时候取决于它周围的环境比如认证逻辑放在哪个中间件里、数据是怎么从入口路由进来的。你把单个函数丢给AI它只能看到局部很容易把安全的代码误报成有漏洞或者忽略真正藏在跨文件调用链里的问题。第三个痛点是不可复现。同一个模型隔一天问同一段代码结果可能差别很大。对于安全审查来说这是要命的因为合规场景里你需要“这次审查覆盖了哪些点、结论是什么”能完整留档下一次还能对照。所以后来我明白了一件事安全审查这件事不能依赖即兴对话必须把审查的规则、步骤、输出格式做成一个可以反复调用的标准技能。这就是security-audit-skill的由来。1.2 为什么叫“skill”而不是普通提示词“skill”这个词在AI工程实践里越来越常见你可以把它理解成一组精心设计的指令、约束、示例和输出模板的封装。它不是让你像跟同事聊天一样随便问而是告诉AI“你现在扮演什么角色、按什么标准、按什么顺序、用什么格式来干活”。我拿一个新员工入职做类比普通提示词相当于问一个老同事“小王这个项目有啥坑”老同事会凭记忆说几个而skill相当于把老同事脑子里的审查清单写成了新员工手册每一章都写明检查什么、证据怎么找、报告怎么写。前者靠临场发挥后者靠流程保障。security-audit-skill这个名字里的“security-audit”两个字是有讲究的。audit不是review不是“扫一眼感觉还行”而是要有明确的审计范围和检查证据逐项核实最后给出可追溯的审计结论。把这个词放到skill名字里其实是给整个技能定了一个基调不要泛泛而谈要输出像审计报告一样的东西。从实现角度看一个skill至少要包含四个部分角色设定告诉模型它是谁有什么专业边界审查范围哪些模块要看哪些不看检查程序按什么顺序、用什么方法找问题报告规范问题怎么描述、风险怎么分级、修复建议怎么给这四个部分我会在下一节详细拆解。2. 核心设计拆解一个可用的安全审计技能应该怎么搭2.1 角色设定让AI进入“安全审计专家”模式第一步不是写检查清单而是先把AI的角色定住。我在skill里写的角色不是“代码审查者”而是更精确的“应用安全审计专家熟悉OWASP Top 10、CWE Top 25、常见框架安全配置和攻击路径分析”。这个定位的目的是把模型的注意力引导到安全风险评估上而不是代码风格、可维护性、性能优化这些无关项。角色设定要避免两个极端。一个极端是写得太宽比如“你是资深开发专家”这样AI会把一半注意力放在代码规范上输出里混着大量“建议使用常量”“建议提取公共方法”之类的噪音。另一个极端是写得太窄比如“你是SQL注入专家”结果遇到越权问题、敏感信息泄露问题它就视而不见了。应用安全的覆盖面很广我最后选择“覆盖Web应用全链路安全的审计专家”再在下面的检查清单里把子领域都列清楚。角色部分我会顺手把一些元规则写进去比如“只基于你看到的代码和描述做判断不要脑补外部信息”“不确定的判断请标注置信度”。这两个元规则后面帮我省了不少事因为AI在安全问题上特别容易一本正经地胡说八道。一个可参考的角色段我放在下面你可以直接抄也可以按自己项目改你是一名应用安全审计专家熟悉OWASP Top 10、CWE Top 25、常见Web框架的安全机制与攻击路径。 本次任务是审查给定项目代码发现真实可利用的安全风险。 审查时必须遵守以下规则 1. 只依据提供的代码、架构说明和上下文做出判断禁止脑补文件之外的信息。 2. 每个发现的问题必须说明触发路径、影响范围和修复建议无法确定的内容标注置信度。 3. 除非发现安全问题否则不对代码风格、性能、可维护性发表评论。 4. 输出格式必须遵循约定的审计报告模板。其实这段角色设定本身也值得单独调试。我第一次直接把角色写好后发现AI输出还是很“散”后来微调了两轮把“禁止脑补文件之外的信息”加进去之后报告里那种“根据经验可能存在……”的底气不足式断言少了很多。审计这件事最忌讳的就是凭感觉给结论。2.2 审查范围与检查点清单角色定了之后最关键的是给AI一份明确的检查清单。如果没有清单AI依然会漏掉很多它“没想到”的点。我维护的这份清单是从实战中一点一点加的目前大概是这样的输入校验与注入类SQL注入、命令注入、XSS、文件上传绕过身份认证与授权类弱口令逻辑、登录绕过、越权访问、未授权接口、JWT校验缺失服务端资源与网络类SSRF、路径遍历、反序列化、XML外部实体数据保护类敏感信息硬编码、日志泄露、加密算法弱项、传输层配置业务逻辑类金额/积分操作未校验、验证码可绕过、并发竞态、超卖依赖与配置类已知CVE组件、调试开关未关闭、默认口令、错误信息泄露你可能会问为什么不直接用OWASP Top 10让AI去跟着看我也试过但实际效果打折。因为OWASP Top 10太概括AI会把“A01:2021-Broken Access Control”这类条目背一遍然后不痛不痒地评一句“该项目可能存在访问控制风险”。这没有用。把顶层分类拆成一个个可执行的检查点AI才知道具体要找什么。检查点不是越多越好我一开始列了50多个结果输出又长又碎。后来做了两轮裁剪一轮按项目技术栈砍掉不适用的比如纯后端API项目就不查DOM XSS一轮按“是否能给出确定结论”来砍如果一个检查点AI几乎永远给不出确凿结论就把它做成“低危提醒”而不是主检查项。2.3 检查流程与证据链条从“觉得有问题”到“确定有问题”有了清单还不够关键要让AI确认安全问题的方式。早期我得到的结论都是“可能”“也许”“建议检查”。这对开发没有用因为开发改代码需要明确证据。所以在后来的skill版本里我强制要求AI在报告每个漏洞时必须带着一条完整的证据链入口到处理逻辑再到触发条件再到影响。我打个比方如果一个审计员报告“财务系统有漏洞”但没有告诉你哪个接口、从哪个参数进入、按什么顺序调用会触发这种报告在公司里没人敢签收。这个逻辑对AI也一样。所以我在skill里写明高危漏洞必须给出具体的调用路径至少要指明文件、函数和参数。为了达到这个效果我会在skill里加入一个“推理前置”的步骤要求AI在正式给结论之前先做一次内部的攻击路径预演比如“如果你是攻击者你会怎么利用这段代码”然后再把预演结果转成报告。这一步对提升结论准确率非常明显AI在“攻击者角色”下更容易找出真正能触发的路径而不是站在静态代码角度做表面分析。证据链这一块还涉及到一个容易被忽略的点上下文窗口不够。一段代码的安全判断经常要跨三四个文件。所以skill里不能只贴清单还得教会AI如何先用“全局概览模式”梳理数据流再进入“局部聚焦模式”逐个文件检查。这一点在后面的实操章节还会细说。2.4 报告格式让输出能直接当评审纪要我发现几乎所有人做AI安全审查时都忽略了输出格式。AI默认喜欢讲故事会从“经过分析我们发现……”开始然后把所有发现混在一起。如果只是自己看看还无所谓但要是当团队评审纪要甚至给客户交差格式非常影响效率。我在skill里设计了一套报告模板可以拆成四块审计范围摘要、高危问题清单、中危问题清单、低危观察项清单。前两块必须详细第三块简写第四块一句话带过。单个问题的描述格式我固定为5个字段字段说明问题标题一句话说清问题风险等级高危/中危/低危位置文件路径函数/行号攻击路径入口参数到处理函数再到触发条件修复建议给出可落地的修复代码或配置修改我为什么要坚持用表格和短句不让AI写长篇大论因为审查报告是要被开发去执行的长段落里面重要信息会稀释。把每个问题压缩成一个表格行开发直接照着修效率和准确性都高很多。后来我给整个技能命名为security-audit-skill本质上也是从输出端把“审计感”钉住让每一次生成的内容都像一份正式审计记录而不是聊天记录。3. 实操过程与核心环节实现拿真实项目完整跑一遍3.1 审查前的上下文准备在实际使用中我发现给AI喂什么上下文直接决定了审查质量。最差的用法是把整个项目文件夹压缩成一个粘贴板然后让AI“全面审查”结果基本等于没有审查因为信息量太大AI只能挑几个显而易见的点应付。我现在的做法是三步走第一步写项目背景卡。包括项目是什么、用什么语言和框架、主要模块划分、哪些是安全敏感模块比如登录、支付、权限、文件上传。一般控制在300到500字核心目的是让AI知道代码在什么样的系统里工作。第二步整理数据流概览。我常用一个简单但好用的格式请求入口 - 认证中间件 - 控制器 - 服务层 - 数据访问层 - 外部依赖每个箭头节点标清楚实际类名或文件名。这一步对AI找越权和链路型漏洞特别重要。第三步按敏感程度分批提交代码。不要一次性把100个文件丢进去。我一般按“认证与权限模块”“用户输入入口模块”“文件与网络交互模块”“数据库与日志模块”四批跑。每一批控制在10到20个文件之间这样AI的注意力不会被稀释。这套准备的思路其实和人工安全评审一样没有架构图、没有数据流直接让一个新人审计员看源码他也会一头雾水。AI只是比你想象的更需要结构化上下文。3.2 执行审查把skill跑起来的两种方式我实际用security-audit-skill跑审查主要是两种方式。一种是在对话式AI工具里直接粘贴skill内容然后把项目背景卡和第一批代码放进来开始一轮审查。这种方式适合单个项目临时检查优点是一两分钟就能启动缺点是每次都要重新粘贴而且聊天窗口会随着对话拉长逐渐丢掉早期信息。另一种是把skill结构化之后做成Agent技能文件挂在自建的AI工作流里。比如把角色设定、检查清单、报告模板分别存成独立文本用工作流节点按顺序加载最后用固定模板输出。这种方式更适合要反复跑的团队场景尤其是能接到CI流水线里每次合并请求自动触发一轮安全审查。不管哪种方式我都会遵守一个原则分轮执行。第一轮让AI输出完整的问题清单第二轮单独挑出高危问题让AI出修复方案第三轮拿修复后的代码做回归确认。一轮跑完直接进入下一轮好处是每轮上下文相对干净不容易出现早期结论被后续对话冲掉的问题。在实际跑的时候我还会在审查开始前加上一句固定指令让AI在输出完报告后自己用一句话评估“这次审查最不确定的地方是什么”。别小看这句它经常能逼出那些AI拿不准、但你可能需要人工复核的点。3.3 一个真实的审查案例从发现问题到修复验证我把去年遇到的一个典型例子简化一下讲清楚完整流程。项目是内部管理系统技术栈是Java Spring Boot MyBatis我跑第三批“数据库与日志模块”时AI在审计报告里标了一个高危问题。问题标题是订单查询接口存在SQL注入风险。位置是OrderQueryService.java第42行findOrdersByCondition方法。攻击路径写的是用户通过GET /order/list?namexxx传入订单名该参数直接拼入动态SQL查询条件攻击者可以通过构造特殊字符改变查询逻辑从而获取非本人订单数据。当时我第一反应是不太信因为团队里MyBatis用得比较规范大部分查询都走的注解和XML里预编译写法。我直接翻到那行代码发现果然是在一个动态查询的复杂业务里有人为了省事用了${orderBy}这种拼接方式虽然理论上那个字段应该由服务端白名单控制但因为参数源头是前端传过来的排序字段确实存在被篡改的可能。修复方案AI也给了把动态排序字段改成服务端枚举映射前端只能传固定的排序key后端转换成白名单字段彻底避免字符串拼接进SQL。我按方案改了之后又用同样的skill跑了一遍回归这次AI确认该问题已经在代码中消解同时没有再报出新的高危项。这个过程让我真正认可了“固定技能固定流程”的价值问题可追溯、修复可验证而不是像以前那样AI说一句话改一个地方改完也不知道到底有没有改干净。4. 常见问题与排查技巧实录4.1 误报太多开发不爱看误报是第一个遇到的头号问题。AI在安全审查里特别容易看到一个正则匹配就觉得有风险比如检测到“eval(”就报“代码执行漏洞”但实际上那个eval接收的参数来自内部配置根本不可控。我的解决办法是在skill里加了两条规则。第一条是“结论必须包含可利用前提”严格禁止AI在没有写清楚攻击者可控输入路径的情况下直接报高危。第二条是“对内置函数和框架方法的调用要结合上下文判断来源”本质上是在逼AI把每个疑似点走一遍数据流而不是只看特征。实际效果大概能把误报率降掉一半还多。另外也别指望完全消灭误报人工审一次总有几次假警报关键是高危误报不能多因为高危误报最浪费团队精力。4.2 漏报严重AI根本没看出问题和误报对应的是漏报。我遇到的漏报集中在两类一类是跨文件调用链型漏洞比如权限校验写在中间件里而某个接口没走这个中间件另一类是业务逻辑漏洞比如“用户可以提交负数订单数量”。跨文件漏报靠上面说的“数据流概览分批审查”能缓解。业务逻辑漏报只能通过把检查清单里的业务规则写得足够具体来解决。比如对电商系统我会明确写出“检查订单金额、数量等参数是否在服务端二次校验”。你没写进去的规则AI是不会主动替你想到的。漏报这种事我认为心态要正不可能指望一次AI审查覆盖所有漏洞。我的定位是把skill当“自动化二哥”用大哥仍然是人工安全评审。AI的强项是覆盖面广、执行快、不会疲劳人工的强项是理解业务意图。两者结合才能达到可接受的安全水位。4.3 审查结果“正确但空洞”没法落地很多朋友跟我吐槽AI输出报告写得像教科书每条都说“建议对输入进行校验”但就是不告诉你在哪个文件哪个参数上校验、怎么校验。这个问题几乎全出在输出格式没约束好。我把报告模板改成了前面说的固定五字段之后效果立竿见影。AI在“位置”字段就不得不写文件路径和函数名在“攻击路径”字段就不得不写参数到触发点的链路。如果某个字段写不出来AI通常会自己降低风险等级或者标注置信度这其实也是好事因为它被迫面对“自己并没有搞清楚”的现实。另外我还会在skill尾部放一个“反例”段落给AI看几个差劲的审查评论和对应的优秀评论让它模仿优秀范例的输出模式。这招是从写提示词的人那里学来的模型对齐这个事给例子比讲道理管用得多。5. 进阶把security-audit-skill接入团队流程5.1 和CI/CD结合做成自动审查关卡既然skill已经稳定把它接到自动化流程里就是水到渠成的事。我目前的标准做法是在合并请求阶段拉取变更代码结合项目背景卡自动生成审查上下文调用AI工作流跑一遍审计然后把高风险结论以评论形式发回到MR下面。这个玩法有几个前提条件。一是模型调用要稳定二是skill文件版本要和项目依赖一起管理三是报告要汇总到统一的地方不能散落在聊天记录。我建议团队先手动跑两三个迭代确认误报率可以接受后再上自动化不然每天机器人都在报假警团队很快会把它拉黑。我对AI自动审查的定位是“门卫”不是“判官”。它可以拦住常见的高危问题但最终合不合并还是由人来定。把它设为门卫之后开发体验其实更好因为真正有问题的代码在进入人工评审前就被拦下一轮人去看的时候只需要聚焦剩下的小范围问题。5.2 与多AI协作和Agent流程的融合最后聊一下我最近在尝试的方向多AI协作。简单说就是让模型A负责第一遍全面扫描让模型B负责针对高危问题的攻击路径模拟再用模型C检查修复方案是否引入新的回归问题。每个模型只做自己最擅长的一段最后由一个汇总模型把三段结论合并成一份报告。这种做法和“单次对话塞一个大skill”相比好处很明显上下文更干净每段任务边界明确模型跑起来不容易跑偏。缺点是工程复杂度上去了要处理模型之间的输入输出对接还要做好容错比如某个模型超时或者返回乱码时其他环节不能跟着挂。顺带提一句做这类Agent流程时我建议每一步之间都留结构化中间文件比如JSON格式的结论。这样即使后一个模型理解错了前面的结果至少人还能回头查中间状态不至于全部黑盒化。这个习惯是我在做LLM智能体工程时学到的放到代码审查场景同样适用。最后再讲点实在感触。security-audit-skill这种技能不是一次性写出来就能一直用的它需要跟着项目一起长。我隔一段时间就会把上一轮审查里的漏报案例翻出来看看是检查清单没覆盖到还是上下文给得不够然后把改进点固化回skill文件里去。整个过程其实就是一个很典型的AI工程实践模型是通用引擎技能是专用定向器流程是质量保障。你越早把这三层分开想越不容易在AI代码审查这件事上踩到“什么都试过但什么都没落地”的坑。如果让我给刚开始尝试的人一个最切实的建议我会说先别追求覆盖所有漏洞类型选一个你最在乎的高危类别比如注入或越权围绕它把检查清单、证据链、报告模板做透跑顺之后再横向扩展。一个能稳定输出一份高危结论的skill远比一个什么都想查但什么都说不清的skill要值钱。
返回列表