☰
打造 security-audit-skill:让 AI 助手变身代码安全审计专家
2026/9/25 4:45:29 网站建设 项目流程

1. skill 是什么,以及为什么要专门做 security-audit-skill

先花半分钟对齐一下概念。你可能已经被“agent skill”“claude skill”“codex skill”这些词轰炸过一阵子了,但如果让你一句话说清楚“skill 到底是个什么东西”,很多人其实还是懵的。

我的理解很简单:skill 就是给 AI 助手(或者说 agent)预先准备好的一组“专业能力包”。它不是一个插件,也不是一个普通的 system prompt,而是一套结构化、可复用、可挂载到不同 agent 框架里的指令和数据组合。里面可以包含角色设定、操作步骤、检查清单、脚本、参考文档,甚至规则库。你在 Claude、Codex、opencode 这类工具里装一个“代码审计 skill”,它就像给一个刚毕业的开发助理配备了一本《安全审计实操手册》加一张《漏洞检查清单》,让它遇到代码时知道该看哪里、该查什么、该按什么标准下结论。

那为什么不能直接写进 system prompt 完事?不是不能,而是很亏。prompt 是全局的、一次性的,塞得太长会稀释模型的注意力;而 skill 是“按需加载”的,模型在合适的场景下主动唤起它,平时不占上下文窗口。这就好比你不能把一本字典天天摊在桌子上办公,但你需要查词的时候,伸手就能拿到。做 security-audit 这种专业动作,规则量非常大,如果全局塞,效果一定大打折扣,这也是我建议把安全审计能力单独抽成一个 skill 的根本原因。

这个项目的目标很直接:定制一个 security-audit-skill,让 AI 助手在收到代码、review 请求或 CI 扫描任务时,能自动切换到“安全审计模式”,输出一份规范的、可执行的漏洞报告,而不是泛泛的“这段代码看起来不错”。

我写这篇文章适合谁?两类人。第一类,正在折腾 agent skill 但不知道如何下手,想找一个有代表性、又不至于太复杂的实战案例;第二类,做研发或安全相关工作,想把 AI 纳入日常代码审计流程,提升 review 效率。不管你是哪类,跟着把这套 skill 搭起来,后面完全能套用到自己的项目里。

2. security-audit-skill 的整体设计思路与方案选型

2.1 先想清楚:这个 skill 要解决什么痛点

在动手写任何 skill 之前,我建议你先回答三个问题:这个能力给谁用?用在哪个环节?产出的东西会被谁消费?

security-audit-skill 我的答案是这样的。给开发者个人或小型团队用,集成在本地 agent 工作流里(比如 code review 前、提交 PR 前、引入新依赖时);也可以挂在 CI 里当成一个辅助检查器;产出是一份结构化的安全审计报告,能被开发者直接读、直接改,也能被后续 agent 用来修复。

想清楚这三点,skill 的架构就出来了。它本质上是三块拼起来的:

第一块是“触发条件”,也就是什么时候模型应该加载这个 skill。第二块是“审计规则”,也就是模型拿到代码后,应该按什么维度去查。第三块是“输出格式”,也就是最终报告长什么样、每个结论要写到多细。

这三块里,最容易被忽略的是第一块。很多我自己早期写的 skill 失败,不是因为规则写得不好,而是模型不知道该什么时候用、什么时候不用。结果是:你在写一个普通的 CRUD 接口,它非要给你做一遍全家桶审计;你给它一段明确说有安全风险的测试代码,它反而当成普通代码放过了。后来我把触发条件写成一个独立小节,并且用“满足以下任一条件就执行”这种判定形式,准确率立刻上了一个台阶。

2.2 为什么安全审计特别适合做成 skill

安全审计这个场景,和 skill 这个形态,几乎是最佳拍档。原因有四个。

其一,审计规则高度可沉淀。OWASP 十大漏洞、密钥泄露、依赖版本风险、越权访问……这些规则十年内都不会有大的变化。它们天然适合被固化成 skill 的规则库,而不是每次都靠模型“自由发挥”。自由发挥的模型,可能这次记得检查 SQL 注入,下次就忘了检查硬编码密钥。

