这次我们前面确实看偏了。
参考文章讲的不是 Sandbox Skill,而是 NVIDIA 开源的 SkillSpector。这两个东西都和 AI Agent 安全有关,但解决的问题完全不一样。
Sandbox 更像是“把不可信代码放到隔离环境里跑”。它关心的是执行边界:文件、进程、网络、密钥能不能被隔开。
SkillSpector 更像是“安装 Skill 之前先做一次安检”。它关心的是这个 Skill 本身有没有可疑指令、可疑脚本、过大的权限、偷偷外传数据的链路,以及 MCP 工具描述里有没有藏指令。
所以这篇文章要换一个核心问题:
当我们开始从 GitHub、社区、市场里安装别人写的 Skill 时,怎么判断它是不是在偷看你的 API Key?
为什么现在要认真看 Skill 安全
很多人第一次用 Claude Code、Codex、Cursor 这类 AI 编程工具时,最容易做的一件事就是放权限。
为了少点确认弹窗,直接让 Agent 能读文件、跑命令、装依赖、访问环境变量。刚开始确实爽,很多自动化流程一下就通了。
但这里有一个隐含前提:你信任正在运行的所有东西。
问题是,Skill 不是一句简单的提示词。一个完整 Skill 往往包含:
| 组成部分 | 可能带来的风险 |
|---|---|
SKILL.md | 可以藏 prompt injection、隐藏指令、触发条件 |
| 脚本文件 | 可以读文件、扫环境变量、发网络请求 |
| 依赖声明 | 可能引入恶意包、漏洞包或未固定版本 |
| MCP 配置 | 可能声明过大权限,或者工具描述和真实行为不一致 |
| Memory / 持久上下文 | 可能影响后续所有对话和任务判断 |
如果一个 Skill 能读取你的 .env、~/.ssh、云厂商凭证、数据库连接串、浏览器缓存、聊天上下文,再叠加一次恶意网络请求,泄露就不是理论风险了。
这也是参考文章标题里“你的 Skill 可能正在偷看你的 API Key”真正值得展开的地方:危险不一定来自模型“想作恶”,也可能来自你安装的 Skill 本身就带着恶意指令或危险代码。
SkillSpector 是什么
NVIDIA 的官方仓库对 SkillSpector 的定位很直接:
Security scanner for AI agent skills.
它不是一个运行时沙箱,也不是一个新的 Agent 框架,而是一个面向 AI Agent Skill 的安全扫描器。
你可以把它放在 Skill 安装前、团队引入外部 Skill 前、CI 审查 Skill 仓库时使用。它支持扫描 Git 仓库、URL、zip、目录,甚至单个 SKILL.md 文件,然后输出终端、JSON、Markdown 或 SARIF 报告。
官方 README 里有两个数字很值得注意:
| 研究结论 | 数字 |
|---|---|
| 数据集规模 | 42,447 个 skills |
| 至少包含一个漏洞的比例 | 26.1% |
| 可能存在恶意意图的比例 | 5.2% |
| 带可执行脚本的 Skill 漏洞概率 | 2.12 倍 |
这说明 Skill 安全不是“过度担心”。当 Skill 从个人 prompt 变成可分发、可安装、可执行的组件,它就越来越像早期软件包生态:好用,但也会混进有问题的包。
参考文里说的五类风险,只是简化版
参考文章把 SkillSpector 概括成五种检测模式:
- 指令覆盖,也就是 prompt injection;
- 隐藏指令或后门指令;
- 数据泄露;
- 权限过大;
- Memory 被植入风险内容。
这个说法适合给新手建立直觉,但如果按官方实现看,范围其实更大。
SkillSpector 官方写的是:16 个类别、64 个漏洞模式。除了上面这些,还包括供应链风险、危险代码 AST、污点追踪、YARA 签名、MCP least privilege、MCP tool poisoning、系统提示词泄露、rogue agent、自修改和持久化等。
我更建议把它理解成三层扫描:
| 层级 | 它在看什么 | 例子 |
|---|---|---|
| 文本和规则层 | Skill 文档、触发词、隐藏指令、权限声明 | ignore previous instructions、零宽字符、过宽触发词 |
| 代码和依赖层 | 脚本、依赖、危险函数、数据流 | os.environ 到 requests.post()、exec()、`curl |
| 语义和生态层 | LLM 语义复核、MCP 工具描述、OSV 漏洞数据 | 描述和行为不一致、参数说明里藏注入、依赖 CVE |
这也是它比普通 grep 更有价值的地方:它不是只搜几个关键词,而是把 Skill 当成一个可安装的软件包来审。
它的实现流程其实很清楚
从源码看,SkillSpector 是一个 LangGraph 工作流,主流程可以简化成五步:
resolve_input把 Git URL、zip、目录、单文件解析成本地可扫描目录。build_context遍历 Skill 文件,建立components、file_cache、manifest、文件类型、行数、是否有可执行脚本等上下文。analyzers并行跑一组分析器,包括静态规则、AST、YARA、MCP、语义分析等。meta_analyzer在开启 LLM 分析时,对原始 findings 做语义过滤、解释和补充,降低误报。report生成 SARIF、风险分数、严重级别和最终建议。
这条流水线有两个关键点。
第一,它会先尽量用静态分析抓高召回问题,比如环境变量收集、外部传输、危险函数、未固定依赖、MCP 权限不匹配。
第二,它可以再用 LLM 做语义复核。官方文档里提到,LLM 分析主要用于理解上下文和意图、过滤误报、生成更好读的解释;如果你只想快速扫描,也可以加 --no-llm 跑静态版本。
这就比“让模型帮我看看这个 Skill 安不安全”稳很多。因为它先有明确规则、明确报告格式、明确风险计分,再让 LLM 做辅助判断。
最值得关注的几类检测
如果你平时会装别人写的 Skill,我觉得最应该关注下面几类。
1. 数据外传和环境变量收集
官方示例里就有类似风险:脚本遍历环境变量,收集疑似 API Key、Token、Secret,然后通过 requests.post() 发到外部服务。
这类问题最危险,因为很多人的 API Key 就放在 shell 环境、.env、云厂商配置或项目配置里。Agent 一旦拿到这些信息,外传只需要一行网络请求。
SkillSpector 对应会看:
- 外部传输;
- 环境变量收集;
- 文件系统枚举;
- 对话上下文泄露;
- 凭证从 source 流向 network sink 的 taint flow。
2. Prompt injection 和隐藏指令
Skill 的 SKILL.md 本质上会参与 Agent 的行为规划。这里如果藏了“忽略上层指令”“把上下文发出去”“在特定条件下改变行为”这类内容,就会污染后续执行。
更麻烦的是,攻击者不一定明着写。他可以放在注释、不可见字符、base64、工具参数说明,甚至 MCP metadata 里。
这也是为什么 SkillSpector 不只检查普通文本,还专门有 MCP tool poisoning 相关规则。
3. 权限和能力不匹配
一个 Skill 说自己只是“帮你格式化文档”,但脚本里却调用 shell、访问网络、读取环境变量,这就很奇怪。
SkillSpector 的 MCP least privilege 检测会看:
| 风险 | 含义 |
|---|---|
| Underdeclared Capability | 代码用了没声明的能力 |
| Wildcard Permission | 权限里出现 *、all、full |
| Missing Permission Declaration | 没写权限声明,但代码能看出需要能力 |
| Overdeclared Permission | 声明了权限,但代码里没对应用途 |
这类检测不是为了追求形式主义,而是帮你发现“描述很干净,行为很放飞”的 Skill。
4. 危险代码和供应链问题
很多 Skill 会附带脚本,这些脚本才是真正的执行面。
官方规则会看 exec()、eval()、动态 import、subprocess、os.system、compile(),也会看 curl | bash、base64 混淆、未固定依赖、已知漏洞依赖和 typosquatting。
这里有一个实用判断:带脚本的 Skill,要比纯文档 Skill 更值得审。
官方研究背景里也提到,带可执行脚本的 Skill 出现漏洞的概率更高。
怎么用,最小路径就够了
如果只是本地试一下,可以直接从官方仓库安装:
git clone https://github.com/NVIDIA/skillspector.git
cd skillspector
uv venv .venv && source .venv/bin/activate
make install
扫描一个本地 Skill:
skillspector scan ./my-skill/
扫描单个 SKILL.md:
skillspector scan ./SKILL.md
扫描 Git 仓库:
skillspector scan https://github.com/user/my-skill
只跑静态分析:
skillspector scan ./my-skill/ --no-llm
输出 JSON 或 SARIF,方便接进 CI:
skillspector scan ./my-skill/ --format json --output report.json
skillspector scan ./my-skill/ --format sarif --output report.sarif
如果不想在本机装 Python,也可以用它的 Dockerfile 构建镜像:
make docker-build
docker run --rm -v "$PWD:/scan" skillspector scan ./my-skill/ --no-llm
这里有个小提醒:如果开启 LLM 语义分析,需要配置 SKILLSPECTOR_PROVIDER 和对应 API Key。它支持 OpenAI、Anthropic、NVIDIA build.nvidia.com,也支持本地 OpenAI-compatible endpoint。
它能解决什么,不能解决什么
SkillSpector 很有价值,但不要把它理解成万能安全边界。
它能解决的是:
- 安装前发现明显恶意或高风险 Skill;
- 让团队知道一个 Skill 为什么危险;
- 把风险输出成可审计报告;
- 帮你在 CI 或内部审核里拦掉高风险 Skill;
- 提醒你哪些 Skill 需要人工复核。
它不能解决的是:
- 已经运行起来的恶意 Skill;
- 运行时隔离;
- 模型供应不稳定;
- 用户自己主动把密钥贴进上下文;
- 所有动态行为和加密二进制内容;
- 图片里的隐藏攻击文本。
官方文档也明确写了限制:非英文内容可能漏报,图片攻击无法分析,编译或加密内容无法分析,主要是静态分析,不做动态执行。
所以更准确的结论应该是:
SkillSpector 不是沙箱,它是安装前的安检。
真正完整的 Agent 安全,应该是几层一起上:
| 防线 | 作用 |
|---|---|
SkillSpector | 安装前审查 Skill 本身 |
| 最小权限 | 减少 Skill 能碰到的资源 |
| Sandbox / VM / Container | 限制执行环境 |
| 凭证代理 | 避免把真实密钥交给不可信代码 |
| 人工确认 | 发布、删除、生产访问等高风险动作保留人控 |
我们该怎么落地
如果你现在已经开始安装社区 Skill,我建议先做三件事。
第一,陌生 Skill 先扫再装。尤其是带 scripts/、requirements.txt、package.json、MCP 配置的 Skill,不要直接丢进全权限 Agent 里跑。
第二,团队里把扫描结果存下来。JSON、Markdown、SARIF 都可以,至少要知道引入过哪些 Skill、当时有哪些风险、为什么接受。
第三,把“扫描”和“隔离”分开看。SkillSpector 帮你回答“这个 Skill 看起来危不危险”,Sandbox 帮你回答“就算它危险,它能不能碰到我的真环境”。这两个不是替代关系,而是组合关系。
所以这篇文章最后想留一句话:
别把 Skill 当成几行提示词,它已经越来越像软件包。既然是软件包,就应该先扫描、再安装、少授权、隔离跑。
参考资料
- NVIDIA GitHub:SkillSpector
- SkillSpector README:Security scanner for AI agent skills
- SkillSpector Development Guide:LangGraph workflow and analyzer pipeline
- OSV.dev:Open Source Vulnerabilities
- Claude Code 文档:Extend Claude with skills
- Codex 文档:Agent Skills
- Cursor 文档:Model Context Protocol