ARTICLE DETAIL

资讯详情

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

从零构建 security-audit skill:把安全审计技能封装进 AI 编程助手

从零构建 security-audit skill:把安全审计技能封装进 AI 编程助手 事情要从一次代码评审说起。我用 AI 编程助手审一个支付相关的 Python 服务它前后跑了十几分钟最后给出的结论是“检测到用户输入未经严格验证存在安全风险建议对相关接口进行修复。”这话没有任何毛病但带过安全工作的人都清楚这种结论等于没说。审计的价值从来不在于“复述一句安全口号”而在于知道该在哪一层去挖问题、用什么手法验证它是不是真的可利用、挖到什么程度就可以下结论以及最关键的——如何按业务影响把一堆发现排好优先级。这些专业经验恰恰是通用大模型最缺的东西。所以当 “skill” 这个词在 AI 编程工具圈里突然火起来配合着 codex skill、claude skill、opencode skill 这些热词刷屏时我第一反应不是赶时髦而是想到了一个很实际的问题既然 skill 能把“专业技能”封装进 AI 助手那我能不能把一整套安全审计方法论打包成一个 security-audit skill让 AI 助手从“安全名词复读机”升级成真正能上手干活的“初级审计员”经过这段时间的折腾我可以说这件事不但能做而且做出来的效果比我想象中好很多。这篇就来完整拆解一下我是怎么从零设计、编写、调试一个安全审计 skill 的。1. 先搞清楚 skill 到底是个什么东西在动手写 security-audit skill 之前我花了不少时间研究最近这一波 skill 热背后的机制。不把这个底层逻辑理顺写出来的 skill 大概率只是个“长得像 prompt 的文件夹”。1.1 从一堆热词看 skill 的爆发为什么编程工具都在搞 skill最近你只要打开任何 AI 编程相关的社区满屏都是 skillworkbuddy skill、ponytail skill、codegraph skill、vue-best-practices skill、book to skill、tscircuit skill……甚至连“数学建模 skill”“PPT skill”“会议纪要 skill”都出来了。这个现象背后有一个很直接的原因纯靠对话调教 AI 做复杂专业任务实在太累了。你让 AI “帮我审一下代码安全”它只能靠通用常识硬猜。你得在每一次会话里反复解释什么是敏感数据、什么是越权、输出格式要怎样它才能勉强接近你想要的效果。一旦换了会话、换了项目这些调教全部归零。skill 要解决的就是这件事把“怎么干某个专业活”的完整流程、知识、工具调用规范固化成一个可复用的技能包AI 助手在需要的时候自动加载不需要你每次重新讲一遍。1.2 skill 的本质一段带“操作规范”的专业技能注入包从实现角度看目前主流编程助手对 skill 的实现大同小异。核心是一个带 YAML frontmatter 的 Markdown 文件通常叫 SKILL.md里面写清楚这个技能的名称、触发描述、具体操作流程和输出要求。旁边还可以附带 scripts 目录放可执行脚本、references 目录放参考资料、assets 目录放模板或静态资源。我理解 skill 的本质就是三层东西的打包知识层这个领域有哪些关键概念、常见误区、判断标准让 AI 知道“什么是对的”。流程层做这件事先干什么后干什么每一步产出什么让 AI 知道“怎么干活”。工具层需要调用哪些外部命令、脚本如何解析结果让 AI 真正“动起手来”。普通 prompt 只覆盖了知识层的很小一部分而 skill 把三层都打包了。这是它和“一段很长的提示词”最根本的区别。1.3 skill、prompt、插件、agent 到底有什么区别很多刚开始接触的朋友会把这几个概念搞混我用大白话总结一下。概念本质打个比方Prompt 提示词一段对话指令你口头交代一句“帮我把客厅打扫一下”Skill 技能包知识 流程 工具的固化包一本《保洁操作手册》附带扫把说明书和清洁剂配比表插件 / MCP 工具给 AI 提供外部工具能力给保洁员配吸尘器、拖把、消毒柜Agent 代理能自主规划、循环执行任务的智能体一个“看到客厅乱就自己决定先扫哪、用哪个工具、干完再检查一遍”的保洁主管skill 不是 agent它更像 agent 的“专业技能库”。一个 agent 可以挂多个 skill在遇到不同类型任务时选择调用对应技能。所以就有了“skill 和 agent 的区别”这种热搜问题简单说agent 是执行者skill 是执行者脑海里的“专业操作规范”。搞清楚这些之后我就可以放心的开始设计 security-audit skill 了。2. 安全审计这件事为什么值得做成一个 skill很多人可能觉得安全审计不就是拿扫描器跑一跑然后看看报告吗直接让 AI 调用几个扫描命令不就行了何必搞一个 skill我实际做下来发现事情远没那么简单。2.1 传统安全审计的三座大山先说传统方式的痛点。第一个痛点是“工具分散、结果割裂”。一个像样的审计流程至少需要覆盖源码静态扫描、依赖漏洞检查、密钥泄露检测、基础设施配置核查。semgrep 管源码规则、bandit 管 Python 安全隐患、npm audit 管前端依赖、trivy 管容器和 IaC 配置、gitleaks 管硬编码密钥……每个工具的输出格式都不一样人工要把这些结果汇总成一份统一的报告本身就是个不小的体力活。第二个痛点是“经验沉淀太难”。一个资深安全工程师看到一段代码能敏锐地意识到“这个文件上传接口虽然做了类型校验但没限制文件名可能能传 .html 导致存储型 XSS”。这种经验是多年踩坑积累出来的。但团队的其他人无法快速复用这套判断逻辑每次审计都像从零开始。第三个痛点是“误报处理消耗大量时间”。扫描工具不理解的业务上下文AI 也不理解最终还是要靠人来判断。这个过程极其枯燥。2.2 AI 助手做审计的现状会背书不会干活通用 AI 编程助手其实已经具备一部分安全知识比如它能说出 SQL 注入是怎么回事、OWASP 是什么。但你让它真的去审计一个项目时它的问题非常明显不知道从哪里开始。一份代码仓库摆在面前有后端接口、有前端页面、有数据库迁移脚本、有 Dockerfile、有 CI 配置。AI 如果没有任何审计流程约束它大概率会东看一眼西看一眼最后凭感觉挑几个“看起来有问题”的地方说一通。它不会系统性地覆盖认证鉴权、输入验证、敏感信息保护、依赖安全、配置安全这几个维度也不会给出可验证的利用路径分析。这不是 AI 笨而是我们没给它“审计员的工作手册”。2.3 把方法论变成 skill一次封装处处复用skill 恰好补上了缺的那本“工作手册”。我当时的设想是把安全审计的完整方法论——审计范围定义、分维度检查清单、工具调用规则、报告输出模板——全部固化到一个 skill 里。这样不管是审计 Python 后端还是 JavaScript 前端AI 助手都能在加载 skill 后按同一套高标准的流程干活。做出来的效果就是你只需要告诉 AI “用 security-audit skill 审一下当前仓库”它会自动规划审计顺序、依次调用脚本扫描、对结果做交叉分析、最后输出一份结构化的 Markdown 报告。这比零散的“帮我看看有没有安全问题”靠谱太多了。3. 设计 security-audit skill 的目录结构与核心文件明确了目标接下来就是动手写。这一节我先讲整体框架怎么搭这是整个 skill 的地基。3.1 先想清楚边界这个 skill 管什么、不管什么很多人写 skill 最大的问题是贪多嚼不烂。想把所有安全知识都塞进去结果 SKILL.md 一万多字AI 根本读不完最后反而啥也没学会。我在动手前先划了一条清晰的边界。这个 security-audit skill 的定位是“软件项目的白盒安全审计辅助工具”主要服务对象是开发团队和负责代码安全评审的工程师。它负责以下内容对指定目录的源代码进行系统性安全审计覆盖输入验证、认证授权、敏感数据保护、依赖安全、配置安全等核心维度调用内部扫描脚本对关键风险点做自动化验证输出结构化、可按严重级别排序的审计报告。它不负责的事情我也写清楚了不做未授权的外部渗透测试不生成可直接用于攻击的利用代码不替代人工对业务逻辑漏洞的最终判断。这个边界既是对使用者负责也是为了让 AI 在审计时保持“防御者视角”而非“攻击者视角”。注意安全审计是防御性的工程实践。写这个 skill 的初衷是帮团队发现并修复自己项目里的问题而不是用来研究如何突破别人系统的防护。3.2 目录结构SKILL.md、scripts、references 如何分工我最终采用的目录结构是这样的我会在后面逐步解释每个部分的作用security-audit-skill/ ├── SKILL.md # 技能主文件元信息 操作流程 输出要求 ├── scripts/ │ ├── run_python_audit.sh # 调 bandit 扫描 Python 代码 │ ├── run_js_audit.sh # 调 npm audit / eslint-plugin-security │ ├── run_secret_scan.sh # 调 gitleaks 检测硬编码密钥 │ ├── run_dep_audit.sh # 调 pip-audit / npm audit 检查依赖漏洞 │ └── summarize_report.py # 把工具输出裁剪成 AI 可读的摘要 └── references/ ├── audit-checklists.md # 分维度的检查清单 ├── owasp-top10-notes.md # OWASP Top 10 核心条目与审计要点 ├── language-guidance.md # Python/JS/Go 各语言审计重点 └── report-template.md # 审计报告模板这个结构的设计逻辑很简单SKILL.md 是 AI 每次加载 skill 时最先读取的文件所以它必须短小精悍只讲流程和规则把大段的知识性内容都甩到 references 目录里让 AI 按需查阅。scripts 目录里的脚本则负责替代 AI 不擅长的“精确计算”部分——比如正则匹配密钥格式、统计依赖版本——因为这些事交给脚本比交给大模型靠谱得多。3.3 SKILL.md 的 frontmatter 与指令正文怎么写才不被 AI 无视SKILL.md 是 skill 的灵魂而 frontmatter 又是 SKILL.md 里 AI 最先看到的部分。根据我的经验这个部分写得好不好直接决定 AI 会不会在合适的时机主动加载这个 skill。frontmatter 至少要包含两个字段name 和 description。description 尤其重要它不是写给人看的而是写给 AI 的“触发索引”。AI 在决定要不要加载某个 skill 时靠的就是 description 里的关键词匹配。所以我把 description 写得非常直白--- name: security-audit description: 对代码仓库执行系统化安全审计覆盖源代码漏洞、依赖风险、密钥泄露、不安全配置等维度输出结构化审计报告。当用户要求做安全审计、代码审查、漏洞扫描、安全检查、渗透测试前置评估时使用此技能。 ---这个 description 我调了好几版。早期写得比较文艺“帮助用户分析代码中的潜在安全弱点”结果 AI 经常等到用户明确说“用安全技能”才加载。后来改成上面这版直接枚举动作场景和触发动词加载率立刻上来了。SKILL.md 的正文部分我坚持“流程优先规则清晰”的原则。全文控制在三四百行以内核心结构是Role设定 AI 的身份——“资深应用安全审计工程师”。Audit Process规定审计步骤的顺序比如先收集项目结构再按依赖、源码、配置、密钥的顺序逐一扫描。Tool Usage明确哪些场景必须调用脚本不能只靠推理。Output Format规定报告的目录结构和严重级别定义。4. 知识库与检查清单skill 的灵魂在 references如果说 SKILL.md 是骨架那 references 目录就是血肉。安全审计的专业深度全靠这些知识文件撑起来。4.1 把 OWASP Top 10 翻译成 AI 能执行的审计指令OWASP Top 10 是 Web 安全领域绕不开的参考标准但直接把它的原文扔给 AI 是没用的。那份文档是给人看的满是背景分析和趋势讨论AI 看了也不知道“下一步该做什么”。我花了很大功夫把 OWASP Top 10 2021 的核心条目“翻译”成可执行的审计指令。比如 A03: Injection 这一条我不写“注入是一种严重的安全风险”而是写检查所有 SQL 查询语句是否使用了参数化查询或 ORM 预编译机制检查命令执行函数如 Python 的 os.system、subprocess 的 shellTrue是否接收到未经白名单校验的外部输入检查 NoSQL 查询是否对操作符注入如 $where、$gt做了输入过滤对发现的可疑点要求 AI 回溯输入数据的完整传播路径判断是否真的可控。同样的方法我把 A01 访问控制、A02 加密失败、A05 安全配置错误、A06 易受攻击和过时的组件等条目都改造成了带“检查动作”的条款。这份 owasp-top10-notes.md 是整个 skill 里最核心的参考资料。4.2 语言差异Python、JavaScript、Go 的审计重点完全不同单一的安全清单没法覆盖所有技术栈所以我又写了一份 language-guidance.md专门区分不同语言的高风险模式。以 Python 为例我要求 AI 重点看eval/exec 使用、反序列化pickle.loads、SQL 拼接、不安全的文件操作路径。以 JavaScript/TypeScript 为例重点则是原型链污染、XSS 输出点dangerouslySetInnerHTML、innerHTML、依赖供应链风险、不安全的 URL 重定向。Go 的重点又不一样并发竞争条件、不安全的模板渲染、命令注入、panic 恢复缺失等。在这份文件里我不只写“重点看什么”还会附上“典型代码样例”和“误报对照”。比如 Python 的 subprocess 也不是用了 shellTrue 就一定是漏洞如果参数是硬编码常量而非用户输入那风险等级就非常低。有了这些对照AI 在判断时就能减少“一刀切”式的误报。4.3 输出模板让审计报告可直接用于工单流转references/report-template.md 严格定义了审计报告的格式。我见过太多 AI 生成的安全报告要么写得像教科书要么问题列表和修复建议对不上号。为了让报告真正可用于团队协作我设计的模板强制要求每个发现项包含六个要素发现项要素说明漏洞类型对应 OWASP 或 CWE 分类严重级别严重 / 高危 / 中危 / 低危 / 信息文件位置文件路径 行号问题描述用业务语言说清楚是什么问题利用场景什么条件下可能被利用产生什么影响修复建议给出具体的、可落地的修复方案模板里还定义了“严重级别判定规则”。严重通常指可直接导致远程代码执行、大规模数据泄露或完全越权高危指可能导致敏感数据泄露或特定条件下的代码执行中危指影响有限但真实存在低危则是代码风格层面的安全改进建议和加固项。别小看这份模板的作用。AI 一旦严格按照这个结构输出报告可以直接拆成工单分配给对应开发人员不需要人工二次整理效率提升非常明显。5. 让 skill 会“动手”审计脚本与工具链知识库充其量只能让 AI “会想”安全审计要真正落地还得让 AI “会做”。这个“做”就靠 scripts 目录里的工具链。5.1 选哪些工具从静态扫描到依赖检查我在 scripts 里封装了一系列真实可用的开源安全工具。选型原则很简单优先选“有明确退出码、输出可解析、社区维护活跃”的工具。BanditPython 源码安全扫描器专门检测常见安全隐患适合审计 Python 项目ESLint eslint-plugin-security前端 JavaScript 安全规则集能查出危险函数调用和不安全的正则表达式npm audit / pip-audit检查依赖库的已知 CVE 漏洞Gitleaks扫描仓库历史记录和当前文件中的敏感信息API key、密码等Trivy检查 Dockerfile、IaC 模板和容器镜像的安全配置与漏洞Semgrep通用静态分析工具我会在脚本里内置几条自定义规则针对命令注入、硬编码密钥和危险反序列化做重点扫描。这个组合覆盖了“源码 依赖 配置 密钥”四个安全审计最关键的层面。当然具体装哪个可以按项目情况裁剪不需要一次全上。5.2 脚本设计AI 调工具和人调工具的逻辑不一样给 AI 用的脚本设计思路和给人用的命令行工具完全不一样。人用工具时能自己处理异常、看完整输出AI 不行AI 面对一个脚本只会按照 SKILL.md 里约定的方式去调用然后读取输出。所以我的每个审计脚本都遵循几条硬性约定执行路径必须由脚本自身解析不能依赖“当前工作目录”因为 AI 在不同项目里执行时工作目录可能不同输出统一写成 JSON 格式写入脚本同目录下的输出文件方便后续解析脚本开头要检测依赖工具是否安装缺失时直接返回明确提示不能抛出一堆看不懂的堆栈超时控制在 5 分钟内避免耗时过长拖死 AI 的整个审计流程。举个例子run_python_audit.sh 的核心逻辑大致是这样的#!/usr/bin/env bash # 用法: bash run_python_audit.sh 项目目录 输出目录 PROJECT_DIR${1:-.} OUTPUT_DIR${2:-./audit-output} mkdir -p $OUTPUT_DIR if ! command -v bandit /dev/null; then echo {\status\: \error\, \message\: \bandit not installed\} $OUTPUT_DIR/python_audit.json exit 1 fi bandit -r $PROJECT_DIR -f json -o $OUTPUT_DIR/python_audit_raw.json -q || true # 用 summarize 脚本裁剪输出保留最关键的发现项 python3 scripts/summarize_report.py \ --input $OUTPUT_DIR/python_audit_raw.json \ --output $OUTPUT_DIR/python_audit_summary.json \ --max-items 30这里有个细节bandit 扫描的结果可能非常长几千个 issue 直接塞给 AI 会把上下文窗口撑爆。所以我写了一个 summarize_report.py把所有报告先做一轮“裁剪”——按严重级别排序保留高危超危的规则命中并过滤掉明显误报的模式。AI 读到的只是精简后的摘要但已经足够支撑后续分析。5.3 工具结果的解析把扫描报告变成 AI 能读懂的上下文脚本跑完不是终点真正的难点在于“怎么让 AI 理解扫描报告”。我的做法是在 SKILL.md 里明确规定AI 拿到 summarize_report.py 输出的 JSON 后必须先结合 references/language-guidance.md 里的“误报对照”做一轮人工判断标注哪些发现是可信的、哪些需要进一步验证再进入报告撰写环节。比如 gitleaks 报告里出现一个疑似 GitHub Token 的字符串AI 需要先看这个字符串所在文件是什么。如果是测试 fixture 目录下的样例数据几乎可以确定是误报如果是 .env 文件且该文件被提交进了 Git 历史这就是实打实的高危问题。这种“工具扫描 AI 研判”的配合模式是整个 skill 价值最大化的关键。纯靠工具会产生大量误报纯靠 AI 会漏掉深度问题两相结合才能达到一个比较理想的平衡点。6. 在主流编程助手里的安装与调试实录一个 skill 写得好不好只有装进实际工具里跑一遍才知道。我简单聊聊在几种主流编程助手里的安装和调优经验。6.1 三种装法Claude Code、Codex、opencode 的 skill 目录不同工具的 skill 机制大同小异本质上都是“把 skill 文件放到某个会被扫描的目录”。以我这段时间的实测经验Claude Code用户的全局 skill 放在~/.claude/skills/下项目级 skill 放在项目根目录的.claude/skills/下。放好后不需要额外配置AI 会自动发现该目录下的 SKILL.md。Codex新版 Codex 引入了类似的技能机制需要按官方文档把 skill 包放到对应目录。不同版本的安装路径有变化建议以官方文档为准。opencode支持通过命令或手动目录方式安装 skill。我一般把 security-audit-skill 整个目录复制到其 skills 目录下然后在对话里用 /skills 命令确认加载状态。如果你是第一次接触 skill我建议先在 Claude Code 里试。它的 skill 机制相对成熟社区示例也多跑通一个 Demo 能帮你快速理解整个概念。等你理解了原理再迁移到其他工具也就是几分钟的事。6.2 调试 skill 的核心手段看它到底加载了什么skill 调试最头痛的问题就是“AI 好像没加载我的 skill”。遇到这种情况先不要急着改内容按顺序排查确认目录位置正确SKILL.md 在 skill 包根目录下不是嵌在子文件夹里。检查 frontmatter 的格式是否合法name 和 description 都没写错YAML 解析失败时整个 skill 都可能被跳过。在对话中主动说“使用 security-audit skill 对当前仓库做安全审计”观察 AI 的回复是否引用了 SKILL.md 里的流程要求。在 SKILL.md 里增加一个明显的标记比如在输出报告开头要求写上“审计流程遵循 security-audit-skill 规范 v1.2”如果 AI 写了说明 skill 生效了如果没写那就是没加载成功需要检查目录或名称。还有一个很实用的技巧故意在 references 里埋一个“只有读到这里才知道”的内部暗号比如规定报告结尾必须输出一个特定的校验短语。AI 如果输出了这个短语说明它确实完整读取了 references 文件而不只是读了 SKILL.md 就开始自由发挥。6.3 实测效果与常见翻车场景经过几轮迭代我用这个 skill 在几个开源项目上做了实测。效果最明显的是对依赖漏洞和硬编码密钥的检出率之前让 AI 自己看它基本发现不了藏在 Git 历史里的密钥挂上 skill 后脚本自动跑 gitleaksAI 再对结果研判很快就锁定了几个需要立即处理的高危泄露点。模板化报告带来的提升也超出预期。审计报告直接按严重级别输出问题清单每一条都带文件行号和修复建议团队成员可以对照着直接改省掉了来回沟通的成本。当然翻车场景也不少我遇到的典型问题有三个第一个是上下文膨胀导致审计中断。项目一大的时候AI 会尝试把整个代码库的关键文件都塞进上下文很快就把窗口占满。后来的对策是在 SKILL.md 里明确要求 AI 先跑脚本拿报告再针对报告里的高风险文件做定向阅读而不是全库扫描。同时给脚本加了输出长度上限超长的报告先摘要再读。第二个是工具版本不一致导致脚本报错。比如某些环境下 bandit 的 JSON 输出字段名有差异。后来我在脚本里加了版本检测对不同的字段结构做了兼容处理遇到未知结构时返回错误信息而不是硬解析。第三个是 AI 对“严重级别”的判断飘忽不定。同一个问题有时候报高危有时候报中危。我最后是通过在 report-template.md 里增加“必须引用判断依据”的硬性要求来缓解的——每个严重级别标注后后面必须跟一条具体的理由比如“该接口无需认证即可访问并返回用户手机号符合高危标准”。这样一来AI 的判断有迹可循人工复核也更快。7. 写在最后skill 的迭代是一辈子的事这套 security-audit skill 我现在已经迭代了三个版本最大的感触是skill 不是写一次就完事的交付物而是要跟着项目、工具、威胁环境持续更新的活文档。我的建议是先从一个最小的可用版本开始别一上来就想写个覆盖所有场景的“完美技能包”。先把 SKILL.md 和几个核心脚本搭起来跑通一个项目的审计再根据实际翻车的地方逐步补充 references比如“这个框架的鉴权方式很容易被误判”“这种云厂商的密钥格式 gitleaks 认不出来需要加正则”……每一轮真实的审计都会给 skill 带来一批宝贵的迭代素材。如果你正在用 AI 编程助手做日常开发又对代码安全有要求我强烈建议你花一天时间自己搭一个这样的 skill。不一定要完全照搬我的设计完全可以只保留一个 SKILL.md 加两个审计脚本先解决“依赖漏洞没人查”“密钥不小心提交进仓库”这种高频问题。等跑顺了再往里面加更多维度的检查。最后分享一个经验性的判断在 AI Agent 的使用体验里“会调工具的 AI”和“有专业技能的 AI”之间隔着的就是一份精心编写的 skill。安全审计这个领域尤其如此因为专业工具的产出只是中间过程最终的价值来自你怎么解读它、组织它、决策它。把这份解读和组织能力沉淀成 skill你团队里的每一个人就都拥有了一个随时待命、不会累、不会忘的安全审计搭档。
返回列表