最近在折腾 AI Agent 技能包的时候,我明显感觉到一个趋势:大家不再单纯纠结“怎么让模型更聪明”,而是开始研究“怎么把专业经验沉淀成可以复用的 Skill”。我这边刚把 security-audit-skill 从零到一搭完,前后踩了不少坑。这篇文章不聊虚的,直接把整个设计思路、目录骨架、规则写法、集成方式和排错过程摊开讲。
这个 Skill 适合两类人看:一类是想给自己的 AI 编程助手补上安全审计能力的开发者,另一类是安全团队想把审计 SOP 自动化沉淀下来的同学。目标只有一个:让 AI 在代码评审、依赖检查、配置核查这些场景里,真正干点安全审计的活,而不是只会写一句“请检查是否存在安全问题”这种空话。全文我会尽量按实操路径来讲,你照着做,基本能复现出一个能用的版本。
在开始之前先说一句:安全审计是一个防御性动作,所有脚本和规则都应在授权范围内、基于合法项目进行设计与使用,这一点会贯穿全文。
1. Security Audit Skill 到底解决什么问题
1.1 为什么要把安全审计能力做成 Skill
先说个我在实际使用里的观察:直接把“帮我审计一下这个项目”丢给 AI 助手,它大概率会给你回复一段泛泛而谈的总结,比如“发现某些依赖版本偏低”“建议做好输入校验”,然后就没有然后了。原因很简单,通用大模型的强项是语言理解与生成,但安全审计是一个需要“专业SOP + 工具校验 + 结构化输出”的领域,光靠提示词里的临场发挥,效果非常不稳定。
把安全审计做成 Skill,本质上是给 AI 配了一套“带步骤的岗位手册”。Skill 里规定了它应该先看什么、用什么工具扫、按哪些规则判断、最后输出什么格式的报告。这样一来,AI 不再凭感觉工作,而是像一名按照标准作业流程执行的安全工程师,每一步都有据可循。我自己的体会是,用了 Skill 之后,AI 对安全问题的响应质量提升非常明显,尤其在依赖漏洞和密钥泄露这类“查得出就是查得出,查不出就是查不出”的场景,结果稳定多了。
从行业背景来说,现在不少团队都在用 AI 辅助写代码,代码量上去了,安全隐患也随之增加。如果没有一个结构化的审计技能,安全问题就只能靠人工 Code Review 去兜底,这对大部分团队来说是不可持续的人力开销。所以把审计能力封装成 Skill,本质上是把“人的经验”转成“可自动执行的流程”,这件事无论对个人开发者还是小团队来说,都很值得做。
1.2 审计场景拆解:它能管到哪一层
我在设计 security-audit-skill 的时候,没有一上来就写规则,而是先列了一个场景清单。安全审计覆盖面太广,如果不切片,Skill 会变成一个什么都想管、什么都管不好的大杂烩。我最终锁定了四个最实用、也最容易自动化的审计场景。
第一个是依赖漏洞审计。现代项目普遍使用 npm、pip、Maven、Go modules 这类包管理器,而依赖树里只要有一个高危漏洞,整个应用就等于裸奔。这个场景非常适合用工具自动扫,比如基于已知漏洞库做版本比对,能在几秒钟内给出结论。
第二个是代码安全审计。这里的重点不是让 AI 去理解所有业务逻辑,而是盯住几类高频高危问题:硬编码密钥、SQL 注入风险、命令注入、不安全的反序列化、路径穿越等。这个场景需要“静态规则 + 模型理解”结合,Skill 的价值在于告诉 AI 按什么优先级去看哪些文件。
第三个是配置与权限审计。很多安全问题不是代码写出来的,而是配置漏出来的。比如云厂商的存储桶权限设为公共读写、数据库端口对全网开放、不必要的特权角色被赋给普通用户,这些都可以通过检查配置文件、IaC 模板来发现。
第四个是密钥与敏感信息泄露审计。这个我最推荐优先做,因为影响最直接。只要 .env 文件或者源码里的 token 被提交到仓库,哪怕仓库是私有的,都存在泄露风险。用工具扫描历史提交记录是标准做法。
这四层场景被我做成了 Skill 内部的四个模块,每个模块有独立的规则文件和工具调用方式。这样设计的好处是,使用的时候可以按需裁剪,比如只跑依赖审计,或者只跑密钥扫描,都能单独执行,不会因为全量扫描耗时太长而影响效率。
2. Skill 的骨架设计:先别急着写规则
2.1 从“审计方法论”到“可执行动作”
很多人一上来就写规则文件,这是最容易翻车的做法。我先说一个方法论层面的问题:安全审计本质上是一个“收集证据—对照标准—判定风险—输出报告”的过程。这个流程在人工场景下很自然,但要让 AI 执行,必须把它拆成非常明确的小动作,否则模型会跳过步骤。
我在 Skill 里给 AI 定义的动作链条是这样的:先确定审计范围,是单文件还是整个仓库;再选择对应场景模块;然后调用扫描器或读取指定文件;接着按规则库对结果做风险判定;最后生成带严重级别和修复建议的报告。看起来简单,但每个动作背后都需要配套的提示词和参数约束,缺一环都会导致结果不完整。
举个例子,如果审计范围是“整个 Node.js 项目”,Skill 会先让 AI 检查是否存在 package-lock.json 或 yarn.lock,如果存在,就优先用锁文件版本做依赖比对,而不是去读 package.json。这两个文件给出的信息粒度完全不同:package.json 只是声明范围,锁文件才记录实际安装的精确版本。这一点不写清楚,AI 很容易误判漏洞是否存在。
再比如代码审计模块,我要求 AI 在判定一个函数是否可能存在注入漏洞时,不能只看函数名,还要追踪输入来源。如果输入来自用户请求参数,那风险等级就要上调;如果输入是硬编码常量,那就要降级或忽略。这种“上下文敏感”的判断逻辑,正是安全工程师的核心经验,也是 Skill 最需要沉淀的部分。
2.2 目录结构与模块划分
我最终采用的目录结构参考了当前 AI Agent 技能插件的主流约定,同时又针对安全审计场景做了定制。根目录是一个 skill 文件夹,比如叫 security-audit-skill,里面分三层:入口文档、规则资源、可执行脚本。
入口文档就是 SKILL.md,这是整个 Skill 的“总指挥”,AI 加载 Skill 时首先会读取这个文件。它里面写清楚这个 Skill 是干什么的、什么时候该用、不能做什么、有哪些前置条件、建议按什么顺序调用内部模块。规则资源放在 references 或 rules 目录下,每个场景一个文件,比如 dependency-audit.md、code-audit.md、config-audit.md、secret-audit.md,每个文件里是具体的审计清单,AI 在判定风险时会去查阅。
可执行脚本放在 scripts 目录下,比如调用 npm audit、grype、trufflehog 这类工具的包装脚本。这里有个关键设计:Skill 不一定要自己完整实现所有逻辑,它可以把“查漏洞”的动作交给现成工具,然后自己负责“解读结果、判断上下文、生成报告”。这样既避免重复造轮子,也大大降低了误报率。
这种目录结构的好处是职责清晰。AI 的“理解能力”用于规则阅读和上下文判断,工具的“确定性能力”用于精确扫描,两者互补。如果你以后想扩展新的审计场景,不需要动主入口,只要新增一个规则文件和一个扫描脚本,再在 SKILL.md 里注册一下就能生效。
2.3 关键技术选型与工具链
做安全审计 Skill,工具选型直接决定效果上限。我试过几组方案,最终保留了下面这一套,兼顾覆盖面和易用性。
依赖漏洞扫描我选的是 Trivy 和 Grype。Trivy 比较全能,不仅能扫容器镜像,也能扫文件系统的依赖,而且漏洞库更新快,误报相对可控。Grype 是 Anchore 出的,和 Syft 配合用效果很好,特别适合对 SBOM 做扫描。如果你项目里用的是 npm 生态,自带的 npm audit --json 也可以作为第一道快速筛查,然后把结果交给 Skill 做二次分析。
密钥扫描用的是 TruffleHog,这个工具最擅长在 Git 历史里翻找已提交的密钥,而且能识别很多常见平台的 token 格式。代码静态审计我用 Semgrep 作为主力,它的规则是 YAML 写的,非常容易嵌入到 Skill 的规则库里。另外 Python 项目可以用 Bandit,Java 项目可以考虑 SpotBugs,但不需要全上,免得Skill 太重。
我不建议在 Skill 里捆绑太多重型工具。经验是选两到三个核心扫描器,把规则写深,比捆一堆工具然后每个都扫不深要实用得多。工具链选定之后,还有一件非常重要的事:把每个工具的 JSON 输出格式在 SKILL.md 里说明清楚,告诉 AI 该解析哪个字段、如何映射到风险等级。很多 Agent 集成失败就是因为 AI 面对工具输出不知所措,而 Skill 恰好能补上这个“解读层”。
3. 核心规则与检查项:把审计经验翻译成机器能懂的语言
3.1 依赖漏洞审计规则
依赖审计这条规则我写得最细,因为它是整个 Skill 里最“确定性”的部分:版本号对不对、漏洞库里有没有匹配项,这些都是客观事实,AI 发挥空间不大,所以规则要尽量精确。
规则文件里我要求 AI 按以下顺序执行:第一步,识别项目使用的包管理器,是 npm、pip、Maven 还是 Go modules;第二步,找到锁文件,没有锁文件的直接提示风险,因为这意味着依赖版本不可复现;第三步,运行对应的漏洞扫描命令,并保留 JSON 输出;第四步,把 JSON 里的每条漏洞记录映射到 CVSS 严重等级,再统一整理成风险清单。
这里有一个细节值得强调:CVSS 分数只是参考,不能直接当成最终风险等级。我在规则里写了一个“上下文修正”的逻辑,如果一个高危漏洞位于生产依赖而非开发依赖,风险等级上调;如果该组件没有直接引入而是被传递依赖带入,且当前没有实际调用路径,风险等级可以下调。这种修正逻辑在人工审计里很常见,但如果不写进 Skill 规则里,AI 是想不到的。
依赖审计的输出格式我也做了约束。每条漏洞记录必须包含组件名、当前版本、修复版本、漏洞编号、CVSS 分数、所属依赖层级、以及是否在调用链上。有了这些字段,后续无论是人工处理还是自动生成工单,都会非常顺畅。
3.2 代码安全审计规则
代码审计是最考验 Skill 质量的模块,因为漏洞的“可能性”与“必然性”之间有一道巨大的鸿沟。我的设计思路是:用 Semgrep 做第一轮模式匹配,把疑似风险点全部捞出来;然后让 AI 对每个疑似点做上下文判决,最终输出“确认风险”“需要人工复核”“误报”三档。
规则文件里我重点覆盖了这几类问题:字符串拼接方式构造 SQL 或命令、使用 eval 或 exec 执行外部输入、反序列化未限定类型、文件路径拼接未做规范化处理、以及在代码中直接出现疑似密钥的长字符串。每一类都配有具体的“危险信号例子”,目的不是让 AI 去看懂所有语言特性,而是让它在看到这些模式时保持警惕。
上下文判决我给了几条硬约束。第一,输入来源如果来自 HTTP 请求参数、文件上传、外部 API 回调,必须标记为高优先级;第二,如果数据流经过了白名单校验、参数化查询、转义函数等处理,可以降级为低风险或忽略;第三,如果 AI 无法确定数据流走向,一律标为“需要人工复核”,不能为了表现“判断力”而擅自给出“无风险”结论。这条规则是我踩过坑之后加的,AI 在没有把握的时候倾向于安抚用户,而对安全审计来说,这是最危险的倾向。
3.3 配置与权限审计规则
配置与权限审计主要针对容器配置、编排文件、CI 文件、以及 IaC 模板。这个场景的规则可以非常具体,因为很多坏配置是“长得很标准”的,不需要复杂上下文判断。我在规则文件里维护了一张“高危配置清单”,比如 Dockerfile 里使用了 root 用户运行应用、暴露了不必要的端口、依赖镜像没有固定 digest;再比如 Kubernetes 的 Deployment 允许特权容器、挂载了宿主机目录、资源限制缺失;还有存储桶策略配置为公共读写、安全组规则对 0.0.0.0/0 开放了敏感端口等。
每一项高危配置,我都会在规则里给出“为什么危险”的简短解释,以及“建议改成什么样子”。这样做有两个好处:对 AI 来说,它可以直接引用规则生成修复建议,不需要额外发挥;对使用者来说,报告里能看到明确依据,而不是一句模糊的“存在风险”。
权限审计我额外加了一条规则:优先检查“最小权限原则”是否被打破。在人工审计中,这条原则几乎是万能标尺,任何配置最终都要回到这个问题上来审视。Skill 在执行配置扫描时,会重点寻找“赋予了超出任务所需权限”的配置,并把这类问题单独归为一个风险类别,方便使用者优先处理。
4. 实操过程:从空目录到可用的 security-audit-skill
4.1 编写 SKILL.md:入口文件怎么组织
前面聊了不少设计和规则,现在开始动手。首先创建项目目录,然后在根目录放一个 SKILL.md 文件。不要小看这个文件,Agent 能不能正确使用 Skill,百分之八十取决于它写得好不好。
我建议的 SKILL.md 结构是:先写用途说明,三到五句话讲清楚这个 Skill 做什么、不做什么;然后是适用场景列表,比如代码审计、依赖审计、密钥扫描;接着是前置条件,比如需要安装哪些命令行工具、是否需要网络权限;再往下是使用流程,用编号列出 AI 接手任务后的标准操作步骤;最后是输出规范,要求 AI 必须按什么结构输出报告。
举一个使用流程的写法示例:第一步,确认审计范围,如果是本地目录,检查目录是否存在并判断项目类型;第二步,根据项目类型判断启用哪些审计模块;第三步,运行对应的扫描脚本并读取 JSON 结果;第四步,对照 rules 目录下的规则文件进行风险判定;第五步,填写报告模板并输出。这里每一步都要写清楚“判断条件”和“执行动作”,不要写“适当检查项目情况”这种模糊表述。
我在实际使用时还加了一个“禁止行为”小节,虽然有点反直觉,但非常有效。里面写明这个 Skill 不做攻击性验证、不越权访问资源、不将扫描结果外发。这既是安全合规要求,也能防止 AI 在审计过程中做出危险动作。
4.2 接入扫描器:让 Skill 真正动手查
SKILL.md 只是“说明书”,真正干活的是脚本。我在 scripts 目录下放了一组包装脚本,每个脚本都只做一件事:调用某个扫描器,把结果转换成统一的 JSON 格式。
以依赖审计为例,脚本逻辑是这样:先判断是否存在 package-lock.json,如果存在就执行 npm audit --json;如果项目里有 Pipfile.lock 或 requirements.txt,就调用 pip-audit;如果是容器镜像或者通用文件系统,就调用 trivy filesystem 或 grype dir。脚本最后会把不同工具的输出统一转成一条条“漏洞记录”,清除掉工具输出的噪音字段,只保留漏洞编号、组件名、当前版本、修复版本、严重等级、描述这些核心字段。
为什么要做统一格式?因为 Agent 对大段复杂 JSON 的解析能力是有限的,而且不同工具的字段名千奇百怪。让 AI 直接面对 npm audit 的输出它是能看,但效率不高,还容易漏字段。统一格式之后,AI 面对的是一个非常规整的数组,每条记录的结构完全一样,解析错误率会大幅下降。
密钥扫描脚本我用的方案是 TruffleHog 扫描整个 Git 历史,然后过滤出“当前仍旧存在的密钥”和“历史上出现过但目前已删除的密钥”两类。别小看这个分类,很多团队以为删掉了 token 就没事了,但历史上已经泄露的密钥必须视为已泄露,需要立即轮换。这个判断规则写进脚本逻辑里之后,报告的说服力强了很多。
4.3 报告模板设计:审计结果要让人一眼看懂
安全审计 Skill 的最终输出是一份报告,报告如果可读性差,前面的扫描工作就大打折扣。我在 SKILL.md 里内置了一份强制使用的 Markdown 报告模板,AI 输出时必须按模板填写,不能自己发明格式。
模板的顶部是一个摘要区,包含审计时间、审计范围、项目类型、扫描工具版本、发现的风险总数,并按严重等级统计:Critical、High、Medium、Low。然后是风险明细区,每个风险一条记录,包含风险标题、所在文件路径、风险等级、证据说明、修复建议。最后是一个行动清单区,优先列出 Critical 和 High 级别的问题,并给出“建议立即处理”的明确措辞。
这里有一个实操细节:我要求 AI 给每条风险加上“证据摘要”,就是粘贴一小段原始代码或配置内容,而不是只写“发现硬编码密钥”。没有证据的风险描述,接收方很难快速置信和定位。同样,修复建议不能只写“建议使用环境变量”,而是要写出具体的修改方向,比如“将该密钥从配置文件中移除,改为从 CI 变量的 SECRET_KEY 注入,并轮换该密钥”。这样报告才真正具备可执行性。
报告模板还有一个用户自定义区,允许使用者追加业务相关的审计要求,比如“检查是否遵循团队内部的日志脱敏规范”。我已经测试过,AI 能很自然地融合这块自定义内容,不会破坏整体输出结构。
4.4 在 Agent 环境里挂载与验证
Skill 写完之后,下一步就是让它跑起来。我这里以当前主流 AI 编程助手的 Skill 加载机制为例,一般操作方式是在项目的 .agent 或者 .claude 之类目录下创建一个 skills 子目录,然后把 security-audit-skill 整个文件夹拷贝进去。具体目录名因环境而异,但不影响原理。
我在验证时最喜欢的测试用例是一个故意包含多种问题的测试项目。我会在测试项目里放一个带硬编码密钥的配置文件、一个存在已知高危漏洞的依赖锁文件、一个权限过宽的容器编排文件,以及一个没有做输入校验的搜索接口代码。验证通过的标准是:Skill 能自动发现上面四类问题,并按模板生成报告,报告里的结论和人工审计结果基本一致。
第一次跑的时候大概率不会顺利,最常见的现象是 AI 压根没有调用 Skill,而是把它当成普通对话直接回答了。这时候不用急着改代码,先在提示词里明确引用 Skill 名称,比如“请使用 security-audit-skill 对当前目录进行安全审计”,多数情况下 AI 就会加载到正确技能。这个坑我后面详细说。
5. 常见问题与排查技巧实录
5.1 Agent 不调用 Skill 怎么办
我碰到过的最典型问题就是 Agent 不调用 Skill。排查思路是这样的:先检查目录路径是否正确,Skill 文件夹有没有放在 Agent 会扫描的目录下;再检查文件命名,入口文件必须严格命名为 SKILL.md,大小写也不能错;最后检查 SKILL.md 的开头部分,用途描述是否足够直白,如果写得过于抽象,Agent 可能认不出它适合当前任务。
还有一个容易忽略的点:不同 Agent 对 Skill 的发现机制不一样,有的要求在使用前先手动触发一次“加载技能”动作,有的则会在对话中动态选择。最佳做法是看一遍对应 Agent 的日志输出,确认它有没有扫描到 skill 目录。日志里能看到加载记录,比盲猜效率高很多。
如果确认已经加载但就是没调用,那大概率是 SKILL.md 里的触发条件写得不够清楚。我给这个 Skill 写了几条非常明确的触发词,比如“安全审计”“security audit”“依赖漏洞”“密钥泄露”“权限检查”,并在文档开头就摆出来,这样能有效提高命中率。
5.2 扫描结果误报率太高
误报率高是最伤可信度的问题,尤其是代码审计模块。我最初的规则只写了危险模式,结果 AI 把很多正常代码都标成了风险,报告发出去没人敢信。后来我调整了策略:不再让 AI 直接基于模式匹配下结论,而是强制要求它做“数据流追踪式”的判断,并且把判断依据写在风险记录里。
为了进一步降误报,我给每个危险模式都配了“豁免场景”。比如,如果发现 md5 的使用,但要先判断是否用于加密存储密码,如果只是用于生成非安全场景的缓存键,那就不算高危;如果发现 exec 调用,要先判断参数是硬编码常量还是用户输入,只有用户输入场景才标记为高风险。技巧是“宁可少报,不可乱报”,但少报也不能漏报,所以对于那些判断不了上下文的场景,我会标成“待人工复核”而不是直接忽略。
依赖审计的误报问题主要来自漏洞库与锁文件版本不匹配。解决方案是尽量使用最新的漏洞数据库,并让 Skill 在报告里标注漏洞数据的查询时间,方便使用者判断时效性。这也是报告模板里带上“扫描工具版本”的原因。
5.3 Token 消耗与超时控制
安全审计 Skill 跑一次全量扫描,会产生大量中间数据,如果全塞进上下文,Token 消耗会非常夸张,甚至导致请求超时。我在最初的版本里就吃过这个亏,扫描一个中型项目,日志输出几万行,把 Agent 直接“撑爆”了。
后来我在脚本层面做了数据裁剪。扫描工具输出 JSON 之后,脚本先做一次过滤,只保留严重等级达到 Medium 及以上的记录,Low 信息只保留统计数字,不保留原始内容。这样进入上下文的数据量会缩小一个数量级。同时在 SKILL.md 里明确告诉 AI:不要一次性读取整个扫描结果文件,而是优先读取裁剪后的摘要文件,只有需要详细调查某一条风险时,才对单个文件做定点读取。
超时问题还和扫描范围有关。如果项目很大,建议先按目录或者模块拆分审计范围,而不是一次全扫。我在 Skill 里加入了“范围参数”设计,用户可以指定只审计 src 目录、只审计特定配置文件,或者只跑某一类规则。这个设计对大型项目非常实用。
5.4 规则更新与维护
Skill 上线之后不是一劳永逸的,安全规则需要持续更新。我的做法是给每个规则文件加上修订记录,包含更新时间、更新人和变更内容。每隔一段时间,我会把漏洞数据库和工具版本升一次级,并重新跑一遍测试用例,确保没有回归。
规则维护还有一个小技巧:记录“误报案例库”。每次人工复核发现 AI 的结论有问题,就把这个案例写进 references 下的 false-positive-cases.md 文件,同时在规则文件里补充对应的“豁免场景”。这样随着时间推移,Skill 的准确率会明显上升。这比一开始就把规则写得很全更实际,因为很多边界情况是只有在真实项目中才会遇到的。
另外,多留意 Agent 社区里其他人分享的 Skill 用法很有帮助。安全审计方法和工具链在不断演进,比如新的漏洞类型、新的扫描器、新的依赖锁定格式,这些信息的获取和消化,其实比单纯维护代码本身更重要。把新知识同步进 rules 文件,再用测试集验证一遍,整个 Skill 才会越用越顺手。
我在实际使用中最深的一点体会是:Skill 不是一个“写完就结束”的交付物,它更像一套需要持续维护的知识体系。把它当成一个长期演进的安全助手来养,效果远好于把它当成一次性脚本。最后再分享一个小技巧:给每个审计模块都留一个“dry-run”模式,也就是不实际执行危险操作,只打印将要执行的命令和范围。这样在不确定脚本行为的时候,可以先看它会干什么,再放手让它跑。对于安全审计这种场景,谨慎永远没错。