其二,审计结论需要标准化。如果让模型用自然语言随便聊聊“我觉得这里有点问题”,那报告质量完全没法保证。但 skill 可以强制它按固定结构输出:漏洞名称、风险等级、文件位置、攻击路径、修复建议。就像要求一个审计员必须按表格填单据,填得不规范就重来。

其三,上下文效率。安全审计规则如果全部塞进 system prompt,大概要 3000 到 5000 字。这些内容在非审计场景下就是纯干扰。skill 的好处是:平时不占用任何上下文,只有在审计任务触发时,规则才被加载进来。这个设计对长会话、复杂任务尤其重要。

其四,它天然是可迭代的。安全领域的变化很快,今天要查的依赖漏洞、明天要查的云配置,都是动态的。skill 跟代码一样可以版本管理,规则可以不断追加、修改,不需要每次去改 agent 的核心提示词。

2.3 与其他方案的对比,我为什么没这么做

在做这个 skill 之前,我也尝试过几种替代方案。简单对比一下。

直接在 system prompt 里写安全审计要求:最省事,但也有最明显的问题。首先,prompt 长度越长,模型对前面内容的遵循度越低,尤其是 Claude 这种上下文特别长的模型,它对“最前面那段安全规则”的记忆往往不如“用户最新发出的代码”管用。其次,全局生效意味着模型在写业务代码时也被安全规则束缚,容易产生过度保守、不敢输出代码的毛病。

用通用审计工具(比如 Semgrep、gitleaks、OWASP ZAP):这些工具很好,但它们只能做静态或半动态的规则匹配,对业务上下文的理解有限。比如一个“越权漏洞”,静态规则很难真正判断“这个接口是不是该做权限校验”,而模型恰恰擅长理解这类业务语义。所以我的定位不是用 AI 替代这些工具,而是让 AI 和它们配合:工具负责精确的规则匹配,skill 负责做工程判断和上下文分析。

写一个单独的安全审计 agent:听起来很专业,但对大多数团队来说过度设计了。维护一个额外的 agent 服务,要考虑鉴权、部署、接口设计一堆事。而做成 skill,挂载到现有 agent 上就能跑,成本和维护量小了一个数量级。

3. 核心细节解析:skill 的规则怎么写才管用

3.1 SKILL.md 的标准结构

写 skill 最忌一上来就写规则。先把“架子”搭对。

一个规范的 agent skill,目录结构是这样的:

security-audit-skill/ ├── SKILL.md ├── rules/ │ ├── injection_risks.md │ ├── auth_and_access_control.md │ ├── data_leakage.md │ └── dependency_checklist.md ├── scripts/ │ └── secret_detector.py └── examples/ ├── bad_sample.go └── good_sample.py

SKILL.md 是入口,它负责告诉模型“我是什么、何时用、怎么用”。我见过不少 skill 的 SKILL.md 写得跟功能说明书一样,堆满“这个 skill 可以做什么”的废话,毫无实操价值。正确的写法要像给同事的交接说明,直接、具体、可执行。

下面是我整理的一个 SKILL.md 头部模板,核心字段就 5 个:

--- name: security-audit description: 对代码进行安全审计,识别常见漏洞并输出标准报告。当收到代码审查、PR 检查、依赖安全检查、漏洞分析等请求时触发。 version: 1.2.0 triggers: - 请求中包含 "安全审计"、"漏洞分析"、"security review" 等指令 - 用户提供完整代码文件并要求评估安全性 - 代码涉及 SQL 拼接、文件上传、认证鉴权、敏感数据处理的场景 - PR 描述中包含 "security"、"audit"、"漏洞" 等关键词 --- # Security Audit Skill 对传入代码或项目执行系统化安全审查,检查 6 大类风险点,输出统一格式的审计报告。

注意 description 和 triggers 这两处,必须写得“让模型一眼就能判断要不要加载”。这里有个小技巧:description 里除了描述功能,还要写明典型的用户触发词。这样 agent 框架在做 skill 匹配时,就能更准确地唤起。

3.2 审计规则怎么写:从审计员视角倒推

有了一堆规则清单之前,先想想“一个专业审计员拿到一段代码会怎么做”。他一定不是拿到代码就猛扫,而是先分类型、定优先级,然后逐项排查。

