ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

AI Agent 安全审计 Skill 实战:从 SKILL.md 到报告生成

AI Agent 安全审计 Skill 实战:从 SKILL.md 到报告生成

最近几个月我几乎每天都在用 Codex、OpenCode 这类 AI Agent 写代码。代码量上去了,心里却越来越没底——AI 生成的代码表面干净,内里难保没有硬编码密钥、依赖漏洞或者危险函数调用。以前我会在对话框里补一句“帮我看下有没有安全问题”,但结果基本是空泛的“建议使用参数化查询”这类正确废话,根本没有真正跑过扫描器,也没有定位到具体行号。后来我干脆把整套安全审计流程做成了一个 security-audit-skill:一个可复用的 Agent 技能包。装上之后,只要说一句“审计当前仓库”,Agent 就会自动调用 Semgrep、Gitleaks、Bandit 这些工具,再基于扫描结果输出一份带风险等级、文件行号和修复建议的报告。这篇文章就记录这个项目的完整落地过程,从设计思路到 SKILL.md 怎么写,再到实际装进 Codex 的踩坑记录,希望对同样在用 AI 写代码、又不想把安全隐患带进生产环境的读者有点帮助。

1. 为什么要给AI Agent做一套安全审计Skill

1.1 AI写代码的速度与安全风险完全不对等

先说一个很直观的现象:一个熟练的开发手写代码,一天撑死写几百行,想清楚每个分支并不难;AI Agent 不同,它十分钟能生成几千行,数据库查询、鉴权逻辑、第三方 API 调用混在一起。开发者代码审查的速度完全跟不上生成速度,几处隐藏问题很容易就被夹带过去了。更麻烦的是,你让 AI 自查,它会有一种“礼貌性自信”,哪怕没有证据也会告诉你“这里风险较低”。如果不限定流程,它根本不会主动去跑任何工具。

安全审计这种工作,靠的是证据和上下文,不是靠感觉。我需要一个东西,能强制 AI 先跑扫描器、再读结果、最后写结论,而不是直接凭训练数据里的经验来“即兴点评”。这就是我决定做 security-audit-skill 的直接原因。它本质上是一个把“人类安全审计员的固定动作”翻译成 Agent 可执行流程的技能包,让 AI 在合代码之前先做一轮客观的静态检查。

1.2 Skill不是Prompt,它是可执行的技能包

社区里最近在热议 skill,很多人问 skill 和 agent 的区别。我理解很简单:Agent 是执行者,Skill 是它学会的技能包。你写一句“帮我看下安全”,Agent 只能自由发挥;你给它一个 skill,它就有了明确的执行流程、工具调用顺序、输出格式要求。skill 通常由指令文件、脚本和知识文档组成,比一个 prompt 要重得多。Codex、OpenCode 这类工具都开始支持 skill 机制,本质上就是把“专家经验”固化下来。

security-audit-skill 做的事情,就是把我平时做代码审计时的那套 checklist,翻译成 Agent 能执行的流程和脚本。普通的 prompt 是一次性的,这次写了下次还得重写;skill 是装在 Agent 技能库里的,每次需要时自动加载。而且 skill 里可以带脚本,这意味着 Agent 不只是“聊安全”,而是真的能调用 Semgrep、Gitleaks 这些本地工具去扫描,这是单纯靠对话很难实现的。

1.3 这个项目到底解决了什么问题

做之前我列了几个痛点,项目的目标就是逐个解决它们。

第一是重复劳动。每次审计都要重新写提示词,不同项目的语气还不一样,效果全看运气。把 skill 装好之后,一句话就能触发完整流程。第二是工具执行缺失。Agent 在对话里很擅长“想象”扫描结果,但不会真的去跑 scanner。skill 里的 SKILL.md 明确要求它先执行 audit.py,这就把“想象”变成了“执行”。第三是输出不统一。多个工具的输出格式五花八门,Agent 看多了容易晕,所以我用脚本把结果统一成 JSON,再由 Agent 转成 Markdown 报告。

第四是安全规则分散。Semgrep、Gitleaks、Bandit、Trivy 各有各的用途,人工一个个跑很麻烦。skill 把它们包成一个入口,根据项目类型自动启用合适的工具。最终效果是,无论哪个项目,只要 Agent 加载了这个 skill,审计路径是固定的,结果格式是统一的。

2. Security Audit Skill的整体设计思路

2.1 先划定边界:静态审计为主,动态渗透不做

