
SkillSpector v2.11.1
用于 AI 代理技能的安全扫描器。在安装 Claude Code、Codex 和 MCP 技能之前,检测其中的漏洞、恶意模式、安全风险、提示注入、数据外泄和供应链风险。
SkillSpector
AI 代理技能安全扫描器。 在安装代理技能之前检测漏洞、恶意模式和安全风险。
概述
AI 代理技能(供 Claude Code、Codex CLI、Gemini CLI 等使用)在隐式信任和极少审查的情况下执行。研究表明,26.1% 的技能包含漏洞,5.2% 表现出可能的恶意意图。
SkillSpector 帮助您回答:“这个技能安装安全吗?”
SkillSpector 是 NVIDIA Verified Skills 流水线 的一部分,该流水线在发布前对代理技能进行扫描、评估和签名。通过验证的技能会发布到 NVIDIA 技能目录。
文档
- 安装前扫描代理技能 — 托管指南:何时扫描、如何阅读报告以及如何管控安装。
- 开发指南 — 架构、包布局以及如何扩展分析器流水线。
- 分析资源上限 — 失败关闭的捆绑包、解析器、嵌套工件、账本和发现结果上限。
- Pi 扩展 — 将 SkillSpector 安装为 Pi 工具,以便在代理会话内扫描技能。
功能特性
- 多格式输入:扫描 Git 仓库、URL、zip 文件、目录或单个文件
- 17 个类别中的 71 种漏洞模式:提示注入、数据外泄、权限提升、供应链、过度代理权限、输出处理、系统提示泄露、记忆投毒、工具滥用、恶意代理、拒绝抵抗、触发器滥用、危险代码(AST)、污点跟踪、YARA 签名、MCP 最小权限和 MCP 工具投毒
- 两阶段分析:快速静态分析 + 可选的 LLM 语义评估
- 实时漏洞查询:SC4 查询 OSV.dev 获取实时 CVE 数据,并自动离线回退
- 多种输出格式:终端、JSON、Markdown 和 SARIF 报告
- 风险评分:0-100 分,附带严重性标签和明确建议
- 基线 / 误报抑制:通过 glob 规则或指纹基线接受已知发现结果,使重新扫描仅显示新的问题(文档)
快速开始
安装
开源软件声明: 本项目将下载并安装额外的第三方开源软件项目。使用前请审阅这些开源项目的许可条款。
首先创建并激活虚拟环境(所有 make 目标均假定 venv 已激活)。使用 uv 或 pip;Makefile 在可用时使用 uv,否则使用 pip。
使用 uv 快速安装(仅 CLI):```bash uv tool install git+https://github.com/NVIDIA/skillspector.git
Update later: uv tool update skillspector
如果你打算运行 `skillspector mcp`,请在安装时安装 MCP 附加组件:```bash
uv tool install 'skillspector[mcp] @ git+https://github.com/NVIDIA/skillspector.git'
From source:```bash
Clone the repository
git clone https://github.com/NVIDIA/skillspector.git cd skillspector
Create and activate virtual environment
uv venv .venv && source .venv/bin/activate
or: python3 -m venv .venv && source .venv/bin/activate
Install for production use
make install
Or install with development dependencies
make install-dev
### Docker(无需 Python)
通过本地构建随附的 [Dockerfile](https://github.com/nvidia/skillspector/blob/main/Dockerfile) 来运行 SkillSpector,无需安装 Python。该镜像基于 Docker 官方 Python `3.12-slim-bookworm` 镜像。
**构建镜像:**```bash
make docker-build
# or: docker build -t skillspector .
扫描本地目录:将当前目录挂载到容器的 /scan(工作目录)中:```bash
docker run --rm -v "$PWD:/scan" skillspector scan ./my-skill/ --no-llm
**使用 LLM 分析进行扫描**,通过本地 `.env` 文件传递凭据:```bash
cat > .env <<'EOF'
SKILLSPECTOR_PROVIDER=anthropic
ANTHROPIC_API_KEY=sk-ant-...
EOF
好的,我将按照您的要求,将这段英文内容翻译成中文,并严格遵循所有规则。
注意: 您提供的输入内容为空。因此,我无法进行翻译。请提供需要翻译的文本内容。```bash
docker run --rm
-v "$PWD:/scan"
--env-file .env
skillspector scan ./my-skill/
或者直接从你的 shell 环境中传入凭据:```bash
docker run --rm \
-v "$PWD:/scan" \
-e SKILLSPECTOR_PROVIDER=anthropic \
-e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
skillspector scan ./my-skill/
将报告写入主机文件系统,方法是写入挂载的目录:```bash
docker run --rm
-v "$PWD:/scan"
skillspector scan ./my-skill/ --no-llm --format json --output report.json
**可选别名**,用于重复的静态扫描:```bash
alias skillspector-docker='docker run --rm -v "$PWD:/scan" skillspector'
skillspector-docker scan ./my-skill/ --no-llm
基本用法```bash
Scan a local skill directory
skillspector scan ./my-skill/
Scan a single SKILL.md file
skillspector scan ./SKILL.md
Scan a Git repository
skillspector scan https://github.com/user/my-skill
Scan a zip file
skillspector scan ./my-skill.zip
#### 大小限制
SkillSpector 对远程输入和归档输入实施两项独立的限制,以约束超大下载和压缩包炸弹(zip bomb)的影响:
- **每次摄取上限**:`INGEST_MAX_BYTES`(100 MiB)——适用于流式 URL 下载、压缩包解压后的总大小,以及 Git 仓库克隆后的磁盘占用。
- **压缩包成员上限**:`INGEST_MAX_ZIP_MEMBERS`(10,000)——限制单个压缩包中的条目数量。
请注意,每文件 1 MB 的分析上限(`MAX_FILE_BYTES`)是一个独立的下游限制:它约束的是各个分析器从已摄取目录中读取的内容量。而上述摄取上限约束的是内容最初能够落盘的量。违反任一摄取上限都会以 `IngestLimitExceededError` 错误安全关闭(fail closed)。
### 输出格式```bash
# Terminal output (default) - pretty formatted
skillspector scan ./my-skill/
# JSON output - machine readable
skillspector scan ./my-skill/ --format json --output report.json
# Markdown output - for documentation
skillspector scan ./my-skill/ --format markdown --output report.md
# SARIF output - for CI/CD integration and IDE tooling
skillspector scan ./my-skill/ --format sarif --output report.sarif
批量扫描
从 contrib/batch_scan/ 并行扫描整个技能目录:```bash
python -m contrib.batch_scan.batch_scan ./my-skills/ --no-llm
python -m contrib.batch_scan.batch_scan ./my-skills/ --workers 20 -f json -o report.json
python -m contrib.batch_scan.batch_scan ./tests/fixtures/ -f terminal --workers 20
支持多语言检测(zh/ja/ko),并支持终端/JSON/Markdown 输出。
对于并发更高的 LLM 扫描,可按照
[`.env.example`](https://github.com/nvidia/skillspector/blob/main/contrib/batch_scan/.env.example) 配置多个 API 密钥——只要这些密钥不共享账户级速率限制,密钥池即可提升吞吐量和韧性。
详见 [contrib 指南](https://github.com/nvidia/skillspector/blob/main/contrib/batch_scan/docs)。
> **关于 LLM 支持的说明:** 默认配置以 DeepSeek 为目标,因为它是
> 最便宜的公开选项。DeepSeek-Chat 预计将
> [停止服务](https://api-docs.deepseek.com/),而贡献者没有硬件来针对本地模型进行测试。批量扫描器最初是
> 针对 OpenAI 兼容端点进行测试的——DeepSeek 缺乏
> 结构化输出支持,因此需要手动修补 JSON 解析。如果你能贡献一个更通用的后端(Ollama、vLLM 或其他提供商),
> 非常欢迎提交 PR。
### 抑制误报(基线)
抑制已知/已接受的结果,使风险评分仅反映未分类的问题,
并且重新扫描时只显示*新的*结果。完整参考请参阅
[抑制指南](https://github.com/nvidia/skillspector/blob/main/docs/SUPPRESSION.md)。```bash
# Accept all current findings into a baseline (run once), then commit it.
skillspector baseline ./my-skill/ -o .skillspector-baseline.yaml
# Scan against the baseline — only NEW findings are reported and scored.
skillspector scan ./my-skill/ --baseline .skillspector-baseline.yaml
# Review what was suppressed (still excluded from the score).
skillspector scan ./my-skill/ --baseline .skillspector-baseline.yaml --show-suppressed
基线也可以使用容错性通配规则(按规则 ID、文件路径或消息)——参见 .skillspector-baseline.example.yaml。
精确指纹基线以证据为约束:更改被扫描的源或 SkillSpector 版本后,该发现会保持激活状态,直到再次被审查。
当选定的基线或基线输出存储在技能目录内时,SkillSpector 会将该确切文件排除在内容分析之外,因此其抑制文本无法产生发现或进入重新生成的指纹;同级文件仍处于正常扫描范围内。
LLM 分析
为获得最佳结果,请为语义分析配置一个兼容 OpenAI 的 LLM 端点。使用 SKILLSPECTOR_PROVIDER 选择提供商;托管提供商附带捆绑的默认模型,而 CLI 提供商则回退到本地运行时的默认模型,除非设置了 SKILLSPECTOR_MODEL。SkillSpector 也适用于本地兼容 OpenAI 的服务器(Ollama、vLLM、llama.cpp)以及托管推理网关。
提供商(SKILLSPECTOR_PROVIDER) | 凭据环境变量 | 端点 | 默认模型 |
|---|---|---|---|
openai | OPENAI_API_KEY(+ 可选的 OPENAI_BASE_URL) | api.openai.com(或任何兼容 OpenAI 的 URL) | gpt-5.4 |
anthropic | ANTHROPIC_API_KEY | api.anthropic.com | claude-opus-4-6 |
anthropic_proxy | ANTHROPIC_PROXY_API_KEY + ANTHROPIC_PROXY_ENDPOINT_URL | 任何 Vertex 风格的 raw-predict 代理 | claude-sonnet-4-6 |
bedrock | AWS_PROFILE(可选)+ AWS_REGION — 通过 boto3 进行 SigV4 签名 | AWS Bedrock Runtime | us.anthropic.claude-sonnet-4-6-20250915-v1:0 |
nv_build | NVIDIA_INFERENCE_KEY | build.nvidia.com | deepseek-ai/deepseek-v4-flash |
claude_cli | (无 — 使用本地 CLI 认证) | 本地 claude 二进制文件 | 本地 Claude 运行时回退,或 SKILLSPECTOR_MODEL |
codex_cli | (无 — 使用本地 CLI 认证) | 本地 codex 二进制文件 | 本地 Codex 运行时回退,或 SKILLSPECTOR_MODEL |
Stock OpenAI
export SKILLSPECTOR_PROVIDER=openai export OPENAI_API_KEY=sk-... skillspector scan ./my-skill/
Anthropic
export SKILLSPECTOR_PROVIDER=anthropic export ANTHROPIC_API_KEY=sk-ant-... skillspector scan ./my-skill/
Anthropic via Vertex-style proxy (corporate gateways, GCP Vertex AI)
export SKILLSPECTOR_PROVIDER=anthropic_proxy export ANTHROPIC_PROXY_ENDPOINT_URL=https://my-gateway.example.com/models/claude-sonnet-4-6:streamRawPredict export ANTHROPIC_PROXY_API_KEY=your-bearer-token export SKILLSPECTOR_MODEL=claude-sonnet-4-6 skillspector scan ./my-skill/
AWS Bedrock (Claude via SigV4)
export SKILLSPECTOR_PROVIDER=bedrock
Optional: select an AWS named profile. When unset, the standard
boto3 credential chain (env vars, instance metadata, SSO, etc.) resolves.
export AWS_PROFILE=my-profile
export AWS_REGION=us-west-2 # default if unset
Default model: us.anthropic.claude-sonnet-4-6-20250915-v1:0
Override with any Bedrock model ID, cross-region inference-profile
ID, or your own application-inference-profile ARN:
export SKILLSPECTOR_MODEL=us.anthropic.claude-opus-4-6-20250915-v1:0
skillspector scan ./my-skill/
NVIDIA build.nvidia.com
export SKILLSPECTOR_PROVIDER=nv_build export NVIDIA_INFERENCE_KEY=nvapi-... skillspector scan ./my-skill/
Local Claude CLI — no API key; uses your existing claude auth login session
Requires: claude CLI installed and authenticated (claude auth login)
export SKILLSPECTOR_PROVIDER=claude_cli
Uses the local Claude CLI runtime fallback unless SKILLSPECTOR_MODEL is set.
export SKILLSPECTOR_MODEL=claude-sonnet-4-6
skillspector scan ./my-skill/
Local Codex CLI — no API key; uses your existing codex login session
Requires: codex CLI installed and authenticated
export SKILLSPECTOR_PROVIDER=codex_cli skillspector scan ./my-skill/
Local Ollama or any OpenAI-compatible endpoint
export SKILLSPECTOR_PROVIDER=openai export OPENAI_API_KEY=ollama export OPENAI_BASE_URL=http://localhost:11434/v1 export SKILLSPECTOR_MODEL=llama3.1:8b skillspector scan ./my-skill/
Override the provider's default model
export SKILLSPECTOR_MODEL=gpt-5.2 skillspector scan ./my-skill/
Skip LLM analysis (faster, static analysis only)
skillspector scan ./my-skill/ --no-llm
### MCP 服务器
将 SkillSpector 作为 [Model Context Protocol](https://modelcontextprotocol.io)
服务器运行,使任何支持 MCP 的代理(Claude Code、Codex CLI、Gemini CLI)或远程
运行时都能将扫描作为工具调用,并**根据结果对技能/MCP 安装进行门控**——从而将 SkillSpector 转变为运行时护栏,而非带外审计步骤。
`skillspector mcp` 需要 `skillspector[mcp]`。```bash
# Install, or reinstall if you already used the CLI-only path
uv tool install --force 'skillspector[mcp] @ git+https://github.com/NVIDIA/skillspector.git'
# FastMCP stdio transport for local CLI agents
skillspector mcp
# streamable HTTP/SSE transport for remote / A2A callers
skillspector mcp --transport http --host 127.0.0.1 --port 8000
stdio 传输是当前 FastMCP 用于本地 CLI 代理的路径,而 issue #199 中报告的 initialize 挂起问题在该路径下仍然存在。
该服务器暴露了一个单一工具:
scan_skill(target, use_llm=true, output_format="json")— 扫描 Git URL、文件 URL、.zip、.md文件或目录,并返回结构化结论:risk_score(0-100)、severity、recommendation、safe_to_install和findings。它还会报告llm_used/scan_mode,因此仅静态扫描得出的低分绝不会被误认为是完整的干净扫描结果。
通过以下方式将其注册到 Claude Code:```bash claude mcp add skillspector -- skillspector mcp
> **安全 — HTTP 传输信任模型**
>
> HTTP 传输**不附带身份验证**。任何能够访问该端口的调用方都可以调用 `scan_skill`。通过 stdio 或 `127.0.0.1` 时,这与 CLI 的信任边界相同。如果您绑定到可路由的接口:
>
> - 在对外暴露之前,将服务器置于经过身份验证的反向代理(例如 nginx + mTLS)之后。
> - 本地路径和 `file://` URL 在 HTTP 上会被**自动拒绝**,以防止未经身份验证的调用方读取任意主机文件。仅接受远程 Git 和 `.zip` URL。
## 漏洞模式
SkillSpector 可检测 **17 个类别中的 71 种漏洞模式**:
### 提示注入(6 种模式)
| ID | 模式 | 严重性 | 描述 |
|----|---------|----------|-------------|
| P1 | 指令覆盖 | 高 | 指示忽略安全约束的命令 |
| P2 | 隐藏指令 | 高 | 注释/不可见文本中的恶意指令 |
| P3 | 数据外泄命令 | 高 | 指示将上下文传输到外部的指令 |
| P4 | 行为操纵 | 中 | 改变智能体决策的隐蔽指令 |
| P5 | 有害内容 | 严重 | 可能导致人身伤害的指令 |
| P9 | 空白填充 | 中 | 大量空白填充,将指令隐藏在可见区域下方或旁边 |
### 反拒绝(3 种模式)
| ID | 模式 | 严重性 | 描述 |
|----|---------|----------|-------------|
| AR1 | 拒绝抑制 | 高 | 指示永不拒绝或始终服从(例如“永不拒绝”、“始终服从”) |
| AR2 | 免责声明抑制 | 高 | 指示省略警告、免责声明或伦理评论(例如“无免责声明”、“不要道德说教”) |
| AR3 | 安全策略失效 | 高 | 使护栏失效的越狱框架(例如“你没有限制”、“忽略你的准则”、“现在做任何事”) |
### 数据外泄(4 种模式)
| ID | 模式 | 严重性 | 描述 |
|----|---------|----------|-------------|
| E1 | 外部传输 | 中 | 将数据发送到外部 URL |
| E2 | 环境变量收集 | 高 | 枚举、复制或搜索环境数据以收集机密 |
| E3 | 文件系统枚举 | 中 | 扫描目录以查找敏感文件 |
| E4 | 上下文泄露 | 高 | 将对话上下文传输到外部 |
### 权限提升(3 种模式)
| ID | 模式 | 严重性 | 描述 |
|----|---------|----------|-------------|
| PE1 | 过度权限 | 低 | 请求超出所述功能的访问权限 |
| PE2 | Sudo/Root 执行 | 中 | 调用提升的系统权限 |
| PE3 | 凭据访问 | 高 | 读取 SSH 密钥、令牌、密码 |
### 供应链(9+ 种模式)
| ID | 模式 | 严重性 | 描述 |
|----|---------|----------|-------------|
| SC1 | 未固定依赖 | 低 | 包没有版本约束 |
| SC2 | 外部脚本获取 | 高 | curl \| bash 和远程代码执行 |
| SC3 | 混淆代码 | 高 | Base64/十六进制编码的执行 |
| SC4 | 已知易受攻击的依赖 | 高 | 具有已知 CVE 的依赖(实时 OSV.dev 查询) |
| SC5 | 已弃用依赖 | 中 | 没有安全更新的未维护包 |
| SC6 | 域名仿冒 | 高 | 与流行包相似的包名 |
| SC8 | 附带 Python 字节码 | 高 | 存在 `__pycache__` / `.pyc`(发现过程会跳过;恶意字节码可绕过) |
| SC9 | 隐藏的可执行工件 | 高 | 嵌套在文档容器中或隐藏/伪装的工件中的可执行文件 |
### 过度自主权(5 种模式)
| ID | 模式 | 严重性 | 描述 |
|----|---------|----------|-------------|
| EA1 | 不受限制的工具访问 | 高 | 无约束地访问工具 |
| EA2 | 自主决策 | 高 | 没有人在环的高影响决策 |
| EA3 | 范围蔓延 | 中 | 能力超出所述目的 |
| EA4 | 无限制的资源访问 | 中 | 资源消耗没有速率限制或配额 |
| EA5 | 外部模型或提供商选择 | 中/高 | 模型/提供商固定或编码 CLI shell 调用,可切换计费账户 |
### 输出处理(3 种模式)
| ID | 模式 | 严重性 | 描述 |
|----|---------|----------|-------------|
| OH1 | 未验证的输出注入 | 高 | 模型输出未经净化即被使用 |
| OH2 | 跨上下文输出 | 中 | 输出未经验证即跨越信任边界流动 |
| OH3 | 无界输出 | 中 | 输出大小或生成速率没有限制 |
### 系统提示泄露(3 种模式)
| ID | 模式 | 严重性 | 描述 |
|----|---------|----------|-------------|
| P6 | 直接泄露 | 高 | 暴露系统提示或内部规则的指令 |
| P7 | 间接提取 | 中 | 通过改写、翻译或侧信道提取 |
| P8 | 基于工具的外泄 | 高 | 通过文件写入或网络请求外泄系统提示 |
### 记忆投毒(3 种模式)
| ID | 模式 | 严重性 | 描述 |
|----|---------|----------|-------------|
| MP1 | 持久上下文注入 | 高 | 旨在跨交互持久化的内容 |
| MP2 | 上下文窗口填充 | 中 | 挤占安全约束的填充内容 |
| MP3 | 记忆操纵 | 高 | 篡改智能体记忆或存储状态 |
### 工具滥用(3 种模式)
| ID | 模式 | 严重性 | 描述 |
|----|---------|----------|-------------|
| TM1 | 工具参数滥用 | 高 | 为意外行为构造的参数(shell=True、--force) |
| TM2 | 链式滥用 | 高 | 绕过单个安全检查的工具链 |
| TM3 | 不安全的默认值 | 中 | 过度宽松的默认值(禁用 TLS、无身份验证) |
### 恶意智能体(2 种模式)
| ID | 模式 | 严重性 | 描述 |
|----|---------|----------|-------------|
| RA1 | 自我修改 | 严重 | 在运行时修改自身代码或配置 |
| RA2 | 会话持久化 | 高 | 通过 cron 作业或启动脚本进行未经授权的持久化 |
### 触发器滥用(3 种模式)
| ID | 模式 | 严重性 | 描述 |
|----|---------|----------|-------------|
| TR1 | 过宽的触发器 | 中 | 匹配常见单词的触发模式 |
| TR2 | 影子命令触发器 | 高 | 遮蔽内置命令或其他技能的触发器 |
| TR3 | 关键词诱饵触发器 | 中 | 旨在最大化激活的通用触发器 |
### 行为 AST(9 种模式)
| ID | 模式 | 严重性 | 描述 |
|----|---------|----------|-------------|
| AST1 | exec() 调用 | 严重 | 直接 exec() 实现任意代码执行 |
| AST2 | eval() 调用 | 高 | 直接 eval() 评估任意表达式 |
| AST3 | 动态导入 | 高 | \_\_import\_\_() 在运行时加载任意模块 |
| AST4 | subprocess 调用 | 高 | 通过 subprocess 执行外部命令 |
| AST5 | os.system / exec 系列 | 高 | 通过 os 模块执行 shell 命令 |
| AST6 | compile() 调用 | 中 | 从字符串创建代码对象 |
| AST7 | 动态 getattr() | 中 | 使用非字面量名称进行任意属性访问 |
| AST8 | 危险执行链 | 严重 | exec/eval 与动态源(网络、编码数据)结合 |
| AST9 | 反射式 getattr() 汇聚点 | 高 | 通过 `getattr(os,'system')` / `getattr(builtins,'exec')` 进行反射式 exec,可绕过 AST1/AST5 |
### 污点跟踪(5 种模式)
| ID | 模式 | 严重性 | 描述 |
|----|---------|----------|-------------|
| TT1 | 直接污点流 | 高 | 数据未经净化直接从源流向汇聚点 |
| TT2 | 变量介导的污点流 | 中 | 数据通过中间变量从源流向汇聚点 |
| TT3 | 凭据外泄链 | 严重 | 凭据(环境变量、机密)流向网络输出汇聚点 |
| TT4 | 文件读取到网络外泄 | 高 | 文件内容流向网络输出汇聚点 |
| TT5 | 外部输入到代码执行 | 严重 | 网络或用户输入流向 exec/eval/subprocess 汇聚点 |
### YARA 签名(4 种模式)
| ID | 模式 | 严重性 | 描述 |
|----|---------|----------|-------------|
| YR1 | 恶意软件匹配 | 严重 | 已知恶意软件签名的 YARA 规则匹配 |
| YR2 | WebShell 匹配 | 严重 | WebShell 模式的 YARA 规则匹配 |
| YR3 | 挖矿程序匹配 | 高 | 加密货币挖矿指标的 YARA 规则匹配 |
| YR4 | 黑客工具/漏洞利用匹配 | 高 | 黑客工具或漏洞利用代码的 YARA 规则匹配 |
### MCP 最小权限(4 种模式)
| ID | 模式 | 严重性 | 描述 |
|----|---------|----------|-------------|
| LP1 | 未声明的能力 | 高 | 代码使用了声明的权限中未列出的能力 |
| LP2 | 通配符权限 | 中 | 权限列表包含通配符(\*、all、full、any) |
| LP3 | 缺少权限声明 | 中 | 没有权限字段,但代码具有可检测的能力 |
| LP4 | 过度声明的权限 | 低 | 声明了权限,但未找到相应的代码能力 |
### MCP 工具投毒(4 种模式)
| ID | 模式 | 严重性 | 描述 |
|----|---------|----------|-------------|
| TP1 | 隐藏指令 | 高 | 元数据中的隐藏指令(HTML 注释、零宽字符、base64、数据 URI) |
| TP2 | Unicode 欺骗 | 高 | 工具元数据中的同形字、RTL 覆盖、混合脚本标识符 |
| TP3 | 参数描述注入 | 中 | 参数定义中的注入模式(覆盖、系统令牌、恶意默认值) |
| TP4 | 描述-行为不匹配 | 中 | 声明的工具描述与实际代码行为不匹配(LLM 驱动) |
所有检测到的模式均列在上面的表格中。
## 风险评分
### 分数计算
- **严重**问题:+50 分
- **高**问题:+25 分
- **中**问题:+10 分
- **低**问题:+5 分
- **可执行脚本**:1.3 倍乘数
### 严重性级别
| 分数 | 严重性 | 建议 |
|-------|----------|----------------|
| 0-20 | 低 | 安全 |
| 21-50 | 中 | 谨慎 |
| 51-80 | 高 | 请勿安装 |
| 81-100 | 严重 | 请勿安装 |
## 示例输出
### 终端输出```
SkillSpector Security Report v2.0.0
Skill: suspicious-skill
Source: ./suspicious-skill/
Scanned: 2026-01-29 10:30:00 UTC
Risk Assessment
Metric Value
Score 78/100
Severity HIGH
Recommendation DO NOT INSTALL
Components (3)
File Type Lines Executable
SKILL.md markdown 142 No
scripts/sync.py python 87 Yes
requirements.txt text 3 No
Issues (2)
HIGH: Env Variable Harvesting (E2)
Location: scripts/sync.py:23
Finding: for key, val in os.environ.items():...
Confidence: 94%
Explanation: This code collects environment variables containing
API keys and secrets, then sends them to an external server.
HIGH: External Transmission (E1)
Location: scripts/sync.py:45
Finding: requests.post("https://api.skill.io/env"...
Confidence: 89%
Explanation: Data is being sent to an external server. Combined
with env harvesting above, this indicates credential exfiltration.
配置
环境变量
| 变量 | 描述 | 是否必需 |
|---|---|---|
SKILLSPECTOR_PROVIDER | 活跃的 LLM 提供商:openai、anthropic、anthropic_proxy、bedrock、nv_build、claude_cli、codex_cli 或 gemini_cli。托管提供商使用捆绑的 model_registry.yaml 默认值;claude_cli 和 codex_cli 回退到本地 CLI 运行时的默认模型,除非设置了 SKILLSPECTOR_MODEL。默认为 nv_build。 | 可选 |
NVIDIA_INFERENCE_KEY | nv_build 提供商(build.nvidia.com)的凭据。 | 当 SKILLSPECTOR_PROVIDER=nv_build 时,LLM 分析必需 |
OPENAI_API_KEY | OpenAI 提供商(SKILLSPECTOR_PROVIDER=openai)的凭据。当活跃提供商未返回凭据时,也作为凭据瀑布流中的二级回退。 | 当 SKILLSPECTOR_PROVIDER=openai 时,LLM 分析必需 |
OPENAI_BASE_URL | 覆盖 OpenAI 端点(例如指向 Ollama)。 | 可选 |
SKILLSPECTOR_REASONING_EFFORT | 可选的、依赖提供商和模型的推理努力设置。非空值会被修剪并原样传递;未设置或空白则保留提供商默认行为。 | 可选 |
SKILLSPECTOR_OUTPUT_LANGUAGE | 简短的单行语言标签(字母、数字、空格、_ 或 -;最多 64 个字符),用于人类可读的 LLM 发现文本,如消息、解释和修复建议。规则 ID、严重性值、路径、代码和其他机器可读值保持不变。未设置、空白或无效值保留默认输出语言。 | 可选 |
SKILLSPECTOR_TEMPERATURE | 托管提供商的可选采样温度,范围从 0 到 1。未设置或空白则保留提供商默认值。较低的值可以减少运行间差异,但不保证输出完全一致。 | 可选 |
SKILLSPECTOR_SEED | 用于 OpenAI 兼容和 Azure OpenAI 提供商的可选整数采样种子。其他托管提供商和 CLI 提供商不会收到该值。提供商支持仍取决于模型。 | 可选 |
ANTHROPIC_API_KEY | Anthropic 提供商(SKILLSPECTOR_PROVIDER=anthropic)的凭据。 | 当 SKILLSPECTOR_PROVIDER=anthropic 时,LLM 分析必需 |
ANTHROPIC_BASE_URL | 覆盖原生 Anthropic 端点(默认:https://api.anthropic.com)。 | 可选 |
ANTHROPIC_PROXY_ENDPOINT_URL | Anthropic 代理提供商(Vertex 风格 raw-predict)的完整端点 URL。 | 当 SKILLSPECTOR_PROVIDER=anthropic_proxy 时必需 |
ANTHROPIC_PROXY_API_KEY | Anthropic 代理提供商的 Bearer 令牌。 | 当 SKILLSPECTOR_PROVIDER=anthropic_proxy 时必需 |
ANTHROPIC_PROXY_API_VERSION | 在请求体中发送的 anthropic_version 值(默认:vertex-2023-10-16)。 | 可选 |
AWS_PROFILE | Bedrock 提供商的命名 AWS 配置文件——通过 boto3 使用 SigV4 进行身份验证。未设置时,使用标准 boto3 凭据链(环境变量、实例元数据、SSO 等)解析。 | 可选(当 SKILLSPECTOR_PROVIDER=bedrock 时使用) |
AWS_REGION | Bedrock Runtime 端点的 AWS 区域。默认为 us-west-2。 | 可选(当 SKILLSPECTOR_PROVIDER=bedrock 时使用) |
SKILLSPECTOR_MODEL | 覆盖活跃提供商的模型。对于托管提供商,这会替换 LLM 分析表中的捆绑默认值。对于 claude_cli 和 codex_cli,这会作为 --model 转发,而不是使用本地 CLI 运行时回退。 | 可选 |
SKILLSPECTOR_MODEL_REGISTRY | 使用自定义路径覆盖捆绑的按提供商 YAML 注册表(src/skillspector/providers/<provider>/model_registry.yaml)。 | 可选 |
SKILLSPECTOR_LOG_LEVEL | 日志级别:DEBUG、INFO、WARNING、ERROR(默认:WARNING)。 | 可选 |
CLI 提供商(
claude_cli、codex_cli):无需 API 密钥。身份验证完全由代理 CLI 自身的登录会话管理(claude auth login/codex login)。当这些提供商处于活跃状态时,SkillSpector 从不读取或转发 API 密钥。子进程在加固的沙箱中运行:工具被禁用、无 MCP、只读沙箱模式(codex),且不受信任的技能内容仅通过 stdin 传递。
CLI 选项```bash
skillspector scan --help
Options: -f, --format [terminal|json|markdown|sarif] Output format [default: terminal] -o, --output PATH Output file path --no-llm Skip LLM analysis (static only) --yara-rules-dir PATH Extra YARA rules directory -b, --baseline PATH Suppress findings listed in a baseline --show-suppressed List baseline-suppressed findings -V, --verbose Show detailed progress --help Show this message and exit
Generate a baseline of all current findings (see docs/SUPPRESSION.md)
skillspector baseline [-o FILE] [--no-llm] [--reason TEXT]
## 集成 SkillSpector
SkillSpector 的设计目标是由其他工具驱动(CI 流水线、安装门禁、编辑器集成)。其退出码和 JSON 输出是一份稳定的契约。
### 退出码
`skillspector scan` 的退出码如下:
| 代码 | 含义 |
|------|---------|
| `0` | 扫描完成,`risk_score` ≤ 50(建议为 `SAFE` 或 `CAUTION`) |
| `1` | 扫描完成,`risk_score` > 50(建议为 `DO_NOT_INSTALL`) |
| `2` | 错误(输入无效、源不可读、内部故障) |
> 退出码将 `SAFE` 和 `CAUTION` 合并为 `0`。若需对它们采取不同操作(例如对 `CAUTION` 发出*警告*,但对 `DO_NOT_INSTALL` 进行*阻止*),请读取 JSON 输出中的 `recommendation` 字段,而非依赖退出码。
### 机器可读输出
`--format json` 会生成 JSON 报告;若未指定 `--output`/`-o`,则写入标准输出:```bash
skillspector scan ./my-skill/ --format json
顶层结构如下(此示例展示了一次完整的、由 LLM 支持的扫描;若使用 --no-llm,则 metadata.llm_requested 为 false):```json
{
"skill": { "name": "...", "source": "...", "scanned_at": "<ISO 8601>" },
"risk_assessment": { "score": 0, "severity": "LOW", "recommendation": "SAFE" },
"components": [ { "path": "...", "type": "...", "lines": 0, "executable": false, "size_bytes": 0 } ],
"issues": [ { "id": "...", "category": "...", "severity": "...", "confidence": 0.0, "location": { "file": "...", "start_line": 0 } } ],
"metadata": {
"has_executable_scripts": false,
"skillspector_version": "...",
"llm_requested": true,
"llm_available": true,
"inference_usage": [
{
"node": "semantic_security_discovery",
"request_kind": "structured_output",
"provider": "nv_inference",
"model": "azure/anthropic/claude-opus-4-6",
"model_source": "provider_response",
"usage_source": "provider_response",
"prompt_tokens": 1000,
"completion_tokens": 100,
"cached_tokens": 400,
"cache_write_tokens": 50,
"total_tokens": 1100
}
]
}
}
- `risk_assessment.severity` ∈ `LOW | MEDIUM | HIGH | CRITICAL`。
- `risk_assessment.recommendation` ∈ `SAFE | CAUTION | DO_NOT_INSTALL`,由严重性映射而来:`LOW → SAFE`,`MEDIUM → CAUTION`,`HIGH`/`CRITICAL → DO_NOT_INSTALL`。
- `metadata.llm_error` 仅在请求了 LLM 分析但不可用时出现。
- `metadata.inference_usage` 在提供方暴露令牌计数器时,包含每条 LLM 响应的一条脱敏记录。当使用情况不可用时,它是一个空列表;SkillSpector 从不估算缺失的令牌。提示词总计包含缓存读取和写入,以便下游定价能够安全地分离这些分区。
`model_source` 区分独立识别的提供方模型与在响应身份缺失或模糊时使用的确切请求模型。
SkillSpector 目前不发送 Anthropic 提示词缓存控制,因此其扫描请求无法选择单独的 5 分钟或 1 小时缓存写入层级;TTL 特定的响应字段会被防御性地归一化到聚合的缓存写入计数器中。
- 有关完整的来源、缓存核算、隐私、故障关闭摄取和下游定价契约,请参阅 [推理使用遥测](https://github.com/nvidia/skillspector/blob/main/docs/INFERENCE_USAGE.md)。
- 每个问题的完整结构由 [models.py](https://github.com/nvidia/skillspector/blob/main/src/skillspector/models.py) 中的 `Finding.to_dict()` 定义;请依赖上述字段,并将任何其他字段视为尽力而为。
对于 CI/IDE 工具,`--format sarif` 会输出 SARIF 2.1.0。
### 推荐的网关映射
当将 SkillSpector 用作安装网关时,请将建议映射为操作:
| `recommendation` | 建议操作 |
|------------------|------------------|
| `SAFE` | 允许 |
| `CAUTION` | 提示 / 警告用户 |
| `DO_NOT_INSTALL` | 阻止 |
SkillSpector 计算评分区间和建议;网关的严格程度(例如 `CAUTION` 是否在 CI 中阻止)是集成工具的策略决策。
## 开发
### 设置
所有 `make` 目标都假定虚拟环境已创建并激活。Makefile 使用 **uv**(如果可用),否则使用 **pip**。```bash
# Clone, create venv, activate, install dev dependencies
git clone https://github.com/NVIDIA/skillspector.git
cd skillspector
uv venv .venv && source .venv/bin/activate
# or: python3 -m venv .venv && source .venv/bin/activate
make install-dev
# Run tests
make test
# Run tests with coverage
make test-cov
# Run linting
make lint
# Format code
make format
工作原理
SkillSpector 采用两阶段检测流水线:
第一阶段:静态分析
- 基于正则表达式的快速模式匹配,覆盖 11 个静态分析器
- 基于 AST 的行为分析,检测危险调用(exec、eval、subprocess 等)
- 通过 OSV.dev 对依赖项中的已知 CVE 进行实时漏洞查询
- 扫描技能中所有符合分析器条件的文件
- 高召回率(能捕获大多数问题)
- 中等精确率(存在一些误报)
有效的根级 OpenSSF 模型签名(skill.oms.sig)会作为 oms_signature 类型保留在组件清单中,但会被排除在静态和 LLM 内容分析之外。OMS 捆绑包必然包含较长的 base64 编码载荷、签名和证书字段;通用的混淆代码检查可能会将这些字段误分类为隐藏的可执行内容。识别器仅检查最小的 OMS DSSE/in-toto 结构;它不验证签名、证书链、透明度日志条目或签名者身份。无效或无法识别的签名文件会按正常流程进行扫描。
第二阶段:LLM 语义分析(可选)
- 评估上下文和意图
- 过滤误报
- 提供人类可读的解释
- 将精确率提升至约 87%
LLM 提示包含反越狱保护措施,以防止恶意技能操纵分析过程。
实时漏洞查询(SC4)
SC4 使用 OSV.dev API 将依赖项与完整的开源漏洞数据库进行比对——覆盖 PyPI 和 npm 上数万条安全公告。
- 无需 API 密钥 —— OSV.dev 免费且无需身份验证。
- 批量查询 —— 所有依赖项通过一次 HTTP 调用完成检查。
- 自动回退 —— 如果 OSV.dev 不可达(隔离/离线环境),将使用内置的小型回退列表。
- 缓存 —— 结果在内存中缓存 1 小时,以避免会话期间重复的 API 调用。
该工具需要对外 HTTPS 访问 api.osv.dev 以获取实时漏洞数据。当该访问不可用时,检测结果将仅限于静态回退列表。
信任模型与数据外传
SkillSpector 是纵深防御工具,而非沙箱。在依赖它之前,请了解它能做什么、不能做什么:
- 它绝不执行被扫描的技能。 所有分析均为静态分析(正则表达式、Python AST、YARA),外加对文件内容的可选 LLM 评估——技能的代码永远不会被运行。
- LLM 分析会将符合分析器条件的文件内容发送至已配置的提供商。 当启用 LLM 分析(默认启用)时,文件内容会被发送至当前激活的
SKILLSPECTOR_PROVIDER端点。已识别的 OMS 签名文件会被排除在外。使用--no-llm可将内容保留在本地(仅进行静态分析)。 - SC4 会将依赖项名称发送至 OSV.dev。 供应链检查会向 OSV.dev 查询技能声明的包名和版本,以查找已知 CVE。这是该检查的基本功能,即使使用
--no-llm也会运行。它发送的是依赖项坐标(而非文件内容),无需 API 密钥,并且在 OSV.dev 不可达时会回退到内置列表。 - 它不会对主机进行沙箱隔离。 SkillSpector 会在你安装技能之前标记风险模式;它不会隔离或限制你选择安装的技能。
局限性
- 非英文内容:可能遗漏其他语言中的模式
- 基于图像的攻击:无法分析图像中的文本
- 加密/二进制代码:无法分析编译或加密的内容
- 运行时行为:仅静态分析,无动态执行
- 离线 SC4:无法访问
api.osv.dev时,SC4 使用小型静态回退列表
研究背景
基于《Agent Skills in the Wild: An Empirical Study of Security Vulnerabilities at Scale》(Liu 等人,2026 年)的研究成果:
- 数据集:来自主要市场平台的 42,447 个技能
- 存在漏洞:26.1% 至少包含一个漏洞
- 高危严重性:5.2% 表现出可能的恶意意图
- 关键发现:包含可执行脚本的技能存在漏洞的可能性高出 2.12 倍
Python API 集成```python
from skillspector import graph
Invoke the LangGraph workflow
result = graph.invoke({ "input_path": "/path/to/skill", "output_format": "json", # terminal, json, markdown, or sarif "use_llm": True, # False for static-only analysis })
Access results
print(f"Risk Score: {result['risk_score']}/100") print(f"Severity: {result['risk_severity']}") print(f"Recommendation: {result['risk_recommendation']}")
for finding in result["filtered_findings"]: print(f"[{finding['severity']}] {finding['rule_id']}: {finding['message']}")
## 许可证
Apache License 2.0 — 详情请参阅 [LICENSE](https://github.com/nvidia/skillspector/blob/main/LICENSE)。
## 贡献
欢迎贡献!请阅读我们的贡献指南并提交拉取请求。
## 支持
- **问题**:[GitHub Issues](https://github.com/NVIDIA/skillspector/issues)