我把审计规则分成了 6 个维度,对应 SKILL.md 里任务拆解的部分:

  1. 注入类风险:SQL 注入、命令注入、XSS、模板注入。
  2. 认证与会话问题:硬编码凭证、弱口令校验、会话固定、越权访问。
  3. 敏感数据泄露:日志里打明文密码、错误信息堆栈暴露、前端注释带 token。
  4. 文件与资源安全:文件上传类型校验、路径穿越、URL 重定向。
  5. 依赖与供应链风险:已知漏洞版本、可疑的下载源、非锁定的依赖版本。
  6. 并发与业务逻辑:竞争条件、支付/积分逻辑绕过、条件竞争导致的重复操作。

每个维度在 rules 目录里都有一份对应的 markdown 文件。这个规则的显著特点是“用问题清单代替论点”,最好写成“当看到 X 情况,检查是否满足 Y 条件,若满足则报告 Z”,而不是“注意 SQL 注入风险”这种抽象句子。

举个具体的例子。injection_risks.md 的开头可以这样写:

# 注入类风险检查规则 ## SQL 注入 检查所有数据库查询的字符串拼接方式: - 若使用 f-string / format 直接拼接 SQL,且拼接内容包含外部输入(用户参数、请求体、文件名),则标记高危。 - 检查动态列名/表名是否参与白名单校验,若直接拼接外部传入的列名,标记中危。 - 查询参数化实现处需确认:是否所有执行分支都走到了参数化接口?是否存在经过字符串操作后丢失参数化特性的情况? ## 命令注入 检查所有 subprocess / shell 调用: - 若 shell=True 且命令字符串含外部输入,标记高危。 - 若使用 shell 管道(|、&&)且在参数中出现外部输入,标记高危。 - 使用 list 形式传参的命令,检查是否有转义绕过场景。

可以看到,每一条都是“可判定的”,模型不需要发挥,只需要判断。这很重要——skill 的核心价值其实就是把“专家的判断逻辑”翻译成“模型的判定步骤”,降低它自由发挥的空间。

3.3 让模型“按章办事”:输出格式与强制规范

如果说审计规则是 skill 的骨架,那么输出格式就是它的脸面。一个输出格式混乱的报告,即使内容正确,也很难被人直接采用。

我在最初版 skill 里,输出规范就一句话:“请输出漏洞列表”。结果模型每次输出的格式都不一样,有的按表格、有的按段落、有的漏洞严重程度写“high”,有的写“高”。后来我把输出规范写成了一个固定的 JSON 结构:

## 输出规范 必须按照以下结构输出审计结果(Markdown 代码块内): { "summary": "审计范围与总体结论,不超过 200 字", "total_issues": 3, "critical": 1, "high": 1, "medium": 1, "low": 0, "issues": [ { "id": "SEC-001", "title": "简要标题", "severity": "critical | high | medium | low", "file": "影响的文件路径", "line": 42, "description": "问题描述、触发条件与攻击链路", "remediation": "修复建议,给出可执行的具体改动方向", "references": "相关的 CWE 编号或资料链接" } ], "false_positive_notes": "如果你认为某些规则命中了但实际风险很低,请在这里说明理由" }

拿这个 JSON 结构作为硬性要求,有几个好处。

第一,机器可读。报告可以直接喂给下游的修复 agent,或者接入 CI 平台自动解析。第二,强制模型思考“严重程度分级”。每次都让模型自己判断 critical/high/medium/low,实际上是在让它做一次筛选,而不是把机器扫出来的问题全部往外倒。第三,加了 false_positive_notes 这栏之后,误报率明显下降。之前模型怕漏报,不管三七二十一全报一遍,导致报告里混入大量根本没风险的“硬编码测试数据”。有了这一栏,模型会在报告里主动解释“为什么我觉得这个不值得报”,这在尺度把握上非常有用。

注意:不要指望模型 100% 遵守 JSON 结构,尤其在通过命令行交互时,它会忍不住在 JSON 前后加解释文字。我的办法是在 SKILL.md 里写一句“禁止在 JSON 外输出任何文字描述,包括开头和结尾”,同时在外层 reader 端做一层容错解析,剥离非 JSON 内容后再解析。两个措施同时上,才能稳。

