Files
wehub-resource-sync bf50115d8a
CI / Lint & Test (Python 3.12) (push) Has been cancelled
CI / Lint & Test (Python 3.13) (push) Has been cancelled
CI / Lint & Test (Python 3.14) (push) Has been cancelled
CI / DCO Check (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
docs: make Chinese README the default
2026-07-13 10:13:37 +00:00

757 lines
33 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- WEHUB_ZH_README -->
> [!NOTE]
> 本文档由 WeHub 基于上游 README 翻译整理,属于社区翻译,非官方中文文档。
> [English](./README.en.md) · [原始项目](https://github.com/NVIDIA/SkillSpector) · [上游 README](https://github.com/NVIDIA/SkillSpector/blob/HEAD/README.md)
> 原作者、版权与许可证归属以原始项目及本仓库 LICENSE 文件为准。
# SkillSpector
**面向 AI agent skill 的安全扫描器。** 在安装 agent skill 之前,检测漏洞、恶意模式和安全风险。
[![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)](https://www.python.org/downloads/)
[![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
## 概述
AI agent skill(供 Claude Code、Codex CLI、Gemini CLI 等使用)在隐式信任且几乎不经审核的情况下执行。研究表明,**26.1% 的 skill 含有漏洞****5.2% 表现出明显的恶意意图**。
SkillSpector 帮助你回答:**「这个 skill 安装起来安全吗?」**
## 文档
- **[开发指南](docs/DEVELOPMENT.md)** — 架构、包结构以及如何扩展分析器流水线。
- **[Pi 扩展](docs/PI_EXTENSION.md)** — 将 SkillSpector 安装为 Pi 工具,以便在 agent 会话中扫描 skill。
## 功能特性
- **多格式输入**:可扫描 Git 仓库、URL、zip 文件、目录或单个文件
- **68 种漏洞模式**,覆盖 17 个类别:提示注入(prompt injection)、数据渗出(data exfiltration)、权限提升(privilege escalation)、供应链(supply chain)、过度代理(excessive agency)、输出处理(output handling)、系统提示泄露(system prompt leakage)、记忆投毒(memory poisoning)、工具滥用(tool misuse)、失控 agentrogue agent)、反拒答(anti-refusal)、触发器滥用(trigger abuse)、危险代码(AST)、污点追踪(taint tracking)、YARA 签名、MCP 最小权限(MCP least privilege)以及 MCP 工具投毒(MCP tool poisoning
- **两阶段分析**:快速静态分析 + 可选的 LLM 语义评估
- **实时漏洞查询**:SC4 查询 [OSV.dev](https://osv.dev) 获取实时 CVE 数据,并自动离线回退
- **多种输出格式**:终端、JSON、Markdown 和 SARIF 报告
- **风险评分**:0-100 分,附严重程度标签和明确建议
- **基线 / 误报抑制**:通过 glob 规则或指纹基线接受已知发现项,使重新扫描仅暴露*新*问题([文档](docs/SUPPRESSION.md)
## 快速入门
### 安装
请先创建并激活虚拟环境(所有 `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'
```
**从源码安装:**
```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
无需安装 Python 即可运行 SkillSpector:根据随附的 [Dockerfile](Dockerfile) 在本地构建。镜像基于 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
```
### 输出格式
```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/` 并行扫描整个 skill 目录:
```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`](contrib/batch_scan/.env.example) 配置多个 API 密钥 — 只要这些密钥不共享账户级速率限制,密钥池即可提升吞吐量和容错能力。
详见 [contrib 指南](contrib/batch_scan/docs/)。
> **关于 LLM 支持的说明:** 默认配置以 DeepSeek 为目标,
> 作为最便宜的公开选项。DeepSeek-Chat 预计将于
> [expected to sunset](https://api-docs.deepseek.com/), 下线,且贡献者
> 没有硬件可在本地模型上测试。批量扫描器最初使用 OpenAI 兼容端点进行测试 — DeepSeek 缺乏
> 结构化输出支持,因此需要手动 JSON 解析补丁。如果你能贡献更通用的后端(Ollama、vLLM 或其他提供商),
> 非常欢迎提交 PR。
### 抑制误报(基线)
抑制已知/已接受的发现项,使风险评分仅反映未分类的问题,
重新扫描仅暴露*新*发现项。完整参考见
[抑制指南](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
```
基线也可使用容差 glob 规则(按规则 id、文件路径或
消息)— 参见 [`.skillspector-baseline.example.yaml`](.skillspector-baseline.example.yaml)。
### LLM 分析
为获得最佳效果,请配置 OpenAI 兼容的 LLM 端点以进行
语义分析。使用 `SKILLSPECTOR_PROVIDER` 选择提供商;每个
提供商都自带捆绑的默认模型。SkillSpector 也可对接
本地 OpenAI 兼容服务器(Ollama、vLLM、llama.cpp)以及托管
推理网关。
| Provider (`SKILLSPECTOR_PROVIDER`) | Credential env var | Endpoint | Default model |
| ---------- | ---- | ---- | ---- |
| `openai` | `OPENAI_API_KEY` (+ optional `OPENAI_BASE_URL`) | api.openai.com (or any OpenAI-compatible 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` | Any Vertex-style raw-predict proxy | `claude-sonnet-4-6` |
| `bedrock` | `AWS_PROFILE` (optional) + `AWS_REGION` — SigV4 via boto3 | 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` | _(none — uses local CLI auth)_ | local `claude` binary | `claude-sonnet-4-6` |
| `codex_cli` | _(none — uses local CLI auth)_ | local `codex` binary | `o4-mini` |
```bash
# 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
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 Server
将 SkillSpector 作为 [Model Context ProtocolMCP](https://modelcontextprotocol.io)
服务器运行,使任何支持 MCP 的代理(Claude Code、Codex CLI、Gemini CLI)或远程运行时都能将扫描作为工具调用,并**根据扫描结果拦截 skill/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 传输是当前面向本地 CLI 代理的 FastMCP 路径,issue #199 中报告的 initialize 挂起问题在该路径上仍然适用。
该服务器公开单个工具:
- **`scan_skill(target, use_llm=true, output_format="json")`** — 扫描 Git
URL、file 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)。
> - 通过 HTTP 时,本地路径和 `file://` URL 会被**自动拒绝**
> 以防止未经身份验证的调用方读取任意主机文件。仅接受远程 Git 和 `.zip` URL。
## 漏洞模式
SkillSpector 在 17 个类别中检测 **68 种漏洞模式**
### 提示注入(Prompt Injection5 种模式)
| ID | 模式 | 严重程度 | 描述 |
|----|---------|----------|-------------|
| P1 | 指令覆盖(Instruction Override | HIGH | 要求忽略安全约束的命令 |
| P2 | 隐藏指令(Hidden Instructions | HIGH | 注释/不可见文本中的恶意指令 |
| P3 | 外泄命令(Exfiltration Commands | HIGH | 要求将上下文向外传输的指令 |
| P4 | 行为操纵(Behavior Manipulation | MEDIUM | 微妙地改变代理决策的指令 |
| P5 | 有害内容(Harmful Content | CRITICAL | 可能导致人身伤害的指令 |
### 反拒绝(Anti-Refusal3 种模式)
| ID | 模式 | 严重程度 | 描述 |
|----|---------|----------|-------------|
| AR1 | 拒绝抑制(Refusal Suppression | HIGH | 要求永不拒绝或始终服从的指令(例如 "never refuse"、"always comply" |
| AR2 | 免责声明抑制(Disclaimer Suppression | HIGH | 要求省略警告、免责声明或伦理评注的指令(例如 "no disclaimers"、"do not moralize" |
| AR3 | 安全策略废止(Safety Policy Nullification | HIGH | 使护栏失效的越狱式表述(例如 "you have no restrictions"、"ignore your guidelines"、"do anything now" |
### 数据外泄(Data Exfiltration4 种模式)
| ID | 模式 | 严重程度 | 描述 |
|----|---------|----------|-------------|
| E1 | 外部传输(External Transmission | MEDIUM | 将数据发送到外部 URL |
| E2 | 环境变量收集(Env Variable Harvesting | HIGH | 收集 API 密钥和机密信息 |
| E3 | 文件系统枚举(File System Enumeration | MEDIUM | 扫描目录以查找敏感文件 |
| E4 | 上下文泄露(Context Leakage | HIGH | 将对话上下文向外传输 |
### 权限提升(Privilege Escalation3 种模式)
| ID | 模式 | 严重程度 | 描述 |
|----|---------|----------|-------------|
| PE1 | 过度权限(Excessive Permissions | LOW | 请求超出声明功能范围的访问权限 |
| PE2 | Sudo/Root 执行 | MEDIUM | 调用提升后的系统权限 |
| PE3 | 凭据访问(Credential Access | HIGH | 读取 SSH 密钥、令牌、密码 |
### 供应链(Supply Chain6 种模式)
| ID | 模式 | 严重程度 | 描述 |
|----|---------|----------|-------------|
| SC1 | 未固定依赖(Unpinned Dependencies | LOW | 软件包未设置版本约束 |
| SC2 | 外部脚本拉取(External Script Fetching | HIGH | curl \| bash 及远程代码执行 |
| SC3 | 混淆代码(Obfuscated Code | HIGH | Base64/hex 编码执行 |
| SC4 | 已知漏洞依赖(Known Vulnerable Dependencies | HIGH | 存在已知 CVE 的依赖(实时 OSV.dev 查询) |
| SC5 | 废弃依赖(Abandoned Dependencies | MEDIUM | 无人维护、无安全更新的软件包 |
| SC6 | 拼写仿冒(Typosquatting | HIGH | 与热门软件包名称相似的包名 |
### 过度代理(Excessive Agency4 种模式)
| ID | 模式 | 严重程度 | 描述 |
|----|---------|----------|-------------|
| EA1 | 无限制工具访问(Unrestricted Tool Access | HIGH | 不受约束的任意工具访问 |
| EA2 | 自主决策(Autonomous Decision Making | HIGH | 高影响决策未经人在回路(human-in-the-loop)参与 |
| EA3 | 范围蔓延(Scope Creep | MEDIUM | 能力超出声明用途 |
| EA4 | 无界资源访问(Unbounded Resource Access | MEDIUM | 资源消耗无速率限制或配额 |
### 输出处理(Output Handling3 种模式)
| ID | 模式 | 严重程度 | 描述 |
|----|---------|----------|-------------|
| OH1 | 未验证输出注入(Unvalidated Output Injection | HIGH | 模型输出未经净化即被使用 |
| OH2 | 跨上下文输出(Cross-Context Output | MEDIUM | 输出未经验证即跨越信任边界流动 |
| OH3 | 无界输出(Unbounded Output | MEDIUM | 对输出大小或生成速率无限制 |
### 系统提示泄露(System Prompt Leakage3 种模式)
| ID | 模式 | 严重程度 | 描述 |
|----|---------|----------|-------------|
| P6 | 直接泄露(Direct Leakage | HIGH | 暴露系统提示或内部规则的指令 |
| P7 | 间接提取(Indirect Extraction | MEDIUM | 通过改写、翻译或侧信道进行提取 |
| P8 | 基于工具的外泄(Tool-Based Exfiltration | HIGH | 通过文件写入或网络请求外泄系统提示 |
### 内存投毒(3 种模式)
| ID | Pattern | Severity | Description |
|----|---------|----------|-------------|
| MP1 | Persistent Context Injection | HIGH | 旨在跨交互持久保留的内容 |
| MP2 | Context Window Stuffing | MEDIUM | 用填充内容挤占安全约束 |
| MP3 | Memory Manipulation | HIGH | 篡改智能体内存或已存储状态 |
### 工具滥用(3 种模式)
| ID | Pattern | Severity | Description |
|----|---------|----------|-------------|
| TM1 | Tool Parameter Abuse | HIGH | 为达成非预期行为而构造的参数(shell=True, --force |
| TM2 | Chaining Abuse | HIGH | 绕过各项独立安全检查的工具链 |
| TM3 | Unsafe Defaults | MEDIUM | 过于宽松的默认设置(禁用 TLS、无身份验证) |
### 失控智能体(Rogue Agent2 种模式)
| ID | Pattern | Severity | Description |
|----|---------|----------|-------------|
| RA1 | Self-Modification | CRITICAL | 在运行时修改自身代码或配置 |
| RA2 | Session Persistence | HIGH | 通过 cron 作业或启动脚本实现未经授权的持久化 |
### 触发器滥用(3 种模式)
| ID | Pattern | Severity | Description |
|----|---------|----------|-------------|
| TR1 | Overly Broad Trigger | MEDIUM | 匹配常见词语的触发模式 |
| TR2 | Shadow Command Trigger | HIGH | 遮蔽内置命令或其他技能(skills)的触发器 |
| TR3 | Keyword Baiting Trigger | MEDIUM | 为最大化激活而设计的通用触发器 |
### 行为 AST9 种模式)
| ID | Pattern | Severity | Description |
|----|---------|----------|-------------|
| AST1 | exec() Call | CRITICAL | 直接 exec() 调用,可执行任意代码 |
| AST2 | eval() Call | HIGH | 直接 eval() 求值任意表达式 |
| AST3 | Dynamic Import | HIGH | \_\_import\_\_() 在运行时加载任意模块 |
| AST4 | subprocess Call | HIGH | 通过 subprocess 执行外部命令 |
| AST5 | os.system / exec-family | HIGH | 通过 os 模块执行 shell 命令 |
| AST6 | compile() Call | MEDIUM | 从字符串创建代码对象 |
| AST7 | Dynamic getattr() | MEDIUM | 使用非字面量名称进行任意属性访问 |
| AST8 | Dangerous Execution Chain | CRITICAL | exec/eval 与动态来源(网络、编码数据)组合 |
| AST9 | Reflective getattr() Sink | HIGH | 通过 `getattr(os,'system')` / `getattr(builtins,'exec')` 实现的反射式 exec,可规避 AST1/AST5 |
### 污点追踪(Taint Tracking5 种模式)
| ID | Pattern | Severity | Description |
|----|---------|----------|-------------|
| TT1 | Direct Taint Flow | HIGH | 数据未经净化直接从源流向汇点 |
| TT2 | Variable-Mediated Taint Flow | MEDIUM | 数据经中间变量从源流向汇点 |
| TT3 | Credential Exfiltration Chain | CRITICAL | 凭据(环境变量、密钥)流向网络输出汇点 |
| TT4 | File Read to Network Exfiltration | HIGH | 文件内容流向网络输出汇点 |
| TT5 | External Input to Code Execution | CRITICAL | 网络或用户输入流向 exec/eval/subprocess 汇点 |
### YARA 签名(4 种模式)
| ID | Pattern | Severity | Description |
|----|---------|----------|-------------|
| YR1 | Malware Match | CRITICAL | YARA 规则匹配已知恶意软件签名 |
| YR2 | Webshell Match | CRITICAL | YARA 规则匹配 webshell 模式 |
| YR3 | Cryptominer Match | HIGH | YARA 规则匹配加密货币挖矿指标 |
| YR4 | Hack Tool / Exploit Match | HIGH | YARA 规则匹配黑客工具或漏洞利用代码 |
### MCP 最小权限(Least Privilege4 种模式)
| ID | Pattern | Severity | Description |
|----|---------|----------|-------------|
| LP1 | Underdeclared Capability | HIGH | 代码使用了未在声明权限中列出的能力 |
| LP2 | Wildcard Permission | MEDIUM | 权限列表包含通配符(\*, all, full, any |
| LP3 | Missing Permission Declaration | MEDIUM | 无 permissions 字段但代码存在可检测能力 |
| LP4 | Overdeclared Permission | LOW | 已声明权限但未发现相应代码能力 |
### MCP 工具投毒(4 种模式)
| ID | Pattern | Severity | Description |
|----|---------|----------|-------------|
| TP1 | Hidden Instructions | HIGH | 元数据中的隐藏指令(HTML 注释、零宽字符、base64、data URI |
| TP2 | Unicode Deception | HIGH | 工具元数据中的同形异义字符、RTL 覆盖、混合书写体系标识符 |
| TP3 | Parameter Description Injection | MEDIUM | 参数定义中的注入模式(覆盖项、系统令牌、恶意默认值) |
| TP4 | Description-Behavior Mismatch | MEDIUM | 声明的工具描述与实际代码行为不符(由 LLM 驱动) |
所有已检测模式均列于上表。
## 风险评分
### 分数计算
- **CRITICAL 问题**+50 分
- **HIGH 问题**+25 分
- **MEDIUM 问题**+10 分
- **LOW 问题**+5 分
- **可执行脚本**1.3 倍乘数
### 严重等级
| Score | Severity | Recommendation |
|-------|----------|----------------|
| 0-20 | LOW | SAFE |
| 21-50 | MEDIUM | CAUTION |
| 51-80 | HIGH | DO NOT INSTALL |
| 81-100 | CRITICAL | DO NOT INSTALL |
## 示例输出
### 终端输出
```
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.
```
## 配置
### 环境变量
| Variable | Description | Required |
|----------|-------------|----------|
| `SKILLSPECTOR_PROVIDER` | 当前 LLM 提供商:`openai``anthropic``anthropic_proxy``bedrock``nv_build``claude_cli``codex_cli``gemini_cli`。各提供商均自带捆绑的 `model_registry.yaml` 及默认模型(见上文 LLM Analysis 表)。默认值为 `nv_build`。 | 可选 |
| `NVIDIA_INFERENCE_KEY` | `nv_build` 提供商(build.nvidia.com)的凭据。 | 在 `SKILLSPECTOR_PROVIDER=nv_build` 时进行 LLM 分析所需 |
| `OPENAI_API_KEY` | OpenAI 提供商(`SKILLSPECTOR_PROVIDER=openai`)的凭据。当当前提供商未返回凭据时,亦作为凭据瀑布(credential waterfall)中的第二层回退。 | 在 `SKILLSPECTOR_PROVIDER=openai` 时进行 LLM 分析所需 |
| `OPENAI_BASE_URL` | 覆盖 OpenAI 端点(例如指向 Ollama)。 | 可选 |
| `ANTHROPIC_API_KEY` | Anthropic 提供商(`SKILLSPECTOR_PROVIDER=anthropic`)的凭据。 | 在 `SKILLSPECTOR_PROVIDER=anthropic` 时进行 LLM 分析所需 |
| `ANTHROPIC_PROXY_ENDPOINT_URL` | Anthropic 代理提供商的完整端点 URLVertex 风格 raw-predict)。 | 在 `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 Analysis 表。 | 可选 |
| `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 密钥。身份验证完全由 agent 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 <path> [-o FILE] [--no-llm] [--reason TEXT]
```
## 集成 SkillSpector
SkillSpector 旨在由其他工具驱动(CI 流水线、安装门禁、编辑器集成)。其退出码和 JSON 输出构成稳定契约。
### 退出码
`skillspector scan` 退出时返回:
| Code | Meaning |
|------|---------|
| `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` 时,报告写入 stdout
```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 }
}
```
- `risk_assessment.severity``LOW | MEDIUM | HIGH | CRITICAL`
- `risk_assessment.recommendation``SAFE | CAUTION | DO_NOT_INSTALL`,由严重程度映射:`LOW → SAFE``MEDIUM → CAUTION``HIGH`/`CRITICAL → DO_NOT_INSTALL`
- 仅在请求了 LLM 分析但不可用时,才会出现 `metadata.llm_error`
- 每个问题的完整结构由 [models.py](src/skillspector/models.py) 中的 `Finding.to_dict()` 定义;请依赖上述字段,并将任何额外字段视为尽力而为(best-effort)。
对于 CI/IDE 工具,`--format sarif` 会输出 SARIF 2.1.0。
### 推荐门禁映射
将 SkillSpector 用作安装门禁时,请将建议映射为操作:
| `recommendation` | Suggested action |
|------------------|------------------|
| `SAFE` | allow |
| `CAUTION` | prompt / warn the user |
| `DO_NOT_INSTALL` | block |
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 采用两阶段检测流水线:
### 阶段 1:静态分析
- 11 个静态分析器基于正则表达式的快速模式匹配
- 基于 AST 的行为分析,检测危险调用(exec、eval、subprocess 等)
- 通过 OSV.dev 实时查询依赖项中的已知 CVE
- 扫描技能中的所有文件
- 高召回率(能捕获大多数问题)
- 中等精确度(存在一定误报)
### 阶段 2:LLM 语义分析(可选)
- 评估上下文与意图
- 过滤误报
- 提供人类可读的解释
- 将精确度提升至约 87%
LLM 提示词包含防越狱(anti-jailbreak)保护,以防止恶意技能操纵分析过程。
## 实时漏洞查询(SC4
SC4 使用 [OSV.dev](https://osv.dev) API 对照完整的开源漏洞(Open Source Vulnerabilities)数据库检查依赖项——覆盖 PyPI 和 npm 上数万条公告。
- **无需 API 密钥** — OSV.dev 免费且无需身份验证。
- **批量查询** — 所有依赖项在单次 HTTP 调用中完成检查。
- **自动回退** — 若 OSV.dev 不可达(气隙/离线环境),则使用小型内置回退列表。
- **缓存** — 结果在内存中缓存 1 小时,以避免会话期间重复的 API 调用。
该工具需要对外 HTTPS 访问 `api.osv.dev` 以获取实时漏洞数据。当无法访问时,发现结果仅限于静态回退列表。
## 信任模型与数据外泄
SkillSpector 采用纵深防御(defense-in-depth),而非沙箱。在依赖它之前,请了解它能做什么、不能做什么:
- **它从不执行被扫描的技能。** 所有分析均为静态(正则、Python AST、YARA),外加对文件*内容*的可选 LLM 评估——技能的代码绝不会被运行。
- **LLM 分析会将文件内容发送至配置的提供商。** 启用 LLM 分析时(默认开启),文件内容会发送至当前活动的 `SKILLSPECTOR_PROVIDER` 端点。使用 `--no-llm` 可将内容保留在本地(仅静态分析)。
- **SC4 会将依赖名称发送至 OSV.dev。** 供应链检查会查询 [OSV.dev](https://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']}")
```
## License
Apache License 2.0 - 详见 [LICENSE](LICENSE)。
## Contributing
欢迎贡献!请阅读我们的贡献指南并提交 pull request。
## Support
- **Issues** [GitHub Issues](https://github.com/NVIDIA/skillspector/issues)