这阵子研究 AI Agent 的 skill 机制,顺手做了一个专门干安全审计的security-audit-skill。过程比我想象中有意思,踩坑也比想象中多。起因很直接:把“帮我审查这个仓库的安全性”丢给大模型,它会列出一堆 SQL 注入、硬编码密钥之类的经典问题,但真拿去落地,你会发现它既不知道审计边界划在哪,也不会按风险等级排序,更不会给出一条带证据链的修复建议。不是说模型不行,而是缺少一套“按安全审计流程办事”的约束。
这篇文章把我从零设计这个 skill 的完整思路、目录结构、SKILL.md 写法、配套脚本和实测过程中的坑全部拿出来。适合正在折腾 Claude、Codex、OpenCode 这类支持 skill 机制的 Agent 朋友,也适合想给团队审计流程引入 AI 助手的工程师。照着我这套走一遍,AI 的产出会从“聊天式回答”变成“结构化审计报告”。
1. 为什么通用 AI 做不了安全审计:从一句“帮我审代码”说起
很多人第一次尝试用 AI 做安全审计,都是从那句“帮我审一下这个项目”开始的。第一次跑完,你会觉得“哇,它居然能指出 SQL 注入”,再多跑几次就会发现它离真正的安全审计还差得很远。
1.1 无边界、无标准、无证据链:对话式审计的三宗罪
先说我观察到的三个核心问题。
第一是审计范围完全随机。同样一句“审一下这个项目”,它这次可能只看了 Python 代码里的eval(),下次重点落在前端dangerouslySetInnerHTML,再下次又跑到 Dockerfile 里去说latest标签不好。没有明确指令的话,模型只能靠训练数据里的经验盲猜,猜中的范围就是你得到的全部结果。而安全审计最怕的就是覆盖面失控——你永远不知道它漏了哪块。
第二是缺少行业标准锚点。专业审计师开口就是 OWASP Top 10、CWE 编号、CIS Benchmark,但通用对话里的 AI 很少主动把这些框架套上去。你说“查一下注入”,它可能只查了 SQL 注入,完全忽略命令注入、LDAP 注入、模板注入这些变种。不是它不懂,是你没告诉它“按这个标准体系来”。
第三是结论没有证据链。它会甩给你一句“这段代码存在 SQL 注入风险”,但你追问“入口参数在哪?污点数据流经过哪几层函数?”它就支支吾吾了。安全审计的结论必须能被验证,能追溯到具体的污点源、传播路径和危险 sink。没有证据链的审计结论,在正式报告里等于零。
1.2 安全审计到底该审什么:能力边界先画清楚
做 skill 之前,我先逼自己把“安全审计”这个范围缩小到可执行的程度。安全审计在不同上下文里含义差别巨大:测 Web 应用、审 Node.js 项目、查云上配置、扫容器镜像,完全是四套东西。如果不划边界,skill 就会变成什么都会一点、什么都不精的缝合怪。
我给这个 skill 定的初始范围是四类:
- 源代码缺陷审计:注入、认证失效、访问控制缺失、敏感信息泄露等代码层面问题。
- 依赖与供应链审计:已知 CVE 版本、过度宽松的版本范围、许可证风险。
- 配置风险审计:环境变量、不安全的默认配置、调试开关未关闭、硬编码凭据。
- 容器与基础设施配置审计:Dockerfile 最佳实践、权限过高、镜像版本漂移。
四类之外的东西,比如需要真实环境交互的渗透测试、社会工程学、物理安全,我在 SKILL.md 第一行就写明“不属于本技能范围”。这个动作特别关键——明确的否定清单和正向能力清单一样重要,它防止 Agent 跑到它不该碰的领域里去。
1.3 用一张范围矩阵把审计对象钉死
为了让模型在执行时不迷惑,我在 assets 里放了一张范围矩阵表,每次审计前先让模型自检“当前对象的类型对应哪一行”。这张表也直接决定了后续的检查计划怎么生成。
| 审计对象 | 覆盖检查项 | 常见产出 | 不属于本技能范围 |
|---|---|---|---|
| 源代码 | 注入、XSS、SSRF、路径穿越、反序列化、硬编码密钥、越权逻辑 | 缺陷清单、CWE 映射、修复建议 | 绕过真实 WAF、利用漏洞拿权限 |
| 依赖文件 | 已知 CVE、版本过旧、恶意包特征 | 漏洞包清单、升级建议 | 供应链投毒溯源 |
| 配置文件 | 弱口令、调试模式、错误的安全头、敏感凭据泄露 | 配置风险清单 | 合规审计中的法律条款解读 |
| 容器镜像 | 基础镜像版本、root 用户运行、高危软件包、权限过大 | 镜像检查报告 | 运行时入侵排查 |
这张表还有一个隐藏作用:它让模型在审计开始前先“确认对象类型”。比如用户说“审一下这个项目”,模型必须先判断这是一个纯前端项目、后端项目还是包含了 Dockerfile 的完整仓库,再决定启用哪几行检查项。这比让模型一股脑把所有规则都跑一遍要省掉大量无效输出。
2. Skill 的本质:给 AI 一份岗位说明书和一个工具箱
先说清楚 skill 到底是什么,否则后面的实操容易看不懂。
2.1 一个 Skill 的最小目录长什么样
你可以把 skill 理解成一个“能力包”:一个带说明文档、检查清单、模板和辅助脚本的目录。Agent 在运行时根据用户请求的关键词动态加载它,而不是把所有指令都写死在一段超长的系统提示词里。
我的security-audit-skill目录结构长这样:
security-audit-skill/ ├── SKILL.md ├── assets/ │ ├── audit_scope_matrix.md │ ├── threat_dictionary.md │ ├── severity_matrix.md │ └── report_template.md ├── rules/ │ ├── sql_injection.md │ ├── hardcoded_secrets.md │ └── unsafe_deserialization.md └── scripts/ ├── collect_context.sh ├── run_semgrep.sh └── parse_semgrep_to_md.pySKILL.md是技能的主文件,相当于岗位说明书。assets放参考文档和模板,模型在需要时按文件名引用。rules是针对某类漏洞的专项检查指引。scripts是给 Agent 准备的工具脚本,用于收集上下文、跑扫描器、格式化结果。
这里要强调一点:skill 不是插件,不需要代码执行环境。它本质上是“文本指令 + 资源文件”的集合,Agent 读取里面内容并按约定执行。脚本是锦上添花,真正驱动行为的是SKILL.md里写清楚的流程。
2.2 触发描述词:写错了 Agent 根本不会加载
skill 的加载依赖于SKILL.md开头的描述字段,这个字段我花了好多轮才调好。写得太宽,用户聊日常也触发;写得太窄,用户真正要审计时它反而沉默。
我最终的描述字段是这么写的:
Name: security-audit Description: 当用户要求审查代码安全性、扫描依赖漏洞、检查配置风险、审计容器镜像,或要求执行安全审计、代码安全评估、漏洞分析的时候使用。 该技能适用于源代码缺陷审计、依赖与供应链审计、配置风险审计三类任务。 不适用于需要真实网络交互的渗透测试、应急响应、病毒分析等场景。注意最后一行的否定描述。很多人在写 skill 描述时只会写“什么时候用”,忽略了“什么时候不用”,结果 Agent 在用户聊“渗透测试”的时候也把安全审计 skill 拉出来用。加一行否定,能减少大量错误触发。
2.3 为什么这件事不适合全部压进系统提示词
有人会问:既然就是这么一段指令,为什么不直接复制到系统提示词里?我之前也是这么想的,后来被现实教育了。
第一次尝试把安全审计的全部要点塞进系统提示词,结果上下文预算直接爆炸。一个包含 OWASP 检查项、CWE 映射、审计流程、报告模板的完整提示词,随便写写就 8000 token。系统提示词一旦太长,模型在真正审计代码时反而“注意力稀疏”,重要规则被淹没在长篇大论里。
skill 机制的优势在于按需加载:用户提出审计需求,Agent 才读取SKILL.md;读取后再按需引用rules/下的专项文件。平时不占上下文,审计时又能拿到完整的专业指引。这就好比一个工具箱放在储藏室,接单时才打开,不用一直背在身上。
另外,skill 的目录和脚本天然适合 Git 版本管理。改了一个检测规则,提交一次 commit,比维护一段不断膨胀的提示词清晰得多。团队协作时也可以把 skill 目录作为代码库的一部分,审计规则随项目仓库一起走,版本对齐不再是问题。
3. security-audit-skill 的边界设计:先定义“不审计什么”
我设计这个 skill 时最大的心得是:边界比能力更重要。一个没有边界的审计技能,会让模型在错误的方向上浪费大量上下文。
3.1 能力范围矩阵:各类对象各有各的检查项
我把四类审计对象分别细化成可操作的检查列表,落在assets/audit_scope_matrix.md里。模型审计某类对象时必须对应到具体检查项,不允许天马行空。
以“源代码缺陷审计(Python/JavaScript/Java)”为例,矩阵中列出的核心检查项包括:
- 注入类:SQL 拼接、命令执行拼接、模板字符串注入。
- 认证与授权:弱口令硬编码、token 生成逻辑缺陷、越权接口缺少鉴权。
- 敏感信息:私钥、API Key、数据库密码写死在代码中;日志打印敏感字段。
- 不安全反序列化:
pickle.loads、eval()、ObjectInputStream等。 - 文件操作:任意文件读取、路径穿越、危险文件上传后缀。
每一条检查项都标注了对应的 CWE 编号(比如 SQL 注入是 CWE-89,硬编码密钥是 CWE-798),并要求模型在报告里写出 CWE 映射。再加上一条硬性规定:每条发现必须包含文件路径、行号和完整证据片段。没有这三样,一律不算数。
3.2 第一强制步骤:先资产盘点,再下审计计划
我观察到一个现象:AI 直接审计时,总是立刻钻到第一个看到的文件里开始分析。它不会先花时间搞清楚这个仓库的结构、语言分布、高风险模块在哪里。结果就是它在一个静态页面上翻了半天,真正的支付模块反而一眼没看。
所以我把“资产盘点”设为 SKILL.md 中审计流程的第一步,并且写成强制步骤:在产出任何漏洞结论之前,必须先输出资产清单和审计计划。
资产盘点需要包含这些内容:
- 仓库根目录结构(最多两层,防止模型一头扎进 node_modules)。
- 编程语言与框架占比,识别主要技术栈。
- 入口文件与路由文件(如 Flask 的
app.py、Express 的app.js、Spring Boot 的controller目录)。 - 依赖清单位置(
requirements.txt、package-lock.json、pom.xml)。 - 配置文件位置(
.env、config/*、application.yml)。 - 高风险模块候选(涉及上传、认证、支付、用户数据导出的目录)。
完成这一步后,模型还要写出“本轮审计聚焦清单”:比如“因为这是一个 Flask 电商仓库,本轮审计优先覆盖订单模块、用户认证模块、支付回调接口”。有了这个聚焦清单,模型后续的逐文件审计就不会漫无目的。
3.3 严重程度矩阵与报告模板:逼着 AI 给证据链
AI 给的漏洞评级经常令人迷惑,同一段代码换个问法,两次评级能差两级。我在assets/severity_matrix.md里定义了一套简单的定级标准,强制模型按这个标准执行。
| 严重级别 | 判定条件 | 结论要求 |
|---|---|---|
| Critical | 无需认证即可利用,或可直接导致远程代码执行/数据全部泄露 | 必须有完整污点数据流证据 |
| High | 需要低权限账号即可触发的注入、越权、任意文件读取 | 必须有真实调用链和触达路径 |
| Medium | 需要特定条件才能触发的配置缺陷、敏感信息泄露、版本漏洞 | 必须有触发条件和影响范围 |
| Low | 加固建议、最佳实践偏离、代码风格导致的安全隐患 | 必须说明为什么是低风险 |
定级标准只是第一步,真正把报告输出稳定下来的是报告模板。我在assets/report_template.md里规定了一个标准结构,模型每次审计完必须套用这个结构输出:
# 安全审计报告 - <项目名> ## 审计范围 <本次覆盖的模块、文件、依赖清单> ## 风险概览 | 严重级别 | 数量 | 说明 | | ... | ## 关键发现 ### 1. <发现标题> [CWE-<编号>] [严重级别] - 文件与行号:<路径:line> - 证据片段:<代码或配置原文> - 触发条件:<如何触达、需要什么角色> - 修复建议:<具体方案,含代码示例> ## 依赖风险 <SCA 扫描结果摘要> ## 加固建议 <适合快速落地的配置或流程改进>有了模板,模型的输出稳定性有了质的提升。每次审计报告都是同样的结构,我后续做自动化解析和生成漏洞台账都方便了。
4. 从零搭建:SKILL.md、审计清单和辅助脚本的完整落地
这一节是最实操的部分。直接给一套可以照着抄的搭建方案。
4.1 第一步:写一份“岗位说明书”式的 SKILL.md
SKILL.md是整个 skill 的核心。我采用的是“职责 + 禁止动作 + 固定流程”三段式结构,让模型知道它该做什么、不能做什么、按什么顺序做。
核心内容我提炼如下:
# Security Audit Skill ## 职责定义 你是一名资深安全审计工程师。你的任务是对目标仓库执行程序化、可验证的安全审计。 审计范围包括源代码缺陷、依赖漏洞、配置风险与容器镜像配置。 你只报告有证据链支撑的发现,拒绝猜测。 ## 禁止动作 - 禁止修改被审计项目的任何源文件、配置文件和依赖文件。 - 禁止执行任何以写为目标的操作命令,所有脚本只允许输出到临时目录。 - 禁止在没有证据的情况下给出漏洞结论,至少需要文件路径+行号+证据片段。 - 禁止对审计对象发起网络请求或占用大量资源的操作。 ## 审计流程 在开始审计前先输出:审计对象类型、资产清单、聚焦文件列表、采用的检查标准。 然后按以下顺序执行: 1. 资产盘点:使用 collect_context.sh 或等效手段获取目录结构和语言占比。 2. 依赖检查:定位依赖清单,核对已知 CVE 情况。 3. 高风险代码路径定位:按威胁字典,优先审计认证、上传、支付、命令处理相关模块。 4. 逐文件深读:对聚焦文件逐行阅读,记录污点源、传播路径、危险 sink。 5. 扫描工具辅助:在环境允许时调用 Semgrep/Trivy,解析输出结果。 6. 总结报告:按 report_template.md 输出结构化报告,每一项发现必须包含严重级别和证据链。 ## 输出要求 报告一律使用 Markdown 格式,遵循 report_template.md。 若某检查项未发现异常,也必须明确写出“该模块未发现异常”,禁止直接跳过。注意“禁止动作”这一段。它解决的是我后面要讲的“审计过程中 AI 乱改代码”的问题。不写死这条,模型在审计时会忍不住给你“顺手修复”。
4.2 第二步:准备威胁字典和检查清单
有了主流程,还需要给模型一本“威胁字典”,不然它只能靠训练数据里的印象来识别漏洞。威胁字典的价值,是把模糊的“注意注入风险”变成精确的“危险函数名单 + 验证步骤”。
我以rules/sql_injection.md为例,展示一条规则长什么样:
# SQL 注入检测规则 ## 触发模式 - 字符串拼接进入 execute/executemany/query 参数 - f-string 或 format 拼接 SQL 语句 - ORM 方法中传入未参数化的原始 SQL ## 典型危险函数 - Python: execute(), executemany(), raw() - JavaScript: query(), run(), prepare().all() - Java: Statement.executeQuery(), MyBatis 的 ${} ## 验证步骤 1. 找到用户可控输入(HTTP 参数、环境变量、文件内容、外部 API 响应)。 2. 追踪输入流经的所有变量,确认是否有 int() 强转、参数白名单、转义函数处理。 3. 确认输入最终进入危险 sink。 4. 记录完整的调用链:入口 -> 中间层 -> sink,作为证据。 ## 误报排除 - 如果输入在进入 SQL 前被参数化查询占位符替代,不算漏洞。 - 如果输入经过 int 强转且目标字段为整数主键,风险降为 Low。每个高危漏洞种类放一个规则文件,加上校验步骤和误报排除逻辑。这一设计直接拉低了模型的误报率,因为它在下结论前必须走一遍“入口-传播-接收器”的完整链路。
4.3 第三步:让扫描工具变成 skill 的“手”
SKILL.md 负责指挥,扫描工具负责执行。我在scripts/里放了几个能辅助 Agent 收集信息的脚本,避免它靠纯阅读去“猜”整个项目。
第一个是收集项目上下文的collect_context.sh:
#!/bin/bash # 用法: ./collect_context.sh /path/to/project PROJECT=$1 echo "== 仓库结构(两层) ==" find "$PROJECT" -maxdepth 2 -type d \ -not -path "*/node_modules*" \ -not -path "*/.git*" \ -not -path "*/dist*" \ -not -path "*/build*" | head -50 echo "" echo "== 语言分布 ==" find "$PROJECT" -path "*/node_modules" -prune -o -path "*/.git" -prune -o -type f -print \ | awk -F. '{print $NF}' | sort | uniq -c | sort -rn | head -10 echo "" echo "== 关键文件检测 ==" for f in "$PROJECT"/.env "$PROJECT"/requirements.txt "$PROJECT"/package-lock.json "$PROJECT"/Dockerfile; do [ -f "$f" ] && echo "FOUND: $f" done第二个是封装 Semgrep 扫描的run_semgrep.sh。我用--output把结果写到/tmp,原则是“所有辅助脚本只允许产生临时文件,不能动项目目录”:
#!/bin/bash # 用法: ./run_semgrep.sh /path/to/project /tmp/output.json PROJECT=$1 OUT=$2 if ! command -v semgrep &> /dev/null; then echo "semgrep 未安装,降级为 grep 模式" grep -rn --include="*.py" --include="*.js" --include="*.java" \ -E "execute\(|eval\(|child_process\.exec|Runtime\.getRuntime" "$PROJECT" \ | grep -v node_modules | head -50 else semgrep scan --json --output "$OUT" "$PROJECT" || true echo "semgrep 输出已写入 $OUT" fi第三个小脚本parse_semgrep_to_md.py把 JSON 结果里最严重的 Top 10 转成 Markdown 片段,方便模型直接粘贴进报告。脚本细节这里不贴了,核心逻辑就是读取 JSON,按extra.severity排序,输出路径、行号、规则 ID 和短描述。
这些小脚本有一个共同原则:降级策略。环境里没有 semgrep 时自动回退到 grep 危险函数名模式,保证 skill 在裸环境下也能跑出基本结果。
4.4 端到端演示:对一段真实示例代码跑一轮审计
拿一个迷你项目演示。假设被审计仓库里有这样的 Python Flask 代码:
from flask import Flask, request import sqlite3 app = Flask(__name__) @app.route("/user") def get_user(): user_id = request.args.get("id") conn = sqlite3.connect("app.db") cur = conn.execute("SELECT * FROM users WHERE id = " + user_id) return str(cur.fetchall()) if __name__ == "__main__": app.run(debug=True)另外在.env里有一行:
DATABASE_PASSWORD = "prod_admin_pwd_2024"AI 加载security-audit-skill后,按我的 SKILL.md 流程,第一步先输出资产盘点:
审计对象类型:Python Flask 应用 关键文件:app.py, .env, requirements.txt 高风险模块候选:/user 接口(外部可控参数直接进入数据库查询) 采用标准:OWASP Top 10 / CWE 映射第二步开始逐文件深读,识别出user_id是污点源,request.args.get("id")是用户可控入口,最终进入conn.execute(...)危险 sink。这时规则sql_injection.md要求模型验证传播路径,它会指出“没有任何参数化处理、没有白名单、直接拼接 SQL”,然后给出 Critical 级别结论。
第三步,它读取.env,识别硬编码数据库口令,按hardcoded_secrets.md扣证据:文件路径.env:1,类型是数据库生产密码。级别 High。同时提示该文件是否被.gitignore忽略,如果被提交到仓库,风险升级。
最终报告自动套用模板输出。整个过程中模型是被动执行流程,不是想到哪说到哪。这就是 skill 和普通对话最本质的差别。
5. 跑通之后才是真正的开始:三个高频坑与排查经验
说完搭建,必须说坑。这些坑我是真踩过的,每一条都花了不少时间排查。
5.1 误报率失控:AI 把“看着危险”当成“已经可利用”
我最初跑一个 Node.js 项目时,skill 报了一堆 High 级别“SQL 注入”,最后人工复核发现绝大部分都是pool.query用了模板字符串,但查询本身是固定 SQL,只是参数按公司规范用反引号拼接了一层别名。完全没有用户输入进入查询。
这个问题的根源在于:模型擅长模式识别,但不擅长区分“数据流真实可控”和“恰好长得像危险模式”。我在规则文件的“误报排除”里加了硬校验:
- 污点源必须能被用户输入、外部 API 或环境变量影响。
- 传播路径上必须存在可能绕过过滤的逻辑。
- 危险 sink 接收到的数据必须与污点源有数据流关联。
这三点缺一条,级别就要降。后来还加了一条:如果模型对某条发现判断置信度低于 80%,则必须转人工复核标记,而不是直接定级。这让报告的可信度提升非常明显。
5.2 上下文窗口不够:大仓库审计的取舍策略
一个真实的中型项目动辄上千个文件,把代码全部塞进上下文既不现实也没必要。我在调 skill 时发现,如果 audit_scope_matrix 里的“路径定位”写得太泛,模型会自动把整个 src 目录列进“审计范围”,然后读几个文件就把上下文占满,后半程开始胡言乱语。
解决办法是在资产盘点后增加一个“聚焦清单”筛选项。我要求模型遵循一个简单原则:优先审计可被外部触达的代码。判断优先级从高到低是:
- 网络入口:路由、控制器、API 网关、消息队列消费者。
- 高敏感模块:认证、支付、上传下载、用户数据导出。
- 文件与命令交互:路径拼接、系统命令调用、反序列化。
- 基础设施配置:Dockerfile、
.env、部署脚本。 - 公共库与工具函数中的危险操作。
前四类优先保证上下文预算,第五类只在时间允许时看。实际跑下来,上下文压力大幅下降,报告质量反而提升,因为模型把有限的上下文都耗在了真正的“高风险路径”上。
5.3 审计的“不破坏”纪律:read-only 与命令逃生舱
前面提到过 AI 在审计时会“顺手修复”代码,这个问题真的会发生。我在测试时让它审计一个 Python 项目,它不但报了漏洞,还主动把sqlite3.connect的代码改成了参数化查询并写入文件。吓得我直接回滚。
根因是 SKILL.md 里没有声明“禁止修改源文件”这个约束,模型默认“用户让我做审计”,修复是“额外的善意”。我从那之后把所有 skill 的“禁止动作”段都写得非常具体:
- 禁止写入、删除、重命名项目内任何文件。
- 禁止修改
requirements.txt或package.json之类的依赖清单。 - 所有辅助脚本的输出必须写入
/tmp或系统临时目录。 - 如果用户明确要求修复,必须先输出修复后的代码块,由用户手动替换。
还有一个安全阀:在 SKILL.md 里写了一条铁律——在调用外部命令前,先声明确认这是只读操作,并输出完整命令让用户批准。我把这称作“命令逃生舱”。它让模型在不确定脚本副作用时停下来问用户,而不是自行执行。
6. 把一次性审计变成持续安全基线
skill 跑顺以后,我开始琢磨怎么让它从“偶尔审一下”变成“每次 CI 都能跑、每个版本都有对比”的持续能力。
6.1 输出格式标准化的价值:从 Markdown 报告到 JSON/SARIF
Markdown 报告适合给人看,不适合给机器做趋势分析。我在报告模板之外,又让 skill 在输出内容末尾附一段 JSON 版本的结果摘要,字段固定为:
{ "meta": { "project": "demo", "audit_date": "2025-01-01", "schema_version": "1.0" }, "findings": [ { "id": "sql-injection-001", "severity": "critical", "cwe": "CWE-89", "file": "app.py", "line": 9, "summary": "用户可控参数直接拼接进入 SQL 查询", "has_evidence": true } ], "dependency_findings": [], "config_findings": [] }有了 JSON 输出,后续无论接 CI 还是做看板都很方便。如果想接更标准的工具链,可以让脚本把 result 转成 SARIF 格式,这样 GitHub Security Code Scanning 等系统可以直接识别。
6.2 指纹去重与漏洞台账:避免每次审计都从头开始
最开始的审计报告,下一次跑时会重复报告同一批问题,干扰判断。我后来在 skill 里加了一个去重逻辑:每条 finding 根据文件路径 + 行号 + 规则ID + 严重级别生成一个短哈希。审计前先读取历史发现库(一个findings.json),如果哈希存在且状态是accepted或won't fix,就不重复输出。
实际做法很简单,让 skill 在最后生成一个“与上次对比”的简表:
| 变化 | 数量 |
|---|---|
| 新增发现 | N |
| 已关闭发现 | M |
| 仍然存在 | K |
这样一个季度跑下来,漏洞台账越来越干净,新引入的问题一眼就能揪出来。
6.3 按业务自定义规则:把团队红线写进 skill
最后聊一个扩展性玩法。每个团队都有自己的技术红线,比如“不允许使用eval”“第三方支付 SDK 必须不低于某个版本”“日志里禁止打印手机号”。这些红线完全可以通过在rules/下新增规则文件写进 skill,让每次审计自动检查。
我会建议团队在规则文件里加这条:
# Team Red Lines ## 规则来源 团队安全规范 v2.1(维护人:@xxx) ## 强制检查项 - [ ] 禁止在 Python 代码中使用 eval/exec(来源:滥用导致 RCE 的多次事故) - [ ] 禁止裸用 `pickle.loads` 处理任何外部输入(来源:反序列化攻击) - [ ] 禁止在日志中输出身份证号、手机号、银行卡号字段 - [ ] LinkedIn/微信等社交信息不得出现在产品日志中 ## 违规处理 命中 Team Red Lines 的发现,直接标记为 High 级别,优先修复。红线规则和通用安全规则最大的不同是:它的优先级永远排前面,报告里会单独成节。这样每次审计完,技术负责人看到的第一部分就是“是否踩了团队红线”,不用在一堆中低危里翻找重点关注项。
我个人的体会是,security-audit-skill最有价值的地方不在于它能发现多冷门的漏洞,而在于它让 AI 的安全判断过程变得可追踪、可复现、可对齐。只要把边界划清、证据链写死、输出格式固定,AI 就能稳定地承担相当一部分安全审计的初筛工作。后续我打算再做两件事:一是把rules/按业务团队拆成模板库,二是把 JSON 输出直接接入工单系统,让发现自动生成待办。如果你也在做类似的事,建议先从一个小仓库跑通再逐步扩展,别一上来就审整个大仓。