4. 实操过程与核心环节实现

4.1 从零搭建最小可用的 security-audit-skill

下面我就带着你,把整个 skill 一步步搭出来。不需要复杂的框架,一个目录、两个 markdown、一个辅助脚本,就能跑起来。

第一步,创建目录和骨架文件。

mkdir -p security-audit-skill/{rules,scripts,examples} cd security-audit-skill touch SKILL.md touch rules/injection_risks.md touch rules/auth_and_access_control.md touch rules/data_leakage.md touch rules/dependency_checklist.md touch scripts/secret_detector.py

第二步,填充 SKILL.md。我把上面提到的头字段、触发条件、审计流程、输出规范一次性写好。这里的关键是“审计流程”部分,要让模型按固定顺序运作,不能跳步。我的流程是:

  1. 确认审计范围:分析传入代码属于什么语言、什么框架、什么业务场景。
  2. 静态识别:根据文件类型判断适用的规则,对每个文件逐行检查。
  3. 跨文件分析:重点关注数据流,判断外部输入是否经过危险函数时流出。
  4. 依赖检查:如果用户提供了依赖清单,检查有无已知高危版本。
  5. 汇总输出:按 JSON 规范输出报告,并标记不确定项。

第三步,规则文件具体怎么填。rules/data_leakage.md 是最好写也最容易见效的,因为漏数据是 AI 模型最擅长抓的问题。我摘一段:

# 敏感数据泄露检查规则 ## 日志输出 - 检查 log 语句、print 语句、console.log 等输出是否包含明文密码、token、session_id、信用卡信息,若包含则标记 high。 - 若输出的是对象整体,需判断对象内部字段是否含敏感信息,如 user 对象含 password_hash,则标记 medium。 ## 错误信息 - 检查异常处理分支是否泄露堆栈、数据库连接字符串、内部 IP、文件路径,若异常信息返回给前端,标记 medium 以上。 - 若错误信息仅在服务端日志中,前端返回通用描述,则标记 low 或忽略。 ## 前端与注释 - 检查前端代码注释、API 文档注释里是否含有 token、内网地址、AK/SK 示例,若有则标记 medium。

规则文件写完之后,可以给每个文件加一个“使用说明”区块,告诉模型这个文件的适配场景和优先级。比如 dependency_checklist.md,要限定“当用户提供 package.json / requirements.txt / go.mod 时才使用”,这就避免了模型在没有依赖文件时硬编依赖问题。

4.2 接入 agent 工具链并让 skill 真正跑起来

搭好了 skill 本体,下一步就是看你怎么把它接到自己日常在用的 agent 里。

如果你的前端工具是 Claude Code 或 Codex,做法很简单:把整个 security-audit-skill 目录放到约定的 skills 目录下(比如.claude/skills/security-audit/),然后在配置里声明启用。不同的 agent 框架有不同的目录约定,建议直接查当前版本的文档,常见的有.claude/skills/和.cursor/skills/两类路径。

接入后需要验证一个关键点:skill 是否会被自动触发。我的验证方法很粗暴——拿一小段明显有问题的代码跑一遍,比如:

import sqlite3 def login(username, password): conn = sqlite3.connect('users.db') cursor = conn.cursor() query = f"SELECT * FROM users WHERE username='{username}' AND password='{password}'" cursor.execute(query) return cursor.fetchone()

如果 agent 在没有任何前置提示的情况下,直接调起 security-audit 并输出结构化报告,说明它已经能自己识别“这段代码需要审计”。如果 agent 只是当作普通问答处理了,就得回到 SKILL.md 的 description 字段,改得更具体一些,把“SQL 拼接”“用户输入拼接”这类具体特征写进去。

接入 CI 就更进阶一点。我在 CI 里放了一个 check 脚本,用模型跑完 skill 后解析 JSON,统计 critical/high 数量,超过阈值就把流水线标红。核心代码不复杂,但这里有两个值得注意的点。

一是接口容差。模型输出经常在 JSON 前加一句“这是审计结果”,所以解析前要做一个清理操作:找到第一个{和最后一个},截取中间内容再 json.loads。

