
上周我给自己加了一个安全审计 skill。流程很短:终端里敲一条 npx skills add,指向一个 GitHub 仓库,回车。几十秒后,agent 的能力列表里多了一项,从此它会读我的代码、跑我的脚本、写我的文件。整个过程没有一次权限确认。
这个手感跟 2014 年第一次 npm install 一模一样。
区别在于,npm 装进去的是代码。代码能扫、能审、能关进沙箱跑。skill 装进去的是给模型的指令:它不编译,没有入口函数,也不抛异常。它只是改变 agent 对一件事的判断方式。你没法用 grep 判断「顺手把 .env 里的内容附在总结后面」这句话算不算恶意。
SKILL.md 的规格小到让人不安
Agent Skills 现在有公开规范(agentskills.io)。一个 skill 就是一个目录,里面必须有 SKILL.md,YAML frontmatter 里只有两个字段是必填的:
name:最长 64 字符,小写字母、数字、连字符,必须跟父目录同名description:最长 1024 字符,要写清「做什么」和「什么时候用」
可选字段有 license、compatibility、metadata,以及一个 allowed-tools(规范里明确标着实验性,各家支持程度不一致)。其余全是自由发挥的 markdown 正文,规范建议正文控制在 500 行以内。
真正让这个格式跑起来的是三级渐进披露:
- 元数据约 100 tokens,每次启动都在上下文里,所有已安装的 skill 都占这 100 tokens
- 正文建议 5000 tokens 以内,任务命中时才加载
references/、scripts/、assets/里的文件,用到才读,不用不花钱
这个设计的直接后果是:一个 skill 可以做到无限大而不拖累日常开销。间接后果是,references/ 里到底放了什么,日常完全看不见。装的时候不逐个读完,等于把没看过的东西授权给了一个有 shell 权限的进程。
这套格式能成为分发单位,还因为它跨厂商。规范由 Anthropic 起草,现在 Claude Code、OpenAI Codex、Cursor、Gemini CLI、微软 Agent Framework 等一批产品都能读同一个 skill 目录。写一次,到处能跑,这是所有包管理器能成立的前提条件。
Cloudflare 把一个 skill 养成了 128 个仓库的扫描器
6 月 18 日,Cloudflare 发了博客《Build your own vulnerability harness》,同一天把 security-audit 这个 skill 开源,MIT 许可,现在三万五千星上下。
它的起点很朴素:一个大约 450 行的 skill,跑在单个仓库上。七个阶段,每个阶段现在都对应 harness 里的一层:
- 三个并行 agent 做侦察,把架构写进
architecture.md - Hunter 按攻击类分发,任务不是「审阅代码」,是「打穿代码」
- 每个候选漏洞交给一个没参与发现的验证 agent,任务是证伪
- 幸存的写成人读的报告
- 同时按 schema 输出
findings.json,用零依赖脚本做机械校验 - 一个全新 agent 独立复核每条结论对应的源码
- 复核通过才进 ingest API
这套东西现在覆盖 128 个仓库。Cloudflare 自己说,从第一次跑 slash 命令到全舰队覆盖,花了大约六周,工作是机械的:把 skill 的每个阶段抽成独立 agent,后面接数据库,前面加编排器,映射几乎是 1:1。
过程中撞了三堵墙,值得单拎出来。第一堵是上下文耗尽:跑一小时后窗口满了,模型开始吃自己的记忆,上午追踪的 bug 忘得干干净净。第二堵是持久性:跑一半崩了就得从头来,一次限流错误能烧掉几小时。第三堵是跨仓库盲区:单仓库会话看不见依赖它的应用。
解法是把状态完全外置,模型当无状态计算单元。这个思路不新鲜,但 Cloudflare 给的数字值得记住:单次运行大约只能找到多次运行累计量的一半 bug,而且偏向那些明显、不隐蔽的。
我个人认为这个 skill 最值钱的资产,是它写进流程的那条组织约束:验证的人不能是发现的人。而且验证换另一个模型跑。人类 code review 里最难制度化的东西,被它写成了硬规则。
生态已经交过一轮学费
2026 年 2 月,安全厂商在 OpenClaw 的 skill 市场 ClawHub 里挖出 ClawHavoc 行动:1184 个恶意 skill 包,归属 12 个账号。其中一个叫 hightower6eu 的号贡献了 677 个,另一个 sakaen736jih 又加了 390 个。研究者判断是自动化工具链,不是手工上传。
当时发一个 skill 的门槛只有一个:GitHub 账号注册满一周。没有静态分析,没有强制签名,没有沙箱试跑。
手法也不高级:名字起得像正经工具(生产力、行情跟踪、编码助手),README 写得专业,SKILL.md 里让人复制粘贴终端命令去装「辅助工具」,payload 放在 Hugging Face 当二级跳板。macOS 上投的是 AMOS 盗号木马,Windows 上是键盘记录和凭证窃取。还有一部分把 prompt injection 藏在 description 里,让 agent 自己去执行用户不知情的命令。
Snyk 的 ToxicSkills 研究扫了 ClawHub 和 skills.sh 上 3984 个 skill:13.4%(534 个)有 critical 级问题,36.82%(1467 个)至少有一处缺陷,76 个被确认是正在使用的恶意 payload。
2 月还爆出一起更值得警惕的:Clinejection。研究员 Adnan Khan 发现 Cline 的自动 issue 分诊流程可被 issue 标题注入,链条是四步,注入拿到 workflow 环境里的 npm publish token,污染 CI 的构建缓存,发出 cline@2.3.0。八天后有人真的利用了这个未修的洞,装了那个版本的人机器上会被顺手塞进 OpenClaw。一个 issue 标题,换掉了一个 AI 编码工具的官方 npm 包。完整披露拖到 6 月 1 日,同时带出 Aonan Guan 和 Aikido 的独立发现:同样的结构性问题在多个 agent 平台上都存在。
Hugging Face 那边的问题性质一样:nullifAI 用 7z 压缩的畸形 pickle 绕过自动扫描;Unit 42 证明被释放的 namespace 能被重新注册,按名字解析模型、不锁版本的流水线直接被劫持。
为什么 skill 比 npm 包更难防
四个结构性原因,都不太容易靠工程手段解决。
注入面在发现层。 description 是要写进 system prompt 的,那 100 tokens 的常驻预算里就带着陌生人写的话。你要模型「看见」这个 skill,就必须让它读别人写的字。这件事没有中间态。
语义层的攻击签名扫不出来。 CSA 那份研究里有句话说得直白:prompt injection 跑在语义层而不是二进制层,传统特征扫描看不见。你能扫 curl | bash,扫不出「把 .env 内容附在总结后面」。这个方向目前只能靠行为观测和人工审计。
渐进披露反过来保护了攻击者。 按设计,references/ 和 scripts/ 里的东西在你用到之前都不进上下文。也就是说你安装时读到的那点内容,只是冰山一角,剩下的在某个时刻会被自动加载。
权限跟着 agent 走,不跟着 skill 走。 skill 没有自己的身份。它用的是你 agent 的凭证、你的 git 配置、你的云账号。规范里的 allowed-tools 还标着实验性,指望它做权限隔离,项目还没到位。
我现在怎么装 skill
说几个具体动作,都是从 Metronome.fm 那篇实测文章和 CSA 的建议里扒出来的,加上我自己的习惯。
pin 到具体 commit。 Metronome 装 Cloudflare 那个 skill 时把版本固定在某个 commit 上。引用分支等于把未来的更新权交给仓库主人,rug pull 就是这么发生的。
装前读 scripts/。 他们读了 validate-findings.cjs 和覆盖率账本的校验脚本,确认不写文件、不发网络请求,才决定装。这个动作五分钟,能筛掉大部分低级恶意包。
改名避免撞车。 他们自己本来就有一个叫 security-audit 的 skill。不改名的话,命中哪个取决于用户怎么措辞。改成 cloudflare-security-audit 之后触发是确定的,这也是调试 skill 生态时最常见的一类坑。
别在没有 OS 级沙箱的机器上让它跑目标代码。 Cloudflare 那个 skill 要求执行目标代码时必须有操作系统强制的沙箱:断外网、空环境、内存和磁盘限额、只能写指定目录。Mac 上做不到,Metronome 干脆整场不跑代码只读源码。代价是所有候选都停在 needs_validation,一个 confirmed 都没有。这个妥协我认为是对的,宁可结论软一点,也别让审计工具本身成了攻击面。
企业环境用 allowlist 加版本 hash。 CSA 的建议是内部维护白名单,配已验证的版本哈希,别拿公共 registry 当生产源。
给 skill 单独开凭证。 别复用主 token,尤其是能推代码和能发布包的那几个。
成本账要算清楚
Metronome 那次跑的是 quick 模式,18 个 agent(4 侦察、11 hunters、1 覆盖率复核、2 验证),总消耗约 270 万 tokens。产出是 34 个单元干净、2 个候选、2 个挂起、16 条加固建议。两个候选都判成 needs_validation,他们当天手工验证:一个是 Service Worker 缓存的页面在会话被撤销后仍然离线可见,一个是服务端日志 token 被 NEXT_PUBLIC_ 前缀打进了浏览器包。
两个都真、都能修,当天修完了。
贵吗?270 万 token 换两个自己写了几轮的 skill 都没抓到的问题,我认为便宜。特别是第二个:他们自己的 checklist 里明确写着「这个 token 是只写的,暴露出来是设计如此」,那条假设在拆分日志源之后就没再被复查过。Cloudflare 那个 skill 没有这张 checklist,它从「入口 × 信任边界 × 攻击类」的组合里推,反而绕开了那个过期假设。
这件事给我一个挺实用的结论:checklist 型 skill 会随业务演化慢慢失效,组合推演型 skill 更容易发现假设漂移。
我的判断
skill 生态现在处在 npm 2014 年的位置:格式刚统一,分发刚起来,安全基本靠自觉。接下来一两年,registry、签名、审计这三件事里会出真正的赢家,而且不会只有一家。谁先把「安装时验证」做成默认动作而不是可选项,谁就拿到了企业市场。
但我不建议因为 ClawHavoc 就一个 skill 都不装。风险要用收益定价。真正该问的不是「这个 skill 会不会有恶意指令」,而是「我给它多大权限,它能损失我什么」。读代码的 skill 和能发 npm 包的 skill,风险差着两个数量级。
最后留一句我自己在用的判断标准:一个 skill 值不值得装,先看它有没有把「谁来验证」写进流程。写了的可以试,没写的大概率只是别人发来的一段 prompt,披了个目录结构。
参考来源