RudrenduPaul/skillguard
GitHub: RudrenduPaul/skillguard
SkillGuard 是一款零认证、零配置的第三方 AI agent skill 文件安全扫描器,通过七类规则包在 skill 运行前检测已知攻击模式以拦截恶意行为。
Stars: 0 | Forks: 0
# SkillGuard
[](https://www.npmjs.com/package/skillguard-cli)
[](./LICENSE)
[](./CHANGELOG.md)
根据 Snyk 的数据,36% 已发布的 agent skill 存在可利用的漏洞。SkillGuard 会在 SKILL.md、hooks 和 scripts 运行之前扫描已知的攻击模式,并根据结果拦截你的 CI 流程。
第三方 AI agent skill 文件(`SKILL.md` manifests、hooks 以及打包的
scripts)在安装的那一刻起,就拥有了真实的 tool、文件和网络权限。大多数市场(marketplaces)和框架在“有人发布了一个 skill”到“用户的 agent 运行它”之间没有任何扫描步骤。SkillGuard 就是这个扫描步骤:作为一个 CLI、一个库以及一个 GitHub Action,它们全都读取相同的七个内置 rule pack。
## 立即尝试
```
npx skillguard-cli scan ./examples/known-bad-skill
```
这会针对仓库中内置的一个 fixture 运行扫描,该 fixture 是安全、无实际功能的,并且是刻意为了匹配模式而设计的,它会返回带有 file:line 引用的真实发现(findings)。每次扫描在开始前都会向 stderr 打印一条 "Loading SkillGuard rule packs..." 消息;这是预期行为,并非卡死。
将其与一个干净的 fixture 进行对比:
```
npx skillguard-cli scan ./examples/clean-skill
```
这会返回零个发现且退出代码为 0。
## 基准测试
下面的每一个数字都是我们实际运行过的,旁边显示了相应的命令,因此你可以自己重现:没有推断,也没有为了偏袒 SkillGuard 而进行四舍五入。
**首次扫描时间**(全新 clone、`npm install`、build、针对内置 fixture 的首次扫描),于 2026-07-13 基于 `build/v0.1` 测试得出:
```
git clone --branch build/v0.1 https://github.com/RudrenduPaul/skillguard.git
cd skillguard && npm install && npm run build
node dist/cli.js scan ./examples/known-bad-skill
```
| 阶段 | 耗时 |
| --- | --- |
| `git clone` | 0.9s |
| `npm install` | 1.3s |
| `npm run build` | 1.0s |
| 首次扫描 | 0.2s |
| **总计** | **~3.3s** |
这是一次单一、真实且带有时间戳的运行结果,基于处于活跃状态的本地 npm 缓存和快速的网络连接,并非多次运行的平均值。请将其视为一个下限:冷缓存或较慢的连接会使总耗时增加。`npx skillguard-cli`(一旦发布)会在上述“首次扫描”行的时间基础上,增加 npm 自身的解析和下载时间。
**已知恶意的 fixture**,`node dist/cli.js scan ./examples/known-bad-skill`:
11 个发现(5 个 HIGH,5 个 MEDIUM,1 个 LOW),涵盖了所有 7 个 rule 类别(SG01 到 SG07),分布于该 fixture 的 5 个 hook/script 文件中,退出代码为 1,实际耗时(wall time)0.155s。这个数字在 CSO 威胁模型通过更改默认抑制行为后进行了重新验证;发现数量和严重程度分布与修复前相比没有变化。
**干净的 fixture**,`node dist/cli.js scan ./examples/clean-skill` 和 `node dist/cli.js scan ./examples/clean-skill-python`:均为 0 个发现,退出代码为 0。这证实了 rule pack 在两个刻意设计为行为良好的 skill 上保持安静。请将其视为一个包含 2 个 fixture 的健全性检查:SkillGuard 尚未针对大量真实世界的 skill 进行过运行,因此这并不是一个通用的“0% 误报率”的声明。
**测试套件**:59/59 通过(`npm test`),包括针对每个文件 ReDoS 超时的真实、非 mock 的实际耗时回归测试。
**Rule 覆盖范围**:7 个第一方类别(SG01 到 SG07),在 [CHANGELOG.md](./CHANGELOG.md) 中逐条进行了记录。
## SkillGuard 的对比
SkillGuard 是专门为 agent skill 威胁模型构建的:frontmatter 声明的作用域与实际行为的对比、hook 级别的供应链风险,以及特定于 skill 打包和安装方式的凭据收集模式。这比通用扫描器的工作范围更窄,该表格对此进行了直白的表述,而不是暗示 SkillGuard 能胜过那些为不同工作而构建的工具。
| | SkillGuard | Snyk Agent Scan | Semgrep (CE) | Socket CLI | Snyk (Open Source/Code) |
| --- | --- | --- | --- | --- | --- |
| 扫描内容 | Agent-skill 文件:SKILL.md, hooks, scripts | Agent skill 和 MCP server 配置 | 通用源代码,支持 30 多种语言 | npm/PyPI 等包安装 | Manifest 声明的依赖项、源代码 |
| 特定于 Agent-skill 的规则集 | 是,专为该威胁模型构建的全部 7 个类别 | 是,其全部核心(prompt 注入、tool 投毒、恶意流程、skill 恶意软件) | 否,仅支持通用 SAST 规则 | 否,专注于供应链,不专注于 skill 文件 | 否,通用 SCA/SAST |
| 基础扫描是否需要 Auth | 不需要(`npx skillguard-cli scan `) | 需要,在任何扫描前需要 Snyk 账户和 `SNYK_TOKEN` | Community Edition 本地扫描不需要 | 需要,完整功能需要 `SOCKET_CLI_API_TOKEN` | 需要,需要 `snyk auth` |
| 运行时 | Node.js,无外部二进制文件 | 通过 `uvx` 使用 Python | 自有二进制文件(基于 Python 的 CLI) | Node.js | 自有 CLI |
| 许可证 | Apache 2.0 | Apache 2.0 | LGPL-2.1 | MIT | 专有 CLI,提供免费层级 |
| 成熟度(GitHub 星标数,于 2026-07-13 检查) | 全新(v0.1.0,预发布阶段) | 2.8k 星标,246 分支,100+ 次发布 | 15.9k 星标 | 295 星标 | 没有单一的开源仓库;商业产品 |
上述对比行的来源:[semgrep/semgrep](https://github.com/semgrep/semgrep)
和 [Semgrep CLI 文档](https://docs.semgrep.dev/getting-started/cli)(语言、
许可证、无需 auth 的本地扫描);[SocketDev/socket-cli](https://github.com/SocketDev/socket-cli)
(许可证、token 要求);[snyk/agent-scan](https://github.com/snyk/agent-scan)
(作用域、auth 要求、星标);[Snyk CLI 文档](https://docs.snyk.io/developer-tools/snyk-cli/snyk-cli-for-open-source)
(Snyk Open Source 扫描的内容)。
这里有一些诚恳的说明,因为一个安全工具的可信度取决于大声说出它的不足之处:
- **Snyk Agent Scan 是最接近的真实竞争对手。** 它扫描相同类型的目标(agent skill,加上 SkillGuard 未涵盖的 MCP server),并且总体上能检测出更多类别(15+ 对比 SkillGuard 的 7 个)。它也更成熟:2.8k 星标对比 SkillGuard 预发布的 v0.1.0。真正的区别在于安装和 auth 的方式:Snyk Agent Scan 在扫描任何内容之前,需要 Snyk 账户、API token 和 Python/`uv` 工具链,而 `npx skillguard-cli scan ` 运行时无需注册、无需 token,也没有非 Node 的运行时依赖。如果你已经拥有 Snyk 账户并且也需要 MCP-server 覆盖范围,Agent Scan 涵盖的范围更广。如果你想要一个零 auth、零配置的检查步骤并直接放入现有的基于 Node 的 CI pipeline 中,这正是 SkillGuard 的用途。
- **SkillGuard 没有封装 Semgrep。** 早期的一个设计阶段计划调用 Semgrep 作为底层引擎,但目前不存在官方的 npm 原生 Semgrep 包可供打包,而且依赖 Python/PyPI 发行版会破坏该工具所基于的零配置 `npx` 安装理念。`src/scan/semgrep-runner.ts` 在源代码中直接记录了这一偏差:SkillGuard 内置了自己的小型进程内模式引擎,该引擎使用相同的 rule-pack 结构(一个 manifest 加上一个规则文件),它受 Semgrep 启发,但并不是 Semgrep。如果你需要对 30 多种语言进行真正的多语言、通用静态分析,并且需要一个成熟的规则生态系统,那么 Semgrep 是更适合、也经过更多实战检验的工具;SkillGuard 并不打算取代它。
- **Socket CLI 是最接近的相邻类别,而不是直接的竞争对手。** 它在其专业领域表现出色(typosquat、恶意安装脚本、跨 npm/PyPI 等的可疑包行为),但它扫描的是已安装的*包*,而不是 SkillGuard 针对的 skill 自身 SKILL.md frontmatter 的结构、hooks 以及声明与实际行为之间的差异。
- **Snyk 本身就是依赖项和代码漏洞领域的类别领导者**,它拥有广泛的语言支持和成熟的企业级 Track record,这是 SkillGuard 和 Snyk Agent Scan 目前都无法宣称的。它自身没有特定于 skill 文件的规则集;这一空白正是 Snyk 自己的团队构建 Agent Scan 来弥补的。
## 安装
```
npm install --save-dev skillguard-cli
```
没有单独的安装步骤,也没有需要获取的外部二进制文件:SkillGuard 的七个 rule pack 和模式匹配引擎全都打包在 npm 包内部。
## CLI 用法
```
npx skillguard-cli scan [options]
```
| Flag | 默认值 | 描述 |
| --- | --- | --- |
| `--format ` | `human` | 输出格式。 |
| `--severity-threshold ` | `HIGH` | 导致扫描失败(退出代码 1)的最低严重级别。 |
| `--timeout ` | `10000` | 单个文件扫描超时时间(以毫秒为单位)。 |
| `--skillguardignore ` | 无,必须显式传递 | 抑制文件的路径。绝不会从扫描目标内部自动加载,请参阅[抑制发现](#suppressing-findings)。 |
| `--allow-inline-suppression` | `false` | 遵循在扫描文件内部发现的行内 `# skillguard-ignore: SGxx` 注释。默认关闭,详见下文。 |
**退出代码**:`0`,扫描通过。`1`,发现达到或超过严重级别阈值。`2`,目标路径不存在或未找到 skill 文件。
## 库用法(agent 原生)
```
import { scanSkill } from 'skillguard-cli';
const result = await scanSkill('./my-skill', { severityThreshold: 'HIGH' });
if (result.exitCode === 1) {
console.log(`${result.findings.length} finding(s) at or above HIGH`);
}
```
`scanSkill()` 运行与 CLI 相同的扫描逻辑,并返回结构化的
`ScanResult`(发现、超时、警告、退出代码),这对于希望以进程内方式调用 SkillGuard 而不是通过 shell 调用的 agent 框架非常有用。
## GitHub Action
```
- name: SkillGuard
uses: RudrenduPaul/skillguard@main
with:
path: ./my-skill
severity-threshold: HIGH
```
该 Action 默认使用 `--format sarif` 并将结果直接上传到
GitHub code scanning,无需任何配置。基础的 CLI 会保留人类可读的默认格式,因为终端和 CI 日志需要不同的东西。
## Rule pack
每个 rule pack 都位于 `rulepacks/` 目录下,并打包在 npm 包中,
在扫描时不会通过网络获取任何内容。
| 类别 | 名称 | 严重性 | 捕获内容 |
| --- | --- | --- | --- |
| SG01 | 网络不匹配 | MEDIUM | 原始套接字、netcat、`/dev/tcp`、绕过典型仅 HTTP 作用域的网络原语。 |
| SG02 | 远程代码执行 | HIGH | `curl \| bash`、对获取响应使用 `eval()`/`exec()`、使用受远程影响的内容进行 shell 调用。 |
| SG03 | 文件作用域提权 | MEDIUM | 写入/删除/`chmod` 超出了 skill 自身目录的范围。 |
| SG04 | hook 供应链 | HIGH | 获取并运行远程代码的安装时 hook 或依赖项,或固定到可变分支。 |
| SG05 | 混淆 payload | LOW | 用于隐藏 payload 的 base64/字符串拼接/动态 `Function` 惯用法。参见下文说明。 |
| SG06 | 凭据收集 | HIGH | 读取凭据形式的环境变量或凭据文件,特别是在网络调用附近。 |
| SG07 | frontmatter 伪造 | MEDIUM | SKILL.md 声明的网络/文件系统作用域与 hooks/scripts 实际操作之间的差异。 |
**SG05 已知限制**:与其它六个类别相比,在纯静态分析下进行混淆检测的漏报率要高得多。
SG05 会捕获已知的、常见的编码/eval 惯用法。请将其视为尽力而为的覆盖,而不是对混淆问题的完整解答。
## 抑制发现
**信任模型:** SkillGuard 的工作是审查你*没有*编写的目录。
以下两种抑制机制都可以使发现静默,因此它们都不会被扫描目标内部的内容自动信任。每一个都需要运行扫描的人员明确、谨慎地选择加入(opt-in)。
`.skillguardignore` 文件会按 glob 匹配抑制整个文件,其心智模型与 `.gitignore` 相同:
**仅当你传递 `--skillguardignore `**(或库选项 `ignoreFilePath`)时才会被遵循。
SkillGuard 绝不会自行读取位于扫描目标内部的
`.skillguardignore`。一个带有自身 `.skillguardignore` 的恶意 skill 提交,除非你明确将 SkillGuard 指向该文件,否则无法使关于自身的发现静默。
如果你自己维护一个 skill 并希望进行自我抑制,保留你的
`.skillguardignore` 并显式传递其路径:
```
npx skillguard-cli scan ./my-skill --skillguardignore ./my-skill/.skillguardignore
```
行内的 `# skillguard-ignore: SG02` 注释(在匹配所在的同一行,或者正上方的一行)会就地抑制单个发现。这默认
**处于关闭状态** 并且需要使用 `--allow-inline-suppression`,原因相同:该注释位于正在审查的确切不受信任的内容内部,因此默认情况下,扫描目标中的任何内容都不能使关于自身的发现静默。
仅对你已经信任的目标启用它,例如在发布前对你自己的 skill 进行自扫描。
## 已知限制
SkillGuard v0.1 特意公开记录了其存在的不足。
完整列表(包括残留的单模式 ReDoS 风险和 symlink 未被扫描也不会被跟踪的策略,这两者在无 worker 的同步 v0.1 版本中已经尽可能关闭,并计划在 v0.2 中进行真正的修复)位于 [CHANGELOG.md](./CHANGELOG.md) 中。在将 SkillGuard 接入你计划信任的 CI gate 之前,请先阅读它。
## 开发
```
npm install
npm run build
npm test
```
## 许可证
Apache 2.0,参见 [LICENSE](./LICENSE)。
标签:AI Agent安全, MITM代理, 域名收集, 暗色界面, 网络信息收集, 自动化攻击, 配置审计, 静态代码扫描