二是分级阈值不要一开始就设很高。CI 刚接入时,报告质量不稳定,误报导致流水线频繁红是常有的事。我的做法是先观察两周,把每天的 critical/high 数量和误报率记录下来,再决定阈值。一般来说,critical 级别的误报率偏低(因为高危漏洞特征很明显),可以大胆点;high 级别则要小心,因为很多所谓 high 只是代码风格问题。

# scripts/ci_check.py 核心片段 import json, sys, re def parse_audit_result(text: str) -> dict: """从模型输出中提取 JSON 审计结果,带容错处理。""" start = text.find('{') end = text.rfind('}') if start == -1 or end == -1: raise ValueError("未找到有效的 JSON 输出") return json.loads(text[start:end + 1]) def main(): raw_output = sys.stdin.read() result = parse_audit_result(raw_output) critical = result.get("critical", 0) high = result.get("high", 0) if critical > 0 or high > 5: print(f"安全审计未通过: critical={critical}, high={high}") sys.exit(1) print("安全审计通过") if __name__ == "__main__": main()

4.3 补一个辅助脚本:密钥扫描器

skill 里不能只有“文本规则”,因为有些安全问题是纯文本规则覆盖不了的,比如“一堆乱码里藏着一个 AK/SK”。这时候就需要真正跑一个脚本去扫。我在 scripts 目录下放了一个简单但实用的密钥检测器,作为 skill 的补充能力。

这个脚本的思路不复杂:利用正则和高熵检测。高熵检测的意思是,如果某段字符串看起来像是随机生成的(字符分布非常均匀、没有明显单词特征),它可能是密钥或 token。下面这段是我线上在用的精简版,能覆盖大部分真实场景:

#!/usr/bin/env python3 """轻量密钥检测器:扫描文件中的常见密钥格式与高熵字符串。""" import os import re import math import sys from collections import Counter # 常见密钥/凭证的格式正则 PATTERNS = [ (r'(?i)(AKIA[0-9A-Z]{16})', 'AWS Access Key'), (r'(?i)(sk-[A-Za-z0-9]{20,})', 'OpenAI/Auth Token'), (r'(?i)(-----BEGIN RSA PRIVATE KEY-----)', 'RSA Private Key'), (r'(?i)(password\s*[=:]\s*["\']?[^"\'\s]{6,})', 'Hardcoded Password'), (r'(?i)(token\s*[=:]\s*["\']?[A-Za-z0-9_\-]{16,})', 'Token'), ] def shannon_entropy(data: str) -> float: """计算字符串的信息熵,用于高熵随机字符串检测。""" if not data: return 0.0 freq = Counter(data) prob = [count / len(data) for count in freq.values()] return -sum(p * math.log2(p) for p in prob) def scan_file(path: str) -> list: hits = [] with open(path, 'r', encoding='utf-8', errors='ignore') as f: lines = f.readlines() for lineno, line in enumerate(lines, 1): line = line.strip() for pattern, label in PATTERNS: if re.search(pattern, line): hits.append((label, path, lineno, line[:80])) # 过滤掉纯单词字符串后,检测熵值高于4.5的字符串 for candidate in re.findall(r'[A-Za-z0-9_\-]{20,}', line): if re.fullmatch(r'[a-zA-Z]+', candidate): continue if shannon_entropy(candidate) > 4.5: hits.append(('High-entropy Secret', path, lineno, candidate[:80])) return hits if __name__ == '__main__': for target in sys.argv[1:]: for root, _, files in os.walk(target): for name in files: if name.endswith(('.py', '.js', '.go', '.java', '.json', '.yml', '.yaml', '.env')): full = os.path.join(root, name) for hit in scan_file(full): print(f"[{hit[0]}] {hit[1]}:{hit[2]} -> {hit[3]}")

这个脚本单独跑也非常有价值。但请注意,它本质上是“辅助工具”,不能替代 skill 里的语义分析。两者配合方式是:脚本先扫一遍,把可能的风险点喂给 agent;agent 再结合上下文判断这些 risk 是不是真的风险。举个例子,测试代码里经常有password = "123456",脚本会报 Hardcoded Password,但 agent 看了上下文发现这是单元测试的固定数据,就会在 false_positive_notes 里说明并降级。这就是“工具负责精确匹配、模型负责业务判断”的落地实现。