我设计这个 skill 时首先划了边界。它做四类检查:密钥与敏感信息泄露(Secret Detection)、依赖与第三方组件漏洞(SCA)、危险代码模式(SAST)、以及云基础设施和 CI 配置问题(IaC)。不做什么也很重要:不做动态渗透测试,不尝试登录生产环境,不执行需要业务凭据的验证。原因很简单,skill 跑在 Agent 的本地环境里,动态测试需要大量上下文和时间,而且容易产生副作用。

静态审计可以离线完成,最适合做成可重复执行的技能包。以我实际项目为例,绝大多数在合代码前能拦下来的问题,其实都是静态问题:一个 API key 忘在配置文件里、一处 SQL 拼接没有参数化、一个依赖版本锁得不够紧。这些问题用静态扫描器完全可以发现,不需要起一个测试环境去“打”一遍。动态的东西留给安全团队或者线下测试,skill 不越权。

2.2 输出结构化结果,Agent才接得住

第二件事是定义输出。Agent 接不住乱七八糟的原始日志,它需要结构化数据。我规定 audit.py 只输出一份 JSON 中间结果,包含 issues 数组,每个 issue 有等级、规则 ID、文件路径、行号、描述和修复建议。然后 prompt 模板再让 Agent 把 JSON 转成人类友好报告。这个分层很关键:工具产生证据,Agent 负责解释。如果反过来,让 Agent 直接读终端输出,结果会乱得不可收拾。

我见过太多 AI 看日志看到一半开始编结论的例子。原始扫描输出里混着 warning、error、统计信息、堆栈,人眼都容易看花,更别说 Agent。所以我在脚本里做了严格的解析层,每个工具返回的 JSON 只提取真正有问题的 issue,统一格式后再写入结果文件。Agent 读取的永远是干净、字段固定的 JSON,而不是原始的 stdout。这一步设计,直接决定了后面报告的稳定性和可信度。

2.3 工具选型:按场景组合而不是追求大而全

工具选择上我踩过一些坑。最开始想把所有工具都集成进来,后来发现没必要。我的标准是:必须命令行可调用、输出可解析、支持自定义规则、尽量开源。最终选了 Semgrep 作为 SAST 主力,Gitleaks 管密钥检测,Bandit 管 Python 专属问题,Trivy 管依赖漏洞和 IaC 配置,Checkov 补一下云原生配置检查。

工具定位输出格式适用场景
SemgrepSAST/自定义规则JSON/文本多语言、特定框架危险调用
Gitleaks密钥/敏感信息JSON硬编码密钥、Token、私钥
BanditPython SASTJSONPython 代码常见漏洞
TrivySCA/IaCJSON/表格依赖漏洞、镜像、配置文件
CheckovIaC 安全JSONTerraform/K8s/CloudFormation

实际使用中,我会在脚本里按项目类型组装这些工具。比如一个 Python Django 项目,跑 Bandit + Semgrep + Gitleaks + Trivy 就够了;一个 Kubernetes 配置仓库则跑 Checkov + Gitleaks。这样避免每次都把所有工具跑一遍,太慢。选型上我不追求“全家桶”,因为 Agent 的上下文和时间都有限,工具跑得太多,结果文件巨大,反而会把真正的问题淹没。

3. 核心实现:手写一个security-audit-skill

3.1 Skill目录结构:从入口到知识库

目录结构是 skill 的骨架。我最终的项目目录长这样:

security-audit-skill/ ├── SKILL.md ├── scripts/ │ ├── audit.py │ ├── gitleaks.toml │ └── semgrep_rules/ │ ├── dangerous-eval.yaml │ └── jwt-none-alg.yaml ├── prompts/ │ ├── report_assistant.md │ └── remediation_assistant.md └── knowledge/ ├── cwe_top25.md └── supply_chain_risks.md

SKILL.md 是入口,Agent 加载 skill 时第一个读它。scripts/ 是真正干活的,audit.py 负责统一调用扫描器并解析结果。gitleaks.toml 是白名单配置,用来降低误报。semgrep_rules/ 放自定义规则,主要针对团队内部技术栈的特定模式。prompts/ 里是给 Agent 的辅助提示词,report_assistant.md 教它怎么写报告,remediation_assistant.md 教它怎么给修复建议。knowledge/ 里放一些参考知识,防止它遇到常见漏洞模式时无话可说。

