十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

从人工到自动化:把安全审计流程封装成AI Skill的实践指南

从人工到自动化:把安全审计流程封装成AI Skill的实践指南 1. 为什么我决定把安全审计沉淀成一个 Skill事情起源于前段时间接到的一个活朋友所在的创业公司拿到一笔融资产品准备上架之前被投资方的安全团队要求出一份像样的安全审计报告。他们的代码库不大不小四十多个服务、二十万行左右但时间很紧两周内要交付。我一开始的想法是直接靠人工过一遍重点模块配合几个现成的扫描工具把报告拼出来。但真正动工之后发现两个问题第一反复做过的扫描、检查、核对动作太多每换一个服务就要把同一套流程重跑一遍纯体力活第二审计经验全在脑子里团队里其他人干不了或者说干出来的东西风格天差地别有的只会列漏洞清单有的只会写“建议加强安全意识”这种废话。那阵子正好在折腾 Claude Code 和 Codex 这类编程助手的 Skill 机制。所谓 Skill简单说就是给大模型预装一份“操作手册”告诉它遇到某类任务时按什么流程走、该调什么脚本、该产出什么格式的结果。普通 prompt 是有问才答Skill 是有备而来。于是我就冒出一个念头能不能把整套安全审计方法论包括信息收集、依赖检测、敏感信息扫描、风险分级、报告模板全部打包成一个security-audit-skill让 AI 按我的流程帮我干活说干就干。这个 skill 前前后后改了三个版本从最初的一堆零散规则文件到后来形成一套能独立完成“代码库体检”的技能包。中间踩了不少坑也把很多审计环节从“玄学”变成了“可复现的流水线”。今天这篇文章就是把整个设计思路、SKILL.md 怎么写的、实际跑起来会遇到什么问题一次性讲清楚。2. 从审计流程到 Skill 工作流的拆解2.1 先把“人怎么审”翻译成“AI 怎么审”写 Skill 之前最先要做的不是打开编辑器写规则而是把人工审计的完整流程拆出来。我自己的审计习惯大致分五步信息收集摸清项目结构、技术栈、依赖清单、入口文件、暴露面。静态代码审查按风险优先级逐层扫描认证、授权、输入校验、SQL 拼接、反序列化、文件上传这些高危区域。依赖与供应链检查找出已知漏洞版本的第三方库查锁文件、查传递依赖。动态行为验证对可疑逻辑做数据流推演确认漏洞是否真的可达。报告输出与整改建议按危害等级归档给出可落地的修复路径。这五步如果靠人肉干第一和第三步最机械第二步最吃经验第四步最费时间第五步最看沟通能力。而一个 Skill 恰恰可以承担第一步、第三步、第五步的大半工作量并在第二步辅助做风险标注第四步引导 AI 做针对性的深挖。我在设计工作流的时候没有让 AI 一次性把五步全干完而是把它拆成了三个可独立调用的子流程快速体检、深度审计、报告生成。这样既可以在五分钟内出一个“大致看看”也可以花半小时做“全面过一遍”。灵活性在真实项目中非常重要因为不是每个调用场景都需要全套流程。2.2 核心不是 prompt是“外挂工具箱”很多人把 Skill 理解为“写一段很长的系统提示词”这是最大的误解。真正让 Skill 好用的是它自带的脚本、规则文件和模板这些东西让 AI 不再凭空推理而是有据可查。拿我的实际案例来说security-audit-skill的目录结构是这样的security-audit-skill/ ├── SKILL.md ├── rules/ │ ├── auth-rules.md │ ├── injection-rules.md │ ├── file-upload-rules.md │ └── crypto-rules.md ├── scripts/ │ ├── scan_gitleaks.py │ ├── check_dependencies.py │ └── analyze_go_files.py ├── prompts/ │ ├── deep-dive.md │ └── report-generate.md └── templates/ ├── audit-report.md └── risk-matrix.csvrules/里存放的是针对不同漏洞类型的审查规则。比如auth-rules.md里记录了 OAuth 回调地址校验的几个典型缺陷点、JWT 算法混淆攻击的判断依据、越权接口的识别方法crypto-rules.md里明确了哪些加密库的哪些用法属于反模式。scripts/里是真正能跑的脚本。比如scan_gitleaks.py用正则和熵值检测硬编码密钥check_dependencies.py读取依赖锁定文件并对比已知漏洞库。prompts/和templates/则是给 AI 特定的指令和输出模板。这个结构的好处是AI 遇到一个新代码库时可以直接调用scan_gitleaks.py拿到线索再去injection-rules.md里查找对应的判断标准最后按audit-report.md的格式写结果。每个环节都有真实数据支撑而不是 AI 凭借训练语感“猜”这个项目哪里有问题。这是我认为 Skill 和普通 prompt 之间最本质的差别prompt 告诉 AI 该怎么说Skill 告诉 AI 该做什么、用什么工具做、按什么标准判断。2.3 先跑通一个最小闭环依赖漏洞扫描在做完整整体设计之前我建议你也和我一样先挑一个最简单的子流程跑通。我选的第一个是依赖漏洞扫描因为它最机械、最容易被自动化。原理不复杂读取项目的package-lock.json、requirements.txt、go.mod这类依赖锁定文件把包名和版本号提取出来再对照已知漏洞库判断风险。这里的关键点是很多项目里锁文件里的依赖条目可能非常多几个大型前端项目能产生上千条依赖记录不可能让人肉一条条看。脚本扫描只需要几秒钟然后让 AI 只看漏洞评级为 high 或 critical 的那几行。check_dependencies.py的核心逻辑就三层快速解析文件格式、调漏洞库接口、按严重程度过滤排序。跑通这个闭环之后整个 Skill 的骨架就出来了后续把其它规则文件、审查流程、报告模板一个个填进去就行。脚手架比想象中更重要因为先看到一个“能出结果”的全流程回头改起来才有方向感。3. SKILL.md 到底该怎么写完整示例与设计逻辑3.1 一个可直接改造的 SKILL.md 骨架SKILL.md 是整个 Skill 的“宪法”AI 会先读它然后根据它决定要不要调用这个技能、怎么调用、按什么顺序执行。写的时候既要让 AI 准确判断“该不该用”也要让 AI 清楚“用了之后怎么干”。下面是我目前使用的SKILL.md简化版本你可以直接拿去做底座再调整--- name: security-audit-skill description: 对目标代码仓库进行安全审计与风险分析。适用于交付前安全自查、第三方代码风险评估、以及已知漏洞排查等场景。 --- # Security Audit Skill ## 触发条件 当你需要完成以下任一任务时使用本 Skill - 对代码仓库进行安全风险扫描与漏洞识别 - 检查是否包含硬编码密钥 / 敏感信息泄露 - 分析依赖锁定文件查找已知高危漏洞 - 输出结构化的安全审计报告与修复建议 如果用户只是询问某类漏洞的一般原理不需要启动本 Skill。 ## 审计阶段 ### 阶段一信息收集 1. 扫描仓库根目录识别使用的技术栈语言、框架 2. 寻找并记录锁文件位置package-lock.json, pnpm-lock.yaml, requirements.txt, go.mod, Cargo.lock 等 3. 统计仓库内文件类型分布确定重点审查模块 ### 阶段二自动扫描 执行 scripts/ 下以下脚本并读取输出 - python3 scripts/scan_gitleaks.py . - python3 scripts/check_dependencies.py lockfile 记录所有命中项不要忽略 low 级别发现在最终报告中合并呈现。 ### 阶段三定向深挖 基于自动扫描结果和以下规则文件逐项验证 - rules/auth-rules.md → 认证授权相关代码 - rules/injection-rules.md → 注入类风险 - rules/file-upload-rules.md → 文件上传相关 - rules/crypto-rules.md → 密码学误用 注意对每一条潜在漏洞必须确认“从输入到危险函数”的完整路径无法确认则标注为待深入验证。 ### 阶段四报告生成 按 templates/audit-report.md 生成报告。危险等级定义如下 - Critical可直接被未授权访问或远程代码执行 - High需要特定前置条件才能利用的高影响漏洞 - Medium信息泄露或代码质量问题但暂无直接利用链 - Low不符合最佳实践但风险有限的问题 ## 重要注意事项 - 不要凭空猜测版本号或漏洞信息所有依赖风险必须有脚本输出或可靠数据源支撑 - 不要给“建议使用安全框架”这类空泛建议每条修复意见必须对应到具体文件和修改方向 - 敏感信息扫描结果包含密钥时应立即提示用户视为已泄露而非仅标记“建议处理”3.2 为什么“触发条件”和“不做什么”比“做什么”更重要我的 Skill 第一版写完最大的败笔就是触发条件写得太宽泛description 里写的是“帮助用户完成代码安全审计”害得 AI 经常在用户只是问“你知道什么是 SQL 注入吗”这种基础问题的时候就把 Skill 加载了然后跑一堆无用的流程浪费上下文窗口不说回答还显得特别笨重。所以后来我专门加了“如果用户只是询问某类漏洞的一般原理不需要启动本 Skill”这一句。这行字看着不起眼但对 Skill 的使用体验是质变级别的优化。Skill 不是越主动越好而是要在正确的时候被调用不该用的时候别抢戏。同理“每条修复意见必须对应到具体文件和修改方向”这条规矩也极其重要。AI 默认的毛病是给空泛建议告诉你“建议加强输入校验”但这等于没说。把这条写死在 SKILL.md 里之后输出的质量立刻上了一个台阶。3.3 给规则文件注入“判断逻辑”而不是“知识列表”再看一下rules/目录里那些规则文件应该写什么。我强烈建议不要写成教科书式的“什么是 XSS”“什么是 SSRF”这些东西模型本来就会写进去纯属浪费 token。真正有价值的是你基于实战经验得出的、模型未必会主动想到的判断线索。拿file-upload-rules.md举例我写的关键检查点不是“文件上传可能绕过扩展名过滤”这种教科书结论而是## 文件上传高发风险点 1. 扩展名校验仅存在于客户端 JS前端可以绕过 2. 校验逻辑只检查了 Content-Type 头而不是文件内容魔数 3. 上传目录位于 Web 根目录下且该目录未禁止脚本执行 4. 文件名使用原始文件名或可控拼接存在路径穿越风险 5. 上传后回显的 URL 是直接拼接的注意是否可构造非法路径这种“判断逻辑”式的规则AI 拿到之后可以直接拿着去代码里照方抓药。它不是知识的堆砌而是几把手术刀能帮模型省去自己思考“该看什么”的时间直接看关键位置。每条规则最好都能说清楚“你看到什么代码结构就认定为什么风险级别”。例如文件名拼接我这么定义如果发现 filename 直接来自请求参数且未经过路径规范化处理 且上传目录配置为可访问的静态资源目录则至少为 High 级别。AI 拿到这种规则就能快速做分类判断而不是模糊地觉得“这里好像不太对”。4. 实际跑审计时最容易翻车的几个环节4.1 误报率失控根源在“看得太少”而不是“看得太多”Skill 跑起来之后我遇到的第一个真正让人头疼的问题是误报。AI 扫描一段代码时特别喜欢根据变量名或注释猜风险。比如看到一个变量叫password就提示“疑似硬编码密码”但实际看上下文那只是一个数据库连接配置的字段名根本不是密码。一开始我以为是模型能力问题后来想明白了模型的判断很多不是基于代码执行路径而是基于代码语义的“联想”。它会因为某个函数名叫decrypt就怀疑使用了弱加密算法哪怕那个函数实际调用的加密库是安全的。解决方法是把规则文件里的“从输入到危险函数的完整数据流”检查写死成强制动作。也就是在 SKILL.md 里明确要求每一个潜在漏洞必须说明攻击者控制的输入从哪里进来、经过了哪些处理、最终到达哪个危险函数。如果 AI 没办法描述这条路径那这个漏洞就不算数。加上这个约束之后误报率降了至少一半。代价是扫描时间变长、token 消耗变大但审计报告的可信度完全不是一个量级。4.2 上下文窗口被塞爆原因是没做信息分层另一个高频问题是大代码库扫描时直接把 AI 的上下文窗口撑爆了。我的目标项目里有大量第三方依赖文件和生成代码如果前后端所有的package.json都让 AI 直接读它连主要业务代码都还没看到就已经处理完了十几万 token。后来我用了一个分治策略让脚本先做一遍“信息摘要”把大文件的体积压下去再交给 AI。比如对.js文件我不让 AI 把整个文件读一遍而是让脚本先用树形结构提取出所有函数名和高风险关键字出现的行号AI 只需要根据行号精准定位风险区域再去看这几行代码。“关键信息先摘录完整内容按需读取”这个策略让 Skill 能处理大得多的仓库且在上下文有限的情况下仍然能覆盖到要害。另外针对依赖锁定文件这类重复结构信息脚本会提前压缩成“包名 版本 安全风险”的结构化摘要。模型拿到的不是上千行 JSON而是精简后的高危列表。4.3 单语言规则一套走天下的梦醒得越早越好我的项目主力语言是 Go 和 TypeScript。第一版规则全部围绕这两种语言来写后来项目里引入了一个 Python 写的内部工具服务Skill 的表现立刻拉胯。它拿 Go 语言的内存安全思维去审 Python给出的建议驴唇不对马嘴。原因很简单规则文件里那些“判断逻辑”本质上是带语言的。比如crypto-rules.md里我写的是判断 Go 的crypto/aes/crypto/rand的使用是否安全但这些对 Python 的cryptography库完全不适用。我的调整是在每个规则文件顶部加字段声明适用范围# crypto-rules.md 适用语言: Go, TypeScript # 以下规则不适用于 Python / Ruby / PHP然后在SKILL.md的信息收集阶段强制要求先识别语言矩阵再根据语言类型加载对应规则文件。这样不同语言的代码审查走的是完全不同的检查清单不会交叉干扰。4.4 依赖库对比结果竟然是过期的这里要特别提醒一下依赖扫描的结果是有时效性的。有一次我的 Skill 跑完显示某个依赖版本无已知漏洞但三天前这个漏洞的 CVE 编号刚刚公布。如果用旧库数据去扫描那个版本一定会被标记为“安全”而这个结论在真实世界是不成立的。所以我在 Skill 的脚本里留了一个数据源更新日期提示输出中会标注“本次依赖漏洞扫描基于 XX 数据库快照日期。若需最新情报请手动更新漏洞库”。同时建议扫描频率较快的场景在本地额外维护一个自动更新服务。安全审计不是一次性活动依赖库的时效性直接影响结论的可靠性。5. 让 Skill 真正能当队友用涉及本地工具和服务化扩展的玩法5.1 接入本地扫描器把 Skill 从“读书人”变成“动手派”写到这一步一个纯靠模型和脚本的 Skill 已经能处理不少场景了。但如果想让它在团队里真正能当队友用我建议你把本地已有的安全扫描工具挂载进来。所谓“挂载”就是在工作流里加入一个调用步骤让 AI 可以把项目路径交给本地工具执行再读取工具输出的结果。常见而且合规的本地工具包括静态分析工具、依赖检查的 CLI比如 OWASP Dependency-Check、代码质量管理工具甚至是编译器自带的 lint 安全规则。我在实际使用中把这类工具的输出合并进报告里并让模型对工具报告中被标记为 error 的条目做二次人工复核也就是模型自己复核。原因有两个本地工具输出的是规则匹配的结果未必理解业务上下文需要模型结合数据流做判读。模型判断的过程其实是在帮你过滤误报它标注“这个 error 是真实可利用的”还是“这是测试代码里的假阳性”直接决定了报告里排风险优先级的花名册。如果你有内部搭建的漏洞情报平台也可以把数据源接口接进来。这样 Skill 就能基于最新漏洞情报而不是模型训练时的旧知识来做判断。这也是我认为 Skill 未来最值得投入的扩展方向之一——它不应该是一个封闭的静态规则包而是一个能动态调取工具与数据的执行层。5.2 审计报告的自动化生成用模板反而更显功力很多人觉得报告模板是约束让 AI 自己发挥更好。试过就知道完全不是这样。没有模板的 AI 报告篇幅忽长忽短格式千奇百怪。团队里的人拿到手要花半天时间重新整理最后告到老板那儿成了能力问题。我在templates/audit-report.md中规定了以下固定结构# 安全审计报告 - [项目名] ## 审计概览 - 审计时间 / 审查范围 - 技术栈 - 总体结论明确可发布 / 有条件发布 / 不可发布 ## 风险汇总表 | 风险等级 | 数量 | 关键发现 | |---------|------|---------| | Critical | 0 | 暂无 | | High | 3 | ... | ## 详细发现 对每个风险单独出一节 - 风险描述可被利用的方式 - 影响范围涉及文件 - 复现思路从输入到危险函数的数据路径 - 修复建议具体到文件与改动方向 ## 改进建议非紧急项 不建议把这里写成“安全意识培训”这种废话 要写类似“建议将 token 统一改为短期有效的 JWT 而非自定义加密串”这种真实可执行的项。这套模板的威力在于AI 的输出会被强制纳入同一个思维框架不会忘了影响范围、不会跳过复现路径。而“总体结论”这一行更是倒逼 AI 做综合判断而不是只列一堆问题就完事。报告生成完之后我还会加一道文件导出步骤直接落成一个 markdown 文件。如果项目里要求用 Excel 或者 PDF 分发我会让脚本再加一个简单的格式转换然后在团队协作工具里做一次 diff 才能归档。整个报告环节的关键不是“写得多”而是“结论清晰、定位准确、能直接驱动修复”。5.3 回归脚本是我觉得最值得做的一件事说到“驱动修复”就离不开修复之后的验证。这个环节我在第二版 Skill 里才补上补完之后整个流程才闭环。做法是在 Skill 的 rules 目录里维护一份regression-rules.md里边按风险类别记录“修复后必须验证的路径”。比如如果一个越权接口被修复验证时确认未授权请求是否返回 403而不是返回 200 空数据如果 SQL 拼接被改成预编译语句验证用户输入中带单引号时是否不再报语法错误如果文件上传扩展名校验被修复验证上传带双扩展名的文件是否被拒绝每次修复完成后我会让 Skill 重新扫描一遍之前命中的代码位置把结果与上一版本的扫描结果做对比确认原本命中的风险点已消失且没有引入新的可疑逻辑。这一步相当于把安全审计从“一次性的体检”变成了“持续的健康管理”。尤其对于长期迭代的项目每次发版前让 Skill 先把git diff涉及的文件做一次定向复查成本很低收益却很大。很多公司一年只做一次外部渗透测试中间的空窗期就靠这种自动化回归来兜底。6. 关于 skill 和 agent 的关系顺手聊几句因为我在内部团队分享这个 skill 的经验几乎每次都会有人问这东西跟 agent 到底有什么区别这个问题的确困扰了不少刚接触 skill 生态的人。我的理解是这样的agent 是大模型自主决策的运行时skill 是注入给 agent 的领域行动手册。一个 agent 决定在什么情境下启动哪个 skill然后根据 skill 里的流程走完任务。skill 更像是给 agent 用的“专业工具包”而不是 agent 本身。举一个直观的例子。我现在的项目配置里同时挂了几个 skillsecurity-audit-skill、code-review-skill、location-based-research-skill。面对用户的问题agent 先判断应该用哪个工具包或者组合用几个工具包。一旦决定使用 security-audit-skill它就按 skill 里的四阶段流程跑信息收集、自动扫描、定向深挖、报告生成。如果把 skill 写成一个很长的 promptagent 只是“看了一遍”执行起来自由度很高容易跑偏但如果 skill 是带脚本、带规则文件、带输出模板的完整工具包agent 的执行路径就被约束在可控范围内产出内容也稳定得多。所以在我看来skill 的真正价值是“给 agent 装上了一个可执行、可复用的流程模块”让复杂任务的执行变得像调用函数一样有确定性。另外提一点不同平台的 skill 生态在接口上会有点不一样但核心思路相通。无论你在哪个生态里试玩SKILL.md 这个思路都值得借鉴。先写触发条件再定义编排流程再挂工具和模板这套方法论切到哪个平台都成立。7. 最后一点经验小结这个 skill 做到第三版我的心态已经从一开始的“能不能让 AI 帮我干活”变成了“怎么让 AI 干得比我预想的更稳”。回看整个过程有几件事如果重来一遍我一定会更早做把触发条件写严格、把规则文件按语言分类、给报告模板定型——这三件小事决定了 skill 的使用体验是玩具还是生产力工具。如果你准备试着自己写一个 security-audit-skill我的建议是先别铺太大拿一个最小的仓库跑通“信息收集 → 自动扫描 → 定向深挖 → 报告生成”这个闭环再扩展。开局阶段最忌讳的是在 SKILL.md 里塞一大堆规则结果 AI 根本没有能力按这个流程真正执行。小步快跑把每一环都跑出可靠结果再逐步叠加规则和工具这样的 skill 才是能够真正进入你日常工作流的东西。SKILL.md
返回列表