5. 常见问题与排查技巧实录

5.1 模型不听话:完全不按规则来

这是最让人崩溃的问题,没有之一。你辛辛苦苦写了 3000 字规则,结果模型拿到代码后一顿自由发挥,既不按审计流程走,也不输出 JSON。

我踩过几轮坑之后,总结出几个实际有效的原因和对策。

首先是 SKILL.md 的定位问题。如果你把 rules 全部写在 SKILL.md 里,模型读它的时候可能已经把它“当成参考”而不是“当成指令”。所以我把 SKILL.md 里的规则都改成“引用”而不是“展开”,只写“参考 rules/ 目录下的 X 文件”,让规则文件作为独立上下文在后续对话中按需加载。模型对待“引用文件”和“正文内嵌规则”的态度是不一样的,实测下来后者更容易被忽略。

其次是规则的语气问题。我对比过两组写法,一组是“你应该检查 SQL 注入”,另一组是“如果代码中出现字符串拼接 SQL 且拼接内容含外部输入,标记为高危”。后者效果好得多。原因是:前者给模型留了解释空间,它会想“哦,这个建议不错,但我这次不想用”;后者则更像一条硬性判定规则,模型在执行时倾向于按固定逻辑走。

最后是上下文顺序问题。SKILL.md 在上下文中离用户指令越远,遵循度越低。有些 agent 框架在加载 skill 时,会把 skill 内容插到用户消息之前,这个位置还不错。如果发现模型行为不对,检查一下框架的 skill 注入位置,尽量让 skill 内容和用户的审计请求在同一个上下文块内。

如果上面都试了还是不行,还有一个“降级方案”:在用户请求中显式附加一句,“请严格按照 skill 的规则执行,输出 JSON 格式报告”。虽然不够优雅,但关键时刻真的管用。

5.2 误报率太高:规则太粗,缺少场景过滤

常见的问题和实际数据:第一次把完整规则载入时,跑一个中型 Node.js 项目,报了 47 个问题,人工复查后真正要修的不到 10 个。原因有几种。

第一,规则里的“检查 X”没有限定“在什么业务场景下才成立”。比如“文件上传”规则,如果你写“检查上传文件是否有类型校验”,模型看到任何上传接口都会报“类型校验不完整”。但小程序后端的上传接口和后台管理系统的上传接口,风险等级能一样吗?我后来在规则里追加了“场景权重项”,要求模型在判断风险等级时,先确定接口是否对公网开放、是否涉及认证用户、文件是否会被下载执行。经过这一层过滤,误报率降下来一大半。

第二,缺少“放行清单”。我给 skill 加了一个 exceptions 段落,明确说明哪些情况下即使规则命中也不报告:

  • 代码位于 test/、tests/、tests/ 目录下。
  • 代码是对外 SDK 的示例文档,且凭证是假数据(以 example、test、fake、your- 开头的占位值)。
  • 漏洞代码出现在被注释掉的代码块中。
  • 依赖配置中的版本锁定为已知内部源,且该内部源已做安全扫描。

加了这个之后,报告质量肉眼可见地提升了。这里面的逻辑是:模型的 false positive 很多来自“不知道哪些场景是例外”。你给它一个明确的白名单,它就不需要自己去猜。

第三,规则之间互相冲突。我最开始把 SQL 注入规则和“代码重构建议”写在一起,模型为了满足“提高代码质量”的建议,反而漏掉了真正的注入点。后来我把所有规则严格限定在“安全维度”,凡是跟性能、可维护性相关的建议一律不放在 skill 里。一个 skill 只干一件事,规则越纯粹效果越好。

5.3 skill 与外部工具联合使用的坑

最后说一个进阶场景里很容易踩的坑:skill 和 Semgrep、gitleaks 等工具的联动。

联动方式通常是:先跑 Semgrep 得到规则匹配列表,再把列表交给 agent,让 agent 基于 skill 的语义规则做二次确认。看起来顺畅,其实坑在“数据对接”。