这个目录结构有个好处:职责分明。Agent 不需要把整个 skill 目录都读进上下文,它只需要先读 SKILL.md,然后按图索骥去调用 scripts、参考 prompts。如果知识文档非常大,Agent 也可以只查需要的部分,而不是一次性全部加载。

3.2 SKILL.md:告诉Agent按流程执行,而不是自由发挥

SKILL.md 是 skill 的灵魂。Codex、OpenCode 这些平台对 skill 的加载机制虽然不同,但 SKILL.md 的编写思路是通用的。我这份是这样写的:

--- name: security-audit description: 对代码仓库执行静态安全审计,定位密钥泄露、漏洞依赖、危险代码和错误配置。当用户要求进行安全审计、检查漏洞、扫描密钥时使用。 --- ## 使用条件 - 用户要求进行安全审计、检查代码漏洞、扫描密钥时触发。 ## 工作流程 1. 确定被审计目录,默认为当前工作目录。 2. 执行: python3 scripts/audit.py --path <target> --format json --out audit_result.json 3. 读取 audit_result.json。如果命令失败,向用户说明原因。 4. 根据 audit_result.json 中 issues 数据,结合 prompts/report_assistant.md 生成中文报告。 5. 报告必须包含: 风险等级汇总表、关键发现列表、每项的文件路径/行号、修复建议。 6. 禁止编造审计结果。没有任何证据的问题不得出现在报告中。

这里最关键的是第 2 条和第 6 条。第 2 条强制 Agent 先跑脚本,第 6 条严格禁止幻觉。很多人写 skill 容易漏了最后这条,结果 Agent 在扫描器没装的情况下直接“填空”,编出一堆漏洞。另外,我在 SKILL.md 里刻意不写“如何做安全审计”这种理论知识,因为 Agent 的知识储备已经够了,它缺的是执行路径,不是通识。把流程写清楚,比写一堆安全概念有用得多。

3.3 audit.py:把外部扫描器封装成统一接口

audit.py 是这个 skill 的引擎。它的核心思想是:把多个扫描器封装成一个命令。我简化后的大概逻辑如下:

#!/usr/bin/env python3 """Security Audit Skill - 统一扫描入口""" import argparse, json, os, shutil, subprocess, sys TOOLS = { "semgrep": ["semgrep", "scan", "--json"], "gitleaks": ["gitleaks", "detect", "--no-banner", "--report-format=json", "--report-path"], "bandit": ["bandit", "-r", "-f", "json"], "trivy": ["trivy", "fs", "--format=json"], "checkov": ["checkov", "-d", "--download-external-modules=false", "-o", "json"], } def check_tools(): missing = [t for t in TOOLS if shutil.which(t) is None] if missing: print(json.dumps({"error": "missing_tools", "tools": missing})) sys.exit(1) def run(tool, args, cwd): try: cmd = TOOLS[tool] + args proc = subprocess.run(cmd, cwd=cwd, capture_output=True, text=True, timeout=180) return proc.stdout, proc.stderr, proc.returncode except subprocess.TimeoutExpired: return "", f"{tool} timeout", 1 def parse_issues(tool, stdout, stderr, returncode): # 这里做各工具的JSON解析,统一成 issue 对象 issues = [] # ... 每个工具解析逻辑不同,按实际schema编写 return issues def main(): parser = argparse.ArgumentParser(description="Security Audit Wrapper") parser.add_argument("--path", required=True) parser.add_argument("--format", choices=["json", "markdown"], default="json") parser.add_argument("--out", default="audit_result.json") parser.add_argument("--profile", default="general") args = parser.parse_args() check_tools() all_issues = [] # 根据 profile 选择工具,并调用 run + parse_issues # 聚合结果 result = {"tool": "security-audit-skill", "issues": all_issues} with open(args.out, "w") as f: json.dump(result, f, indent=2, ensure_ascii=False) print(f"Found {len(all_issues)} issues, results saved to {args.out}") if __name__ == "__main__": main()

为了博文可读性,我省去了每个工具的解析函数。实际工程中每个扫描器的输出 schema 都不一样,最麻烦的是 Semgrep 的 JSON 嵌套很多,Gitleaks 的老版本和新版本字段也不一致。我建议在写 parser 时,先各跑一次样例,把 JSON 结构记录下来,再写对应的取值路径。这步偷懒,后面 Agent 读到的数据就是一团乱麻。