Semgrep 的输出是 JSON,字段里有 check_id、path、line、message。如果直接把这段 JSON 原封不动塞给 agent,agent 会被大量技术细节淹没,然后开始给每条结果写长篇分析,输出报告变得又长又无效。我的对策是:在脚本里先做一次过滤和转译,只把高置信度的结果保留下来,并且转成一句人话,比如“path/to/file.py:42 检测到 subprocess 调用且 shell=True,请检查是否有命令注入风险”。

这里还有一层,Semgrep 这类工具的结果有“工具信任度”,agent 往往过于相信工具输出。我见过模型对着一个规则误报的漏洞,花大篇幅分析攻击链,显得非常专业,但其实代码那行根本不可达。所以我在 SKILL.md 里明确加了一条:“对于工具命中结果,不要直接采信,必须重新从数据流角度确认是否真实存在攻击路径。” 这一条对抗模型盲目信权威非常有效。

5.4 一个拿来就能用的避坑速查表

我把这段时间踩过的坑整理成一张表,按“症状—原因—对策”排列:

症状常见原因处理办法
skill 完全不被触发description 里缺少具体触发词,描述太泛在 description 里写清“当用户提供代码并要求审计/检查漏洞时使用”,附上典型触发例句
触发了但输出很水规则文件里全是“注意安全”类抽象话改成“当出现 X,若满足 Y,则标记 Z”的判定式表达
报告格式不统一输出规范写得太晚或太轻用 JSON schema 做强制结构,并加上“除 JSON 外禁止输出任何内容”
误报堆成山没有场景过滤和放行清单增加受影响面判断(公网/认证/可执行),维护一个例外白名单
模型自行脑补攻击链规则未要求它区分“确认”与“猜测”在输出规范中加“confidence”字段,让模型标注每条的置信度
与工具联动时重复输出工具报告和规则分析混在一起先在脚本里做过滤和转译,再让 skill 按统一结构输出
上下文窗口被 skill 占满规则文件太多,一次性全部加载按审计场景拆成多个小规则文件,让 agent 按文件类型选择加载

这张表不只是给我的项目用的。你后面做任何 skill,遇到类似症状,都可以先对照着排查一轮。

6. 后续扩展方向与我的实际体会

搭完 security-audit-skill 之后,我一直在琢磨怎么把它继续做强。目前已经想清楚、准备落地和已经落地一半的扩展,大概有三个方面。

第一是跟修复 agent 打通。现在 skill 只负责“出报告”,修复还需要人工。我的下一步计划是:报告解析后直接喂给修复 agent,让它根据 JSON 里的 remediation 提示生成具体修复 diff。这件事做起来并不复杂,因为我在输出规范里已经定了 JSON 结构,机器天然可以对接。唯一需要注意的是控制修复 agent 的“激进程度”,安全修复最容易出现“改这儿坏了那儿”的问题。

第二是支持更多框架的安全规则。现在这套规则主要覆盖 Python、Go、JavaScript 的通用漏洞。如果我拿它去审计 Rails 项目,几乎可以确定会有大量漏报。原因是框架特有的安全机制模型未必知道。所以规则库需要按框架扩展,比如 Laravel 的 SQL 注入防护、Spring Security 的配置检查。每个框架写一个独立规则文件,放进 rules 目录,让模型按项目框架自动选择,就能把覆盖率提上去。

第三是加入隐私合规维度的审计。代码安全不完全等于安全,GDPR、个人信息保护法这些合规要求,如今也开始影响代码层面的实现。比如是否对用户数据进行脱敏、是否在日志里保留了远超必要周期的个人信息。把合规规则沉淀成 skill,本质上和沉淀安全规则一样,都是把需要“专业判断”的东西显式化。

最后再分享一点我个人在实际操作中的体会。做这个 security-audit-skill,最耗时间的不是写规则,而是“让模型知道该怎么用规则”。我大概花了三分之二的时间在调整触发条件、输出格式和例外清单上。这让我意识到一件事:skill 的本质不是什么高深的技术,它是在把专家脑子里的决策过程“翻译”成模型能按步骤执行的文档。翻译得越具体、越可判定,效果就越好。所以如果你现在也想做一个自己领域的 skill,别急着写大而全的规则,先挑一个最核心的判断场景,把它写细、写死、写成判断式,跑通之后再慢慢扩充。这种“先窄后宽”的做法,比我一开始追求全覆盖的版本要稳妥得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询