另外还要处理几个细节:超时。一个大型 repo 跑全部工具可能超过十几分钟,Agent 调用往往有超时限制。我在脚本里给每个工具设置了 180 秒超时,并支持 profile 参数来减少扫描范围。还有退出码。很多扫描器找到漏洞会返回非 0 退出码,subprocess 不要因此直接抛异常,要正常解析输出。把错误处理写充分,Agent 才能在你不在场的情况下顺利执行完整流程。

3.4 提示词模板:教Agent“读报告”和“写建议”

audit.py 产出 JSON 之后,Agent 需要把它读进上下文并写报告。问题来了:JSON 可能很长,直接丢给 Agent 会让上下文爆炸。prompt 模板就是用来约束它怎么读、怎么用的。我在 prompts/report_assistant.md 里写了下述要求:

你是一名安全审计工程师。请根据用户提供的 audit_result.json 生成报告。 要求: - 先用 Markdown 表格呈现各风险等级的问题数量。 - 每个问题需要给出:风险等级、规则/工具、文件路径、行号、问题描述、修复建议。 - Critical/High 级别问题必须逐条列出;Medium 最多列出10条;Low 只给摘要。 - 如果JSON中没有任何issue,明确写“未发现可疑问题”,不要补充“潜在风险”。 - 修复建议要具体到代码,例如“将 os.system(subprocess) 改为 subprocess.run(['ls'], shell=False)”,不要写“提升安全性”。

很多人会忽略这样一个细节:你不写“最多列出 10 条”,Agent 在报告高等级问题时还能克制,到了中低风险就会开始凑数。加了数量限制后,报告质量和上下文占用都好了很多。另外,修复建议必须具体到代码。如果只写“提升安全性”,等于什么都没写。Agent 其实有能力给出具体 diff,关键是 prompt 里要逼它做到这一步。

4. 实操:把Skill装进Codex和OpenCode

4.1 安装与目录约定

下面说一下怎么装进 Codex 和 OpenCode。Codex 的 skill 目录默认在 ~/.codex/skills/,OpenCode 在 ~/.config/opencode/skills/,不同版本可能有差异,可以先跑 skill list 看默认路径。安装其实就是把整个目录复制过去:

# 安装到 Codex cp -r security-audit-skill ~/.codex/skills/ # 安装到 OpenCode cp -r security-audit-skill ~/.config/opencode/skills/ # 验证 codex skills list opencode skill list

我踩过的一个坑是,很多 skill 示例把 SKILL.md 写得很复杂,装了之后 Agent 根本不触发。解决办法是:在 description 里写明触发场景,比如“当用户要求进行安全审计、检查代码漏洞、扫描密钥时使用”。Agent 判断是否使用 skill,主要看 description 和你对话的语义是否匹配,这一点比 SKILL.md 正文还重要。我在第一次安装后测试了很久,最后才发现是 description 写得太宽泛,导致 Agent 总在犹豫要不要用。

4.2 从触发到报告:一次完整调用过程

安装完后,回到对话里直接说:“用 security-audit skill 审计当前仓库。”Agent 会读取 SKILL.md,执行 audit.py,然后基于结果生成报告。这里有个核心机制:Agent 执行 shell 命令获得输出,再在后续回复中使用。它不会自己把所有脚本都调用一遍,而是严格按照 SKILL.md 的流程来。整个流程如下:

  1. 用户发出审计请求。
  2. Agent 定位当前目录并运行python3 scripts/audit.py --path . --format json --out audit_result.json。
  3. 脚本将各扫描器结果合并,写入 audit_result.json。
  4. Agent 读取 JSON,使用 report_assistant.md 组织语言。
  5. 输出 Markdown 报告并在末尾指出审计结束。

这五步里,第 2 步最容易被卡住。因为 Codex 在安全策略上会限制一些命令;如果 Agent 拒绝执行 audit.py,就要检查 SKILL.md 是否描述了命令用途,并且确认不是危险操作。一般来说,在本地项目目录内执行扫描脚本是允许的,但如果你的 Agent 使用容器沙箱,需要把目录挂载进去。另外,有些 Agent 会要求命令必须有明确参数,所以我在 SKILL.md 里给了完整的命令行,而不是只写python3 scripts/audit.py。

4.3 一个微型仓库的真实审计演示

我建了一个微型测试仓库,故意放了三类问题:一个硬编码的 API Key,一个 Flask 路由里直接拼接 SQL,一个 requirements.txt 里固化了带漏洞依赖版本。运行 audit.py 后,audit_result.json 里面会有 Gitleaks、Bandit、Trivy 三个来源的 issue。Agent 最终生成的报告大概是这样的:

## 安全审计报告 ### 风险统计 | 等级 | 数量 | | High | 2 | | Medium | 1 | | Low | 0 | ### 关键发现 1. [High] 硬编码 API Key - 文件: app/config.py:12 - 工具: gitleaks - 建议: 改为环境变量注入,并轮换已泄露密钥。 2. [High] SQL注入风险 - 文件: app/views.py:48 - 工具: bandit / semgrep - 建议: 使用参数化查询,例如 `cursor.execute("SELECT * FROM user WHERE id=%s", (user_id,))`。 3. [Medium] 依赖版本过旧 - 文件: requirements.txt:4 - 工具: trivy - 建议: 升级到修复版本并重新运行测试。

这种报告比我手动让 AI“看看有什么问题”要踏实得多,因为每个结论都有扫描器证据,不是 AI 拍脑袋。换言之,skill 的价值不在“AI 比人聪明”,而在“AI 被约束在正确的流程里”。

5. 常见问题与排查实录

5.1 扫描器缺失或版本不一致

你在新环境跑 skill,最常遇到的就是命令找不到。我建议 audit.py 启动时先做环境检查,把缺失工具一次性列出来,而不是跑到一半才报错。安装时可以使用 pip 和 brew,但我在 SKILL.md 里也写了一句:“如果环境缺少工具,向用户说明需要安装哪些命令,不要尝试自行安装。”为什么?因为 Agent 如果在没有用户确认的情况下执行系统级安装,既慢又有风险。让用户动手装,反而更干净。

版本不一致的问题也很常见。Semgrep 不同版本对规则的兼容性有差异,Gitleaks 旧版输出字段名也不一样。解决办法是在项目里固定一个 requirements.txt 或脚本安装说明,确保环境一致。如果你像我一样经常在多个机器之间切换,建议录制一个 install.sh,一键装齐所有工具。

5.2 扫描结果太多,Agent上下文爆炸

大型仓库扫描后 JSON 可能有几百个 issue,全塞进上下文会让 Agent 失焦。我的方案有三个:第一,脚本支持 --max-issues 参数,默认只保留 Medium 以上前 50 条;第二,报告模板要求只详细写 High,Medium 给列表,Low 给摘要;第三,把完整 JSON 落盘,报告里只展示关键字段。这三个组合下来,上下文占用大概只有原来的三分之一。

上下文爆炸不仅影响 Agent 的理解,还会让响应变得很慢。如果你的项目里有 node_modules 之类的超大目录,一定要先配置忽略规则,否则扫描器会一个文件一个文件地读进去,结果和上下文都会失控。宁可少看几个低风险项,也要确保高风险项没有被淹没。

5.3 密钥检测的误报与白名单

Gitleaks 误报是常态,尤其是测试代码里的假 token。我维护了一个 gitleaks.toml 白名单文件,并提供 --skip-paths 参数。示例:

[extend] useDefault = true [allowlist] description = "测试数据与mock密钥" paths = [ "tests/", "fixtures/", "*.md", ] regexes = [ "sk_live_test_only", "fake_secret", ]

注意:白名单不要写太宽,否则真密钥也会被跳过。我一般只在确定是单元测试或文档示例时才加白名单。白名单本身也要放进代码评审范围,避免有人打着“测试数据”的幌子把真实密钥混过去。这个看起来不起眼的文件,其实是长期维护 skill 时投入产出比最高的一个。

5.4 Agent幻觉:没有证据的漏洞不要写

这是最坑的问题。有一次工具没装好,audit.py 返回错误,Agent 竟然在报告里写了“发现 3 个高风险漏洞”。查了才知道,SKILL.md 只说了“运行脚本后读结果”,没说不许编。从那以后我在 SKILL.md 和 report prompt 里都加了铁律:“只能报告 JSON 中存在的 issues,不得补充推测风险。”另外,脚本出错时应该输出结构化错误字段,这样 Agent 能直接告诉用户出了问题,而不是自行补全。

幻觉这个坑需要反复强调。AI 的生成惯性很强,只要 prompt 里没有明确禁止,它就会顺着“安全审计报告”这个语境开始编造。最好的办法是让结果文件的 schema 足够清晰,并且把“无结果”也当成一种正常结果写进 prompt。比如 JSON 里 issues 为空数组时,Agent 必须写“未发现可疑问题”,而不是加一句“但建议人工复核”之类的万金油。

5.5 文件权限与忽略规则

有时候仓库里有不该扫的目录,比如 node_modules、build、vendor。如果不忽略,会导致扫描时间暴涨,还会给出大量无关结果。我在端点支持一个 .auditignore 文件,同时默认忽略常规目录。这个文件用 Gitignore 的语法,好记也好写。

node_modules/ dist/ build/ vendor/ .venv/ __pycache__/

在 audit.py 里解析它并把目录列表传给扫描器,能省下大量时间。这点在做真实项目审计时几乎是必须的。除了性能考虑,忽略文件目录也能减少误报。比如 build 目录里的压缩代码可能触发大量无意义的规则,而这些问题实际根本不会进入生产环境。

6. 让这个Skill更好用的几个经验

6.1 按项目类型加载不同的扫描Profile

根据项目类型动态启用工具。比如爬取项目的 package.json、requirements.txt、go.mod、*.tf,判断语言和基础设施类型。Python 用 Bandit + Semgrep,Node 用 Semgrep + npm audit,K8s/Terraform 用 Checkov。这样不仅快,报告也更聚焦。

Profile 的定义可以放在一个简单的配置文件里,例如 profiles.json,在 audit.py 启动时读取。这样即使你不改 SKILL.md,也能随时调整不同场景下要启用的工具组合。我在实际使用中深有体会:一个 Web 项目每次启动都跑 Checkov,会带来大量的噪音;而一个只包含 Kubernetes yaml 的仓库跑 Bandit,也毫无意义。按 Profile 分流是保证报告质量最重要的一步。

6.2 沉淀自定义规则:把团队规范写进Skill

通用规则经常漏掉团队内部的危险用法。比如我们内部禁用了某些 ORM 的 raw 方法,我写了一条 Semgrep 规则放在 semgrep_rules/ 下,skill 自动加载。

rules: - id: no-orm-raw languages: [python] message: "禁止直接使用 raw SQL 方法" severity: HIGH patterns: - pattern: $OBJ.raw(...) metadata: cwe: "CWE-89"

这类自定义规则其实是 security-audit-skill 最有价值的部分,因为它是团队经验的代码化。通用规则仓库可能不会覆盖你们内部框架的特定反模式,而自定义规则可以。时间长了,这个 skill 会越来越贴合团队的技术栈,审计结果的可信度也会明显上升。

6.3 给Agent加一个修复建议步骤

我后来给 skill 补了一个 remediate 子命令,让 Agent 根据 High 风险列表生成修复建议,并且直接给出 diff。但我的经验是:不要让 Agent 直接自动修改,除非测试通过。更稳妥的做法是生成补丁文件,人 review 之后再应用。

之所以不建议自动修改,是因为修复本身可能引入新的问题。比如把os.system()改成subprocess.run(),参数没处理好反而会有兼容性问题。Agent 生成 patch 可以作为初审,但合并前的测试和 review 不能省。在实际工作流里,我会让 Agent 输出建议 patch,然后复制到分支里跑一遍测试再决定是否采用。

6.4 从个人技能包走向团队CI规范

skill 在本地好用之后,自然想推广到 CI。你可以把 audit.py 作为预提交钩子或 GitHub Action,在每次 PR 时跑一遍。这和 Agent Skill 不冲突,反而形成互补:本地 Agent 用 skill 辅助开发,CI 保证合入前一定要过审计。

在 CI 里跑的时候,不需要 SKILL.md 和 prompts 这两层,只需要 scripts 目录,直接复用 audit.py 的 JSON 输出,然后在 workflow 里检查是否有关键级别漏洞。这样做的好处是,开发者在本地用 skill 发现问题、提前修复;CI 作为最后一道网,防止漏网之鱼。整个流程合起来,才是安全的闭环。

最后说一点我自己的体会。security-audit-skill 不是要取代安全工程师,它更像给你配了一个“先跑工具的实习生”。真正的漏洞分析、业务风险评估、修复方案评审,仍然需要人来把关。但我实际用了两周之后,最大的感受是:那些因为“图省事”而漏掉的低悬果实——硬编码密钥、直接拼 SQL、忘了锁依赖版本——几乎都挡在了合并之前。如果你也在用 AI Agent,建议花半天时间把类似流程做成自己的 skill,这比每天在对话里重复“注意安全”有用得多。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进