Doramagic 项目包 · 项目说明书
decoy-scan 项目
生成时间:2026-05-14 05:23:08 UTC
项目介绍
decoy-scan 是一款面向 MCP (Model Context Protocol) 生态的供应链安全扫描工具,旨在 Agent 执行工具调用之前发现 MCP 服务器中的安全风险。该项目由 Decoy 团队开发,采用零依赖设计,仅需 Node.js 18+ 即可运行,无需安装任何 npm 包。资料来源:[README.md:1]()
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
decoy-scan 是一款面向 MCP (Model Context Protocol) 生态的供应链安全扫描工具,旨在 Agent 执行工具调用之前发现 MCP 服务器中的安全风险。该项目由 Decoy 团队开发,采用零依赖设计,仅需 Node.js 18+ 即可运行,无需安装任何 npm 包。资料来源:README.md:1
decoy-scan 的核心价值在于:
- 主动防御:在攻击者利用漏洞之前识别 MCP 服务器中的危险工具和提示注入
- 零配置:开箱即用,自动发现本地 MCP 客户端配置
- 多平台支持:覆盖主流 MCP 客户端(Claude Desktop、Cursor、Windsurf 等)
- CI/CD 友好:支持 JSON、SARIF 等结构化输出,便于集成到自动化流水线
资料来源:README.md:1-3
核心功能
decoy-scan 提供全面的 MCP 安全扫描能力,涵盖以下检查维度:
| 检查类别 | 功能描述 |
|---|---|
| 工具风险分类 | 基于名称和描述将工具分为 critical/high/medium/low 四个风险等级 |
| 提示注入检测 | 37 种正则模式,覆盖 20 个攻击类别,检测工具描述中的提示注入 |
| 毒性流分析 | 识别跨服务器数据泄露(TF001)和破坏性攻击链(TF002) |
| 工具清单哈希 | 追踪工具的增删改,检测扫描间的清单变化 |
| Skill 扫描 | 检测 Claude Code 中的提示注入、硬编码密钥、可疑 URL |
| 服务器命令分析 | 检测管道到 shell、内联代码、域名仿冒、临时目录生成 |
| 环境变量暴露 | 识别传递给服务器的 API 密钥、令牌、敏感凭证 |
| 供应链告警 | 对接 Decoy 告警数据库,覆盖 40+ 已知漏洞 MCP 包 |
| 传输安全 | 检查 HTTP 无 TLS、缺失认证、通配符 CORS、公共 SSE |
| 输入验证 | 验证参数约束、maxLength、开放模式 |
| 权限范围 | 评估过度授权服务器和危险能力组合 |
| OWASP 映射 | 将所有发现映射到 ASI01–ASI05(OWASP Agentic Top 10) |
资料来源:README.md:1
工具风险等级定义
| 等级 | 含义 | 示例工具 |
|---|---|---|
| Critical | 可执行代码、修改数据或造成不可逆变更 | execute_command, write_file |
| High | 可读取文件或发起网络请求 | read_file, fetch_url |
| Medium | 轻度风险,需注意配置 | list_directory |
| Low | 安全工具,可放心使用 | get_time |
资料来源:AGENTS.md:1
提示注入检测类型
decoy-scan 内置 37 种提示注入检测模式,涵盖以下攻击类别:
- 指令覆盖(Instruction Override)
- 隐匿(Concealment)
- 数据外泄(Data Exfiltration)
- 凭证收割(Credential Harvesting)
- 强制执行(Coercive Execution)
- 工具影身(Tool Shadowing)
- 规避技术(Evasion Techniques)
资料来源:AGENTS.md:1
支持的平台
decoy-scan 支持检测以下 MCP 客户端的配置文件:
| 平台 | 操作系统 | 配置文件路径 |
|---|---|---|
| Claude Desktop | macOS / Windows / Linux | 平台相关配置目录 |
| Cursor | macOS / Windows / Linux | 平台相关配置目录 |
| Windsurf | macOS / Windows / Linux | 平台相关配置目录 |
| VS Code | macOS / Windows / Linux | 平台相关配置目录 |
| Claude Code | macOS / Windows / Linux | 平台相关配置目录 |
| Zed | macOS / Windows / Linux | 平台相关配置目录 |
| Cline | macOS / Windows / Linux | 平台相关配置目录 |
配置文件路径根据操作系统自动适配(macOS、Windows、Linux)。
资料来源:AGENTS.md:1
技术架构
架构概览
graph TD
A[用户执行 decoy-scan] --> B[发现 MCP 配置]
B --> C{配置类型}
C -->|项目级| D[扫描 .mcp.json]
C -->|用户级| E[扫描各客户端配置]
D --> F[探针 MCP 服务器]
E --> F
F --> G[获取工具列表]
G --> H[分类工具风险]
G --> I[检测提示注入]
G --> J[分析服务器命令]
G --> K[检查环境变量]
H --> L[生成扫描报告]
I --> L
J --> L
K --> L
L --> M[JSON / SARIF / CLI 输出]核心模块结构
根据 CONTRIBUTING.md 的代码结构说明,主逻辑位于 index.mjs:
| 模块 | 功能 |
|---|---|
RISK_PATTERNS + classifyTool() | 基于名称/描述的工具风险分类 |
POISONING_PATTERNS + detectPoisoning() | 工具描述中的提示注入检测 |
analyzeServerCommand() | 服务器启动命令分析 |
SENSITIVE_ENV_PATTERNS + analyzeEnvExposure() | 环境变量暴露检测 |
analyzeReadiness() | 生产就绪状态启发式检查 |
OWASP_MAP + mapToOwasp() | OWASP Agentic Top 10 映射 |
HOST_CONFIGS + discoverConfigs() | MCP 客户端配置发现 |
probeServer() | MCP stdio 探针 |
scan() | 完整扫描编排器 |
toSarif() | SARIF 输出生成器 |
资料来源:CONTRIBUTING.md:1
库模式使用
decoy-scan 不仅可作为 CLI 工具使用,还提供编程接口:
import {
scan,
toSarif,
classifyTool,
detectPoisoning,
analyzeToxicFlows,
hashToolManifest,
detectManifestChanges,
discoverSkills,
analyzeSkill,
} from 'decoy-scan';
const results = await scan({ skills: true });
console.log(results.toxicFlows); // [{ id: "TF001", severity: "critical", roles: {...} }]
console.log(results.skills); // [{ name: "...", findings: [...] }]
console.log(results.servers[0].manifestHash); // "45c4c571f03c78a2"
资料来源:README.md:1
安装与使用
快速开始
无需安装,直接使用 npx 运行:
npx decoy-scan # 完整扫描
npx decoy-scan --json # 机器可读输出
npx decoy-scan --sarif # SARIF 2.1.0 格式(适用于 CI/CD)
npx decoy-scan explain <target> # 解释风险等级/类别/工具
npx decoy-scan explain <target> --json # 结构化解释输出
资料来源:AGENTS.md:1
CLI 选项
| 选项 | 简写 | 描述 |
|---|---|---|
--json | -j | 输出 JSON 格式 |
--sarif | - | 输出 SARIF 2.1.0 格式 |
--brief | - | 输出最小摘要(隐含 --json) |
--verbose | -v | 显示所有工具,包括低风险 |
--quiet | -q | 抑制状态输出 |
--version | -V | 打印版本 |
--help | -h | 打印帮助信息 |
资料来源:AGENTS.md:1
GitHub Actions 集成
decoy-scan 提供官方 GitHub Action,可直接集成到 CI/CD 流水线:
# .github/workflows/mcp-security.yml
name: MCP Security
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- uses: actions/checkout@v4
- uses: decoy-run/decoy-scan@v1
with:
policy: no-critical,no-poisoning,no-toxic-flows
sarif: true
report: true
token: ${{ secrets.DECOY_TOKEN }}
Action 输入参数:
| 输入 | 默认值 | 描述 |
|---|---|---|
policy | no-critical,no-poisoning | 逗号分隔的策略规则 |
sarif | true | 上传 SARIF 到 GitHub Security |
report | false | 上传到 Decoy Guard 仪表板 |
token | — | Decoy API 令牌 |
verbose | false | 显示所有工具包括低风险 |
策略规则示例:
no-critical 关键工具失败(代码执行、文件写入)
no-high 高风险工具失败(文件读取、网络)
no-poisoning 提示注入失败
no-toxic-flows 跨服务器数据泄露/破坏链失败
no-secrets MCP 配置中的密钥暴露失败
require-tripwires 未安装 decoy-tripwire 时失败
max-critical=N 关键工具数量限制
资料来源:README.md:1
输出格式
JSON 输出结构
{
"timestamp": "ISO-8601",
"hosts": ["Claude Desktop", "Cursor"],
"servers": [{
"name": "server-name",
"hosts": ["Claude Desktop"],
"command": "npx",
"args": ["@modelcontextprotocol/server-filesystem"],
"tools": [{
"name": "read_file",
"description": "...",
"risk": "high",
"poisoning": [{ "type": "...", "severity": "...", "description": "..." }]
}],
"risk": "high",
"error": null,
"findings": [{
"type": "env-exposure",
"severity": "high",
"description": "...",
"source": "env-config"
}]
}],
"summary": {
"total": 2, "critical": 1, "high": 1, "medium": 0, "low": 0, "poisoned": 0
},
"exitCode": 1
}
资料来源:AGENTS.md:1
SARIF 输出
SARIF 2.1.0 格式输出,适用于 GitHub Security 标签页集成:
npx decoy-scan --sarif
资料来源:README.md:1
退出码
| 退出码 | 含义 |
|---|---|
0 | 未发现 critical 或 high 风险问题 |
1 | 发现 high 风险问题 |
2 | 发现 critical 问题、工具污染或毒性流 |
退出码同时作为 exitCode 字段出现在 JSON 和 --brief 输出中,便于程序化判断。
资料来源:AGENTS.md:1
设计原则
decoy-scan 遵循以下核心设计原则:
- 零依赖:仅使用 Node.js 内置模块,不添加任何 npm 包
- 无构建步骤:纯 ES 模块,无需 TypeScript 或打包器
- 高性能:扫描应在数秒内完成,对服务器探针采用激进超时策略
- 安全扫描:仅读取配置,不修改任何文件,及时终止启动的服务器
- Agent 优先:JSON 和 SARIF 输出必须可被机器解析,AGENTS.md 必须完整
资料来源:CONTRIBUTING.md:1
版本历史
decoy-scan 采用语义化版本号,主要版本特性如下:
| 版本 | 日期 | 主要更新 |
|---|---|---|
| 0.7.0 | 2026-05-10 | v2遥测信封、重试+持久队列、首次运行仪表板链接 |
| 0.6.0 | 2026-05-08 | 毒性流分析 v2、Skill 扫描、仪表板上传 |
| 0.5.0 | 2026-04-21 | explain 子命令、CLI 输出重构 |
| 0.2.0 | 2026-03-20 | SSE 传输安全、输入验证、动态诱饵检测 |
| 0.1.0 | 2026-03-15 | 初始版本发布 |
资料来源:CHANGELOG.md:1
开发指南
本地开发
git clone https://github.com/decoy-run/decoy-scan
cd decoy-scan
node bin/cli.mjs --help
无需安装依赖,无需构建步骤,仅需 Node.js >= 18。
资料来源:CONTRIBUTING.md:1
测试
运行完整测试套件:
npm test
测试覆盖 CLI 输出、JSON/SARIF 结构、策略门控、毒性流检测、Skill 分析和清单哈希。所有测试通过后方可提交 PR。
手动测试不同输出模式:
node bin/cli.mjs --no-probe # 仅配置扫描
node bin/cli.mjs --no-advisories # 跳过网络请求
node bin/cli.mjs --json # 验证 JSON 结构
node bin/cli.mjs --sarif # 验证 SARIF 结构
node bin/cli.mjs --verbose # 显示所有输出
资料来源:CONTRIBUTING.md:1
添加新的检测模式
污染检测模式定义在 index.mjs 的 POISONING_PATTERNS 中:
{
pattern: /regex/i, // 匹配规则
type: "category-name", // 发现类型(用于 OWASP 映射)
severity: "critical", // critical, high, medium, low
description: "人类可读描述" // 输出中显示
}
添加模式后,若适用,需将 type 添加到 OWASP_MAP。
资料来源:CONTRIBUTING.md:1
添加新平台支持
在 HOST_CONFIGS 中添加新条目:
"New Client": () => {
const p = platform();
if (p === "darwin") return join(homedir(), "path", "to", "config.json");
if (p === "win32") return join(process.env.APPDATA || "", "path", "config.json");
return join(homedir(), ".config", "path", "config.json");
},
资料来源:CONTRIBUTING.md:1
安全问题报告
发现安全漏洞请通过电子邮件联系 [email protected],请勿为此项目创建公开 Issue。
资料来源:CONTRIBUTING.md:1
资料来源:[README.md:1-3]()
快速开始
decoy-scan 是一个 MCP(Model Context Protocol)供应链安全扫描工具,用于检测 MCP 服务器配置中的安全风险、提示注入和有毒数据流。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
功能概述
| 功能模块 | 说明 |
|---|---|
| 工具风险分类 | 按名称和描述将工具分类为 critical/high/medium/low |
| 提示注入检测 | 37 种正则模式覆盖 20 个攻击类别 |
| 有毒流分析 | 跨服务器数据泄漏(TF001)和破坏性(TF002)攻击链检测 |
| 工具清单哈希 | 检测扫描间工具的增删改 |
| 技能扫描 | Claude Code 技能中的提示注入、硬编码密钥、可疑 URL 检测 |
| 服务器命令分析 | 管道到 shell、内联代码、 typosquatting、临时目录检测 |
| 环境变量暴露 | API 密钥、令牌、密码、云凭证检测 |
| 供应链情报 | 40+ 已知漏洞 MCP 包 |
| 传输安全 | HTTP 无 TLS、缺失认证、泛域 CORS |
| OWASP 映射 | 所有发现映射到 ASI01-ASI05 |
资料来源:README.md:37-51
系统要求
| 要求 | 详情 |
|---|---|
| Node.js 版本 | >= 18 |
| 依赖 | 零依赖(仅使用 Node.js 内置模块) |
| 构建步骤 | 无需构建,直接运行 ES 模块 |
| 支持平台 | macOS, Windows, Linux |
资料来源:CONTRIBUTING.md:8-10
基本用法
方式一:直接运行(推荐)
npx decoy-scan
无需安装,直接运行。工具会自动扫描本地所有支持的 MCP 客户端配置。
资料来源:README.md:23-24
方式二:本地开发
git clone https://github.com/decoy-run/decoy-scan
cd decoy-scan
node bin/cli.mjs --help
资料来源:CONTRIBUTING.md:4-8
支持的主机
decoy-scan 支持以下 7 个 MCP 客户端的配置文件自动发现:
| 主机 | 平台支持 |
|---|---|
| Claude Desktop | macOS, Windows, Linux |
| Cursor | macOS, Windows, Linux |
| Windsurf | macOS, Windows, Linux |
| VS Code | macOS, Windows, Linux |
| Claude Code | macOS, Windows, Linux |
| Zed | macOS, Windows, Linux |
| Cline | macOS, Windows, Linux |
配置文件路径根据操作系统自动适配(macOS 使用 ~/Library/...,Windows 使用 %APPDATA%,Linux 使用 ~/.config)。
资料来源:AGENTS.md:59-61
扫描工作流
graph TD
A[启动 decoy-scan] --> B[发现 MCP 服务器配置]
B --> C{配置检测}
C -->|有配置| D[启动服务器进程]
C -->|无配置| E[生成诊断信息]
D --> F[通过 stdio 查询工具列表]
F --> G[工具风险分类]
F --> H[提示注入检测]
F --> I[环境变量暴露分析]
G --> J[生成扫描报告]
H --> J
I --> J
E --> K[输出 --json / --sarif 格式]
J --> KCLI 参数参考
全局参数
| 参数 | 简写 | 说明 |
|---|---|---|
--json | -j | JSON 结构化输出(机器可读) |
--sarif | -s | SARIF 2.1.0 格式输出(CI/CD 集成) |
--brief | -b | 最小摘要信息 |
--verbose | -v | 显示所有工具包括低风险项 |
--quiet | -q | 静默模式,不输出状态信息 |
--version | -V | 显示版本号 |
--help | -h | 显示帮助信息 |
资料来源:AGENTS.md:13-18
扫描控制参数
| 参数 | 说明 |
|---|---|
--no-probe | 仅扫描配置,不探测服务器 |
--no-advisories | 跳过网络请求(不查询供应链情报) |
--no-telemetry | 禁用遥测数据收集 |
--verify | AI 验证扫描结果 |
资料来源:AGENTS.md:19-26
策略控制参数
| 参数 | 说明 |
|---|---|
--policy <rules> | 逗号分隔的策略规则 |
--report | 上报结果到 Decoy Guard 仪表板 |
策略规则包括:no-critical、no-high、no-poisoning、no-toxic-flows、no-secrets、require-tripwires、max-critical=N。
资料来源:README.md:78-82
输出格式
标准输出
默认情况下,decoy-scan 输出人类可读的彩色终端界面:
▸ Discovering MCP servers…
▸ Running N checks…
✗ filesystem 2 critical
Critical: read_file, write_file
High: list_directory
✓ claude-desktop passed
N issues found · N critical, N high · N checks passed · Ns
服务器状态徽章:
✗ name N critical- 发现严重问题! name poisoned tool- 检测到提示注入(洋红色)? name probe failed- 服务器探测失败✓ name passed- 通过扫描
资料来源:CHANGELOG.md:12-22
JSON 输出
decoy-scan --json
输出结构:
{
"timestamp": "ISO-8601",
"hosts": ["Claude Desktop", "Cursor"],
"servers": [{
"name": "server-name",
"hosts": ["Claude Desktop"],
"command": "npx",
"args": ["@modelcontextprotocol/server-filesystem"],
"tools": [{
"name": "read_file",
"description": "...",
"risk": "high",
"poisoning": [{ "type": "...", "severity": "...", "description": "..." }]
}],
"risk": "high",
"error": null,
"findings": [{
"type": "env-exposure",
"severity": "high",
"description": "...",
"source": "env-config"
}]
}],
"summary": {
"total": 2, "critical": 1, "high": 1, "medium": 0, "low": 0,
"poisoned": 0, "toxicFlows": [], "status": "warn", "exitCode": 1
}
}
资料来源:AGENTS.md:64-93
SARIF 输出
decoy-scan --sarif
生成符合 SARIF 2.1.0 标准的输出,可直接上传到 GitHub Security 选项卡。
资料来源:README.md:57-58
Brief 输出
decoy-scan --brief
最小摘要格式:
{
"servers": 3,
"critical": 1,
"high": 2,
"medium": 4,
"low": 5,
"poisoned": 0,
"status": "fail",
"exitCode": 2
}
资料来源:AGENTS.md:100-116
退出码
| 退出码 | 含义 |
|---|---|
0 | 无 critical 或 high 风险问题 |
1 | 发现 high 风险问题 |
2 | 发现 critical 问题、工具中毒或有毒流 |
退出码在 --json 和 --brief 输出中通过 exitCode 字段暴露,便于自动化脚本处理。
资料来源:AGENTS.md:45-54
GitHub Action 集成
基本配置
在 .github/workflows/mcp-security.yml 中添加:
name: MCP Security
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- uses: actions/checkout@v4
- uses: decoy-run/decoy-scan@v1
资料来源:README.md:60-71
完整配置示例
- uses: decoy-run/decoy-scan@v1
with:
policy: no-critical,no-poisoning,no-toxic-flows
sarif: true
report: true
token: ${{ secrets.DECOY_TOKEN }}
verbose: false
| 输入参数 | 默认值 | 说明 |
|---|---|---|
policy | no-critical,no-poisoning | 逗号分隔的策略规则 |
sarif | true | 上传 SARIF 到 GitHub Security |
report | false | 上传到 Decoy Guard 仪表板 |
token | — | Decoy API 令牌 |
verbose | false | 显示所有工具包括低风险 |
资料来源:README.md:73-80
GitHub Action 输出
Action 提供以下输出供后续步骤使用:
| 输出 | 说明 |
|---|---|
exit-code | 扫描退出码 |
sarif-file | SARIF 文件路径 |
summary | 摘要信息 |
资料来源:action.yml:45-54
explain 子命令
用于解释扫描发现的含义,无需解析完整输出:
decoy-scan explain critical # 严重等级
decoy-scan explain tool-description # 发现类别
decoy-scan explain prompt-override # 中毒类型
decoy-scan explain read_file # 工具名称
decoy-scan explain list # 列出所有可解释目标
decoy-scan explain <target> --json # 结构化输出
JSON 输出示例:
{
"tool": "decoy-scan",
"version": "0.5.1",
"target": "critical",
"result": {
"kind": "tier",
"key": "critical",
"title": "Critical",
"summary": "Can execute code, modify data, or cause irreversible changes.",
"body": "...",
"examples": ["execute_command", "write_file"],
"advice": "..."
}
}
result.kind 可能是:tier(等级)、category(类别)、poisoning(中毒类型)、tool(工具)。
资料来源:AGENTS.md:24-49
库模式使用
decoy-scan 也可作为 Node.js 模块导入使用:
import {
scan,
toSarif,
classifyTool,
detectPoisoning,
analyzeToxicFlows,
hashToolManifest,
detectManifestChanges,
discoverSkills,
analyzeSkill,
} from 'decoy-scan';
const results = await scan({ skills: true });
console.log(results.toxicFlows); // 有毒流分析结果
console.log(results.skills); // 技能扫描结果
console.log(results.servers[0].manifestHash); // "45c4c571f03c78a2"
资料来源:README.md:86-97
扫描检查项速查
| 检查项 | 检测内容 |
|---|---|
| 工具风险分类 | 按名称和描述评估风险等级 |
| 提示注入检测 | 指令覆盖、隐藏、凭证窃取、强制执行、工具影子、规避技术 |
| 有毒流分析 | 跨服务器数据泄漏(TF001)和破坏性攻击链(TF002) |
| 清单变更追踪 | 工具增删、描述变更的哈希对比 |
| 服务器命令 | 管道到 shell、内联代码、typosquatting |
| 环境暴露 | API 密钥、令牌、数据库 URL、云凭证 |
| 供应链情报 | 40+ 已知漏洞 MCP 包 |
| 传输安全 | HTTP 明文、缺失认证、公开 SSE |
| 输入验证 | 无约束参数、缺失长度限制、开放 schema |
| 权限范围 | 过度特权、危险能力组合 |
资料来源:README.md:37-51
下一步
- 查看 AGENTS.md 了解机器可读输出的详细 schema
- 查看 CONTRIBUTING.md 了解如何扩展检测模式
- 查看 CHANGELOG.md 了解版本更新历史
- 访问 decoy.run 文档 获取完整文档
资料来源:[README.md:37-51]()
命令行工具
decoy-scan 提供了一个零依赖的 Node.js CLI 工具,用于扫描 MCP(Model Context Protocol)客户端配置中的安全风险。该命令行工具无需安装配置,下载后即可直接运行,支持对 Claude Desktop、Cursor、Windsurf、VS Code、Claude Code、Zed 和 Cline 等多种 MCP 主机进行安全扫描。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
decoy-scan 提供了一个零依赖的 Node.js CLI 工具,用于扫描 MCP(Model Context Protocol)客户端配置中的安全风险。该命令行工具无需安装配置,下载后即可直接运行,支持对 Claude Desktop、Cursor、Windsurf、VS Code、Claude Code、Zed 和 Cline 等多种 MCP 主机进行安全扫描。
CLI 的核心功能包括:工具风险分类、提示注入检测、有毒数据流分析、工具清单哈希追踪、技能扫描、服务器命令分析、环境变量暴露检测、供应链告警以及 OWASP Agentic Top 10 映射。资料来源:README.md:1-45
快速开始
npx decoy-scan # 完整扫描
npx decoy-scan --json # 机器可读输出
npx decoy-scan --sarif # SARIF 2.1.0 格式(用于 CI/CD)
npx decoy-scan explain <target> # 解释风险等级/类别/工具名称
该工具要求 Node.js 18 或更高版本,无需预先安装任何依赖包。资料来源:CONTRIBUTING.md:1-8
全局选项
| 选项 | 说明 |
|---|---|
--verbose, -v | 显示所有工具,包括低风险项 |
--quiet, -q | 抑制状态输出 |
--version, -V | 打印版本号 |
--help, -h | 打印帮助信息 |
扫描控制选项
| 选项 | 说明 |
|---|---|
--no-probe | 仅扫描配置文件,不探测服务器 |
--no-advisories | 跳过供应链告警检查(避免网络请求) |
--json | 输出 JSON 格式结果 |
--sarif | 输出 SARIF 2.1.0 格式结果 |
--brief | 仅输出摘要信息(隐含 --json) |
输出控制选项
| 选项 | 说明 |
|---|---|
--output <file> | 将结果写入指定文件 |
--no-telemetry | 禁用遥测数据收集 |
--report | 上传结果至 Decoy Guard 仪表板 |
资料来源:AGENTS.md:1-10
子命令
`explain` 子命令
explain 子命令用于解析扫描结果的含义,无需解析完整的扫描输出。当 AI agent 看到某个发现并需要结构化上下文来采取行动时,此命令非常有用。
decoy-scan explain critical # 严重性等级
decoy-scan explain tool-description # 发现类别
decoy-scan explain prompt-override # 投毒类型
decoy-scan explain read_file # 工具名称(运行真实分类规则)
decoy-scan explain list # 枚举所有可解释的目标
decoy-scan explain <target> --json # 结构化输出(推荐用于 agent)
资料来源:AGENTS.md:20-35
#### explain 输出格式
--json 输出的 JSON 结构如下:
{
"tool": "decoy-scan",
"version": "0.5.1",
"target": "critical",
"result": {
"kind": "tier",
"key": "critical",
"title": "Critical",
"summary": "Can execute code, modify data, or cause irreversible changes.",
"body": "...",
"examples": ["execute_command", "write_file", "..."],
"advice": "..."
}
}
result.kind 的值包括:
| kind 值 | 说明 |
|---|---|
tier | 严重性等级(critical、high、medium、low) |
category | 发现类别(如 env-exposure、missing-description) |
poisoning | 投毒类型(如 prompt-override、credential-harvesting) |
tool | 工具名称(包含 risk、reason、matched 等字段) |
资料来源:AGENTS.md:36-50
退出码
CLI 通过退出码向调用者传递扫描结果的状态:
| 退出码 | 含义 |
|---|---|
0 | 未发现严重或高风险问题 |
1 | 发现高风险问题 |
2 | 发现严重问题、工具投毒或有毒数据流 |
退出码也会在 --json 和 --brief 输出的 exitCode 字段中暴露,便于 agent 在不重新解析严重性计数的情况下进行分支判断。资料来源:AGENTS.md:58-68
输出格式
JSON 输出架构
{
"timestamp": "ISO-8601",
"hosts": ["Claude Desktop", "Cursor"],
"servers": [{
"name": "server-name",
"hosts": ["Claude Desktop"],
"command": "npx",
"args": ["@modelcontextprotocol/server-filesystem"],
"tools": [{
"name": "read_file",
"description": "...",
"risk": "high",
"poisoning": [{ "type": "...", "severity": "...", "description": "..." }]
}],
"risk": "high",
"error": null,
"findings": [{
"type": "env-exposure",
"severity": "high",
"description": "...",
"source": "env-config"
}]
}],
"summary": {
"total": 2,
"critical": 1,
"high": 2,
"medium": 4,
"low": 5,
"poisoned": 0
}
}
资料来源:AGENTS.md:75-100
`--brief` 输出架构
--brief 隐含 --json,输出精简的摘要对象:
{
"servers": 3,
"critical": 1,
"high": 2,
"medium": 4,
"low": 5,
"poisoned": 0,
"status": "fail",
"exitCode": 2
}
| 字段 | 说明 |
|---|---|
servers | 扫描的非诱饵、非错误服务器数量 |
critical、high、medium、low | 各风险等级的工具数量 |
poisoned | 工具投毒发现数量 |
status | pass(清洁)、warn(高风险)或 fail(严重/投毒/有毒流) |
exitCode | 进程退出码 |
资料来源:AGENTS.md:102-125
SARIF 输出
使用 --sarif 选项可生成 SARIF 2.1.0 格式的输出,适用于 GitHub Security 标签页集成:
decoy-scan --sarif
npx decoy-scan --sarif | jq
资料来源:README.md:15-18
工作流程架构
graph TD
A[用户执行 decoy-scan] --> B[发现 MCP 服务器配置]
B --> C{选项解析}
C -->|explain| D[解析 explain 子命令]
C -->|scan| E[执行安全扫描]
D --> F[查询 RISK_PATTERNS]
D --> G[查询 POISONING_PATTERNS]
F --> H[返回结构化解释]
G --> H
E --> I[探测 MCP 服务器]
I --> J[获取工具列表]
J --> K[执行安全分析]
K --> L{发现风险?}
L -->|是| M[分类风险等级]
L -->|否| N[标记为通过]
M --> O[生成扫描报告]
N --> O
O --> P[根据结果设置退出码]支持的主机
decoy-scan 支持以下 7 个 MCP 主机:
| 主机 | 平台支持 |
|---|---|
| Claude Desktop | macOS, Windows, Linux |
| Cursor | macOS, Windows, Linux |
| Windsurf | macOS, Windows, Linux |
| VS Code | macOS, Windows, Linux |
| Claude Code | macOS, Windows, Linux |
| Zed | macOS, Windows, Linux |
| Cline | macOS, Windows, Linux |
配置文件路径根据操作系统自动适配(macOS、Windows、Linux)。资料来源:AGENTS.md:70-73
CI/CD 集成
GitHub Action
decoy-scan 提供官方 GitHub Action,可用于 CI/CD 流水线:
# .github/workflows/mcp-security.yml
name: MCP Security
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- uses: actions/checkout@v4
- uses: decoy-run/decoy-scan@v1
#### Action 输入参数
| 输入 | 默认值 | 说明 |
|---|---|---|
policy | no-critical,no-poisoning | 逗号分隔的策略规则 |
sarif | true | 上传 SARIF 至 GitHub Security 标签页 |
report | false | 上传至 Decoy Guard 仪表板 |
token | — | Decoy API token(用于 report) |
verbose | false | 显示所有工具包括低风险项 |
#### 策略规则
no-critical 严重工具(代码执行、文件写入)导致失败
no-high 高风险工具(文件读取、网络)导致失败
no-poisoning 工具描述中的提示注入导致失败
no-toxic-flows 跨服务器数据泄露/破坏链导致失败
no-secrets MCP 配置中暴露的密钥导致失败
require-tripwires 未安装 decoy-tripwire 导致失败
max-critical=N 允许的严重问题数量
资料来源:README.md:75-100
CLI 参数与 GitHub Action 输入的映射
graph LR
A[CLI 参数] --> B[Action 输入]
A1[--json] --> B1[sarif=false, brief=true]
A2[--verbose] --> B2[verbose=true]
A3[--report] --> B3[report=true]
A4[--policy] --> B4[policy]
A5[--token] --> B5[token]代码结构
CLI 的核心实现在 index.mjs 中,各模块职责如下:
| 模块 | 功能 |
|---|---|
RISK_PATTERNS + classifyTool() | 基于名称/描述的工具风险分类 |
POISONING_PATTERNS + detectPoisoning() | 工具描述中的提示注入检测 |
analyzeServerCommand() | 服务器启动命令分析 |
SENSITIVE_ENV_PATTERNS + analyzeEnvExposure() | 环境变量暴露检测 |
analyzeReadiness() | 生产就绪性启发式检查 |
OWASP_MAP + mapToOwasp() | OWASP Agentic Top 10 映射 |
HOST_CONFIGS + discoverConfigs() | MCP 客户端配置发现 |
probeServer() | MCP stdio 探测 |
scan() | 完整扫描编排器 |
toSarif() | SARIF 输出生成器 |
扫描类别详解
1. 工具风险分类
根据名称模式和描述分析,将每个工具分类为严重/高/中/低风险。关键风险模式包括代码执行、文件写入、网络调用等。资料来源:CONTRIBUTING.md:20-22
2. 工具投毒检测
37 种正则表达式模式横跨 20 个攻击类别,检测隐藏在工具描述中的提示注入,包括指令覆盖、隐藏、数据外泄、凭证窃取、强制执行、工具影子和规避技术。资料来源:CONTRIBUTING.md:22-24
3. 服务器命令分析
检查启动命令中的管道到 shell、临时目录、内联代码、域名仿冒和网络工具。资料来源:CONTRIBUTING.md:24-26
4. 环境变量暴露
标记 12 类敏感凭证,包括 API 密钥、令牌、密码、数据库 URL 和云凭证。资料来源:CONTRIBUTING.md:26-28
5. 生产就绪性
检查缺失描述、缺失模式、无必需字段、过度作用域以及无安全提示的危险工具。资料来源:CONTRIBUTING.md:28-30
6. 供应链告警
通过 Decoy 告警数据库交叉引用 40+ 个已知易受攻击的 MCP 包。资料来源:CONTRIBUTING.md:30-32
设计原则
- 零依赖:仅使用 Node.js 内置模块,不添加 npm 包。
- 无需构建:纯 ES 模块,无 TypeScript,无打包器。
- 快速:扫描应在数秒内完成,积极设置服务器超时。
- 安全:从不修改配置,仅读取扫描,遇到问题时立即终止。
- 面向 Agent:JSON 和 SARIF 输出必须是机器可解析的。资料来源:CONTRIBUTING.md:50-57
手动测试模式
node bin/cli.mjs --no-probe # 仅配置扫描
node bin/cli.mjs --no-advisories # 跳过网络调用
node bin/cli.mjs --json # 验证 JSON 结构
node bin/cli.mjs --sarif # 验证 SARIF 结构
node bin/cli.mjs --verbose # 显示所有输出
库导出
CLI 的核心功能也可作为库导入使用:
import {
scan,
toSarif,
classifyTool,
detectPoisoning,
analyzeToxicFlows,
hashToolManifest,
detectManifestChanges,
discoverSkills,
analyzeSkill,
} from 'decoy-scan';
const results = await scan({ skills: true });
console.log(results.toxicFlows); // [{ id: "TF001", severity: "critical", roles: {...} }]
console.log(results.skills); // [{ name: "...", findings: [...] }]
console.log(results.servers[0].manifestHash); // "45c4c571f03c78a2"
资料来源:README.md:25-40
遥测数据
CLI 默认收集匿名使用统计信息,可通过以下方式禁用:
- 设置环境变量
DECOY_TELETELRY=0 - 使用
--no-telemetry标志
首次运行会显示遥测通知,并缓存于 ~/.decoy/telemetry-notice-shown。资料来源:CHANGELOG.md:2026-05-10
常见使用场景
| 场景 | 命令 |
|---|---|
| 快速扫描 | npx decoy-scan |
| CI 集成 | npx decoy-scan --sarif --no-advisories |
| Agent 集成 | npx decoy-scan --brief --json |
| 了解风险 | npx decoy-scan explain critical |
| 详细输出 | npx decoy-scan --verbose |
| 仅配置检查 | npx decoy-scan --no-probe |
资料来源:README.md:10-25
资料来源:[AGENTS.md:1-10]()
安全检查项目
decoy-scan 是一款针对 MCP (Model Context Protocol) 供应链安全的扫描工具,零依赖,基于 Node.js 18+ 运行。本文档详细说明该工具执行的所有安全检查项目及其检测机制。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
核心安全检查概览
decoy-scan 实现了 12 大安全检查类别,涵盖从工具风险分类到供应链威胁检测的完整攻击面分析。
| 检查类别 | 检测内容 | 严重级别 |
|---|---|---|
| 工具风险分类 | 按名称和描述将工具分为 critical/high/medium/low | |
| 提示词注入检测 | 37 种正则模式覆盖 20 个攻击类别 | |
| 有毒数据流分析 | 跨服务器数据泄露和破坏性攻击链 | |
| 工具清单哈希 | 检测工具新增、移除和描述变更 | |
| 技能扫描 | Claude Code 技能中的注入和敏感信息 | |
| 服务器命令分析 | 管道到 shell、内联代码、域名仿冒等 | |
| 环境变量暴露 | API 密钥、令牌、云凭证等 | |
| 供应链预警 | 40+ 已知漏洞 MCP 包 | |
| 传输安全 | HTTP 无 TLS、缺失认证、公开 SSE | |
| 输入验证 | 无约束参数、缺失 maxLength、开放 schema | |
| 权限范围 | 过度授权服务器、危险能力组合 | |
| OWASP 映射 | 每项发现映射到 ASI01-ASI05 |
资料来源:README.md
工具风险分类体系
风险级别定义
工具风险分类是 decoy-scan 的核心检测引擎,通过 RISK_PATTERNS 和 classifyTool() 函数实现。
graph TD
A[工具输入] --> B{名称模式匹配}
B -->|^execute.*| C[Critical 级别]
B -->|^read.*|^write.*| D[High 级别]
B -->|^list.*|^search.*| E[Medium 级别]
B -->|其他| F[Low 级别]
C --> G[可执行代码、修改数据、不可逆变更]
D --> H[文件读写、网络访问]
E --> I[信息列举]
F --> J[安全工具]资料来源:CONTRIBUTING.md:1-9
Critical 级别工具模式
以下工具名称模式被直接判定为 critical 风险:
| 正则模式 | 匹配示例 | 风险说明 | |||||
|---|---|---|---|---|---|---|---|
| `^execute[_-]?(script\ | code\ | js\ | javascript\ | python\ | sql)$` | execute_code, execute_python | 可执行任意代码 |
| `^evaluate[_-]?(script\ | code)$` | evaluate_script | 脚本评估执行 | ||||
| `^run[_-]?(script\ | code\ | js\ | python\ | sql)$` | run_javascript | 代码运行 | |
| `^eval[_-]?(script\ | code)$` | eval_code | 直接代码执行 | ||||
^write[_-]?file$ | write_file | 文件写入 | |||||
^spawn[_-]?process$ | spawn_process | 进程生成 |
资料来源:CHANGELOG.md:1-20
分类算法改进
在 v0.5.6 版本中修复了此前版本存在的边界问题:之前版本对每个名称模式都使用了锚点 ^,导致带有后缀的代码执行名称(如 evaluate_script、execute_python)被错误分类为 "low"。
改进措施包括:
- 添加了完整的带后缀代码执行模式到 critical 层级
- 子串回退机制现在同时对小写化的名称运行,使
evaluate、spawn、fetch等危险动词即使没有提供描述也能正确分类
资料来源:CHANGELOG.md:1-20
提示词注入检测
攻击类别体系
提示词注入检测通过 POISONING_PATTERNS 和 detectPoisoning() 函数实现,包含 37 种正则模式覆盖 20 个攻击类别。
graph TD
A[工具描述文本] --> B{Poisoning Pattern 匹配}
B -->|指令覆盖| C[instruction-override]
B -->|隐匿| D[concealment]
B -->|数据泄露| E[data-exfiltration]
B -->|凭证窃取| F[credential-harvesting]
B -->|强制执行| G[coercive-execution]
B -->|工具影子| H[tool-shadowing]
B -->|规避技术| I[evasion-techniques]
C --> J[Critical/High 级别发现]
D --> J
E --> J
F --> J
G --> J
H --> J
I --> J检测模式结构
每个 poisoning 检测模式包含以下字段:
{
pattern: /regex/i, // 匹配规则
type: "category-name", // 发现类型(用于 OWASP 映射)
severity: "critical", // critical/high/medium/low
description: "Human-readable" // 人类可读说明
}
资料来源:CONTRIBUTING.md:1-20
OWASP Agentic Top 10 映射
所有提示词注入检测结果都会映射到 OWASP Agentic Top 10 for 2026 标准,通过 OWASP_MAP 和 mapToOwasp() 函数实现。
| 发现类型 | OWASP 映射 | 严重级别 |
|---|---|---|
| instruction-override | ASI01 | Critical |
| credential-harvesting | ASI02 | Critical |
| data-exfiltration | ASI03 | High |
| tool-shadowing | ASI04 | High |
| coercive-execution | ASI05 | Medium |
有毒数据流分析
攻击链检测
有毒数据流分析检测跨服务器的数据泄露和破坏性攻击链。
graph LR
A[服务器 A] -->|敏感数据流| B[服务器 B]
B -->|外部通信| C[攻击者控制端点]
D[服务器 X] -->|破坏操作| E[系统资源]
subgraph TF001[数据泄露攻击链]
A
B
C
end
subgraph TF002[破坏性攻击链]
D
E
end攻击链类型
| ID | 类型 | 说明 |
|---|---|---|
| TF001 | 数据泄露 | 跨服务器敏感数据流向外部 |
| TF002 | 破坏性攻击 | 跨服务器破坏操作链 |
资料来源:README.md
服务器命令分析
检测能力
analyzeServerCommand() 函数分析 MCP 服务器的启动命令,检测以下可疑特征:
| 检测类型 | 特征 | 风险 | ||
|---|---|---|---|---|
| 管道到 shell | ` | bash, | sh` | 命令注入 |
| 临时目录执行 | /tmp/, /var/tmp/ | 持久化攻击 | ||
| 内联代码 | node -e "...", python -c "..." | 混淆执行 | ||
| 域名仿冒 | 相似拼写的包名 | typosquatting | ||
| 网络工具 | curl, wget, nc | 外部通信 |
资料来源:CONTRIBUTING.md:1-9
环境变量暴露检测
敏感信息模式
SENSITIVE_ENV_PATTERNS 和 analyzeEnvExposure() 函数检测 12 类敏感环境变量暴露:
graph TD
A[MCP 配置] --> B{环境变量分析}
B -->|API 密钥| C[API_KEY, OPENAI_API_KEY]
B -->|令牌| D[AWS_SECRET, GITHUB_TOKEN]
B -->|密码| E[DB_PASSWORD, MYSQL_PWD]
B -->|数据库 URL| F[DATABASE_URL]
B -->|云凭证| G[AWS_ACCESS_KEY, AZURE_KEY]
B -->|其他| H[12 类总计]
C --> I[High 级别发现]
D --> I
E --> I
F --> I
G --> I暴露类别
| 类别 | 模式示例 | 严重级别 |
|---|---|---|
| API 密钥 | *_API_KEY, *_SECRET_KEY | High |
| 访问令牌 | *_TOKEN, *_ACCESS_TOKEN | High |
| 数据库凭证 | *_PASSWORD, *_CREDENTIALS | Critical |
| 云服务密钥 | AWS_*, AZURE_*, GCP_* | Critical |
生产就绪性检查
检查项目
analyzeReadiness() 函数实现以下生产就绪性检查:
| 检查项 | 条件 | 严重级别 |
|---|---|---|
| 缺失描述 | 工具缺少 description 字段 | Medium |
| 缺失 schema | 工具缺少 inputSchema | Medium |
| 无必需字段 | 关键参数缺少 required 声明 | Medium |
| 过度授权 | 权限范围过大 | High |
| 破坏性工具无安全提示 | 危险操作无 confirm 参数 | Medium |
资料来源:CONTRIBUTING.md:1-20
工具清单变更追踪
哈希机制
decoy-scan 通过 hashToolManifest() 和 detectManifestChanges() 函数追踪工具清单变更:
graph LR
A[首次扫描] -->|生成哈希| B[工具清单哈希]
C[后续扫描] -->|生成哈希| D[工具清单哈希]
B --> E{哈希比对}
D --> E
E -->|哈希变化| F[变更检测]
E -->|哈希相同| G[无变更]
F --> H[报告变更详情]检测变更类型
| 变更类型 | 说明 |
|---|---|
| 工具新增 | 新增的工具可能引入风险 |
| 工具移除 | 移除的工具有安全盲区 |
| 描述变更 | 描述修改可能隐藏恶意行为 |
供应链预警集成
预警数据库
decoy-scan 通过供应链预警功能交叉引用 Decoy 预警数据库,覆盖 40+ 已知存在漏洞的 MCP 包:
graph TD
A[扫描的 MCP 包] --> B{Decoy 预警数据库}
B -->|已知漏洞| C[高风险警告]
B -->|未知| D[通过扫描]
C --> E[提供修复建议]检查方式
预警检查默认启用,可通过以下方式跳过:
npx decoy-scan --no-advisories # 跳过网络调用
退出码与状态
退出码定义
| 退出码 | 含义 | 触发条件 |
|---|---|---|
| 0 | 通过 | 无 critical 或 high 风险问题 |
| 1 | 警告 | 发现 high 风险问题 |
| 2 | 失败 | 发现 critical 问题、工具投毒或有毒数据流 |
`--brief` 输出状态
{
"servers": 3,
"critical": 1,
"high": 2,
"medium": 4,
"low": 5,
"poisoned": 0,
"status": "fail",
"exitCode": 2
}
| 状态值 | 含义 |
|---|---|
pass | 清洁无问题 |
warn | 存在 high 风险 |
fail | 存在 critical/poisoned/toxic-flows |
资料来源:AGENTS.md
输出格式
支持的输出格式
| 格式 | 用途 | 使用场景 |
|---|---|---|
| 人类可读 | 默认输出 | 终端查看 |
--json | 机器可读输出 | CI/CD 集成、代理消费 |
--sarif | SARIF 2.1.0 | GitHub Security 标签 |
--brief | 摘要输出 | 快速状态检查 |
JSON 输出结构
{
"timestamp": "ISO-8601",
"hosts": ["Claude Desktop", "Cursor"],
"servers": [{
"name": "server-name",
"hosts": ["Claude Desktop"],
"command": "npx",
"args": ["@modelcontextprotocol/server-filesystem"],
"tools": [{
"name": "read_file",
"description": "...",
"risk": "high",
"poisoning": [{ "type": "...", "severity": "...", "description": "..." }]
}],
"risk": "high",
"error": null,
"findings": [{
"type": "env-exposure",
"severity": "high",
"description": "...",
"source": "env-config"
}]
}],
"summary": {
"total": 2,
"critical": 1,
"high": 1,
"medium": 0,
"low": 0
}
}
架构组件
核心模块结构
| 模块 | 职责 | 文件位置 |
|---|---|---|
RISK_PATTERNS | 工具风险分类正则 | index.mjs |
POISONING_PATTERNS | 提示词注入检测正则 | index.mjs |
SENSITIVE_ENV_PATTERNS | 环境变量暴露模式 | index.mjs |
OWASP_MAP | OWASP 映射表 | index.mjs |
HOST_CONFIGS | MCP 客户端配置发现 | index.mjs |
classifyTool() | 工具风险分类函数 | index.mjs |
detectPoisoning() | 投毒检测函数 | index.mjs |
analyzeServerCommand() | 服务器命令分析 | index.mjs |
analyzeEnvExposure() | 环境变量暴露分析 | index.mjs |
analyzeReadiness() | 生产就绪性检查 | index.mjs |
probeServer() | MCP stdio 探测 | index.mjs |
scan() | 完整扫描编排 | index.mjs |
toSarif() | SARIF 输出生成 | index.mjs |
资料来源:CONTRIBUTING.md:1-15
扫描流程
graph TD
A[启动扫描] --> B[发现 MCP 服务器]
B --> C[探测服务器工具列表]
C --> D[工具风险分类]
C --> E[提示词注入检测]
C --> F[服务器命令分析]
C --> G[环境变量暴露检测]
C --> H[生产就绪性检查]
D --> I[汇总发现]
E --> I
F --> I
G --> I
H --> I
I --> J[输出报告]
J --> K{退出码判定}
K -->|0| L[无问题]
K -->|1| M[High 风险]
K -->|2| N[Critical/投毒]设计原则
decoy-scan 的安全检查遵循以下核心设计原则:
- 零依赖 — 仅使用 Node.js 内置模块,不引入外部包
- 零构建 — 原始 ES 模块,无需 TypeScript 或打包工具
- 快速 — 扫描应在秒级完成,激进地设置超时
- 安全 — 只读扫描,不修改配置,及时终止派生的服务器进程
- 代理优先 — JSON 和 SARIF 输出必须机器可解析
资料来源:CONTRIBUTING.md:1-5
扩展检测能力
添加新的投毒检测模式
在 POISONING_PATTERNS 中添加新模式:
{
pattern: /new-suspicious-pattern/i,
type: "new-category-name",
severity: "high",
description: "Human-readable description"
}
添加后需在 OWASP_MAP 中注册(如果适用)。
添加新的就绪性检查
在 analyzeReadiness() 函数中添加:
if (/* condition */) {
findings.push({
type: "readiness-check-name",
severity: "medium",
description: "What's wrong and why it matters"
});
}
添加新的主机支持
在 HOST_CONFIGS 中添加新客户端配置:
"New Client": () => {
const p = platform();
if (p === "darwin") return join(homedir(), "path", "to", "config.json");
if (p === "win32") return join(process.env.APPDATA || "", "path", "config.json");
return join(homedir(), ".config", "path", "config.json");
}
相关文档
- CLI 使用指南 — 完整的命令行接口文档
- 贡献指南 — 如何添加新的检测模式
- OWASP Agentic Top 10 2026 — 安全检查的威胁模型基础
资料来源:[README.md](https://github.com/decoy-run/decoy-scan/blob/main/README.md)
风险分级系统
decoy-scan 的风险分级系统是 MCP 安全扫描的核心组件,负责对 MCP 服务器中的工具进行分类、评级和映射。该系统通过多层检测机制,识别工具的风险等级,并将所有发现映射到行业标准 OWASP Agentic Top 10。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
系统概述
风险分级系统位于 index.mjs 主模块中,核心由以下组件构成:
| 组件 | 位置 | 功能描述 |
|---|---|---|
RISK_PATTERNS | index.mjs | 工具风险模式正则表达式集合 |
classifyTool() | index.mjs | 工具风险分类核心函数 |
POISONING_PATTERNS | index.mjs | 提示注入检测模式 |
detectPoisoning() | index.mjs | 提示注入检测函数 |
OWASP_MAP | index.mjs | OWASP 映射配置 |
mapToOwasp() | index.mjs | OWASP 映射转换函数 |
资料来源:CONTRIBUTING.md:代码结构表
风险等级架构
系统采用四级风险分类体系,每个等级对应不同的安全影响和处置策略。
风险等级定义
| 等级 | 严重性 | 影响范围 | 示例工具 |
|---|---|---|---|
| Critical | 关键 | 可执行代码、修改数据、不可逆变更 | execute_command, write_file, eval_code |
| High | 高 | 文件读取、网络访问、数据外泄风险 | read_file, fetch, spawn |
| Medium | 中 | 中等权限操作、需关注配置 | write_config, create_resource |
| Low | 低 | 有限权限、安全风险较低 | read_info, list_items |
Critical 等级工具包括代码执行、文件写入等可能造成不可逆影响的操作。High 等级涵盖文件读取和网络访问等存在数据泄露风险的工具。
资料来源:AGENTS.md:Exit Codes、index.mjs:RISK_PATTERNS
分类算法流程
graph TD
A[工具输入] --> B[提取工具名称]
B --> C{名称匹配 Critical 模式}
C -->|匹配| D[返回 Critical]
C -->|未匹配| E{名称匹配 High 模式}
E -->|匹配| F[返回 High]
E -->|未匹配| G{名称匹配 Medium 模式}
G -->|匹配| H[返回 Medium]
G -->|未匹配| I{名称包含高风险关键词}
I -->|匹配| J[返回 High]
I -->|未匹配| K{描述分析}
K --> L{关键词匹配}
L -->|匹配| M[返回对应等级]
L -->|未匹配| N[返回 Low]
style D fill:#ff6b6b
style F fill:#ffa500
style H fill:#ffd93d
style N fill:#6bcb77classifyTool() 函数首先检查工具名称是否匹配预定义的正则表达式模式,若未匹配则回退到描述分析。
资料来源:CONTRIBUTING.md:RISK_PATTERNS + classifyTool()
工具名称模式匹配
系统通过 RISK_PATTERNS 定义的正则表达式对工具名称进行精确匹配。
Critical 等级模式
| 模式 | 匹配示例 | 说明 | ||||
|---|---|---|---|---|---|---|
^execute_command$ | execute_command | 命令执行 | ||||
^run_.* | run_script, run_sql | 带前缀的运行命令 | ||||
^exec_.* | exec_shell, exec_python | exec 前缀执行 | ||||
| `^eval[_-]?(script\ | code)$` | eval_script, eval-code | 脚本/代码评估 | |||
| `^evaluate[_-]?(script\ | code)$` | evaluate_script | 脚本评估 | |||
| `^execute[_-]?(script\ | code\ | js\ | python\ | sql)$` | execute_python, execute_js | 多语言执行 |
| `^run[_-]?(script\ | code\ | js\ | python\ | sql)$` | run_javascript, run_sql | 多语言运行 |
v0.5.4 版本修复了后缀代码执行名称漏检问题,将正则模式从锚定匹配改为灵活匹配。
资料来源:CHANGELOG.md:v0.5.4 Fixed
描述回退机制
当工具名称未匹配任何模式时,classifyTool() 会将工具名称小写后进行子字符串匹配,作为回退策略。
graph LR
A[名称未匹配] --> B[转小写]
B --> C{子字符串匹配}
C -->|eval| D[可能 High]
C -->|spawn| E[可能 High]
C -->|fetch| F[可能 High]
C -->|无匹配| G[低风险关键词分析]这一机制确保即使工具名称不符合标准命名约定,只要包含高风险动词也能被正确分类。
OWASP Agentic Top 10 映射
系统通过 OWASP_MAP 将所有发现映射到 OWASP Agentic Top 10 标准。
映射配置结构
OWASP_MAP = {
"type-name-1": "ASI01",
"type-name-2": "ASI02",
// ...
}
每个 POISONING_PATTERNS 条目的 type 字段值会关联到对应的 OWASP 分类标准。
资料来源:CONTRIBUTING.md:OWASP_MAP + mapToOwasp()
ASI01–ASI05 映射范围
| OWASP 标准 | 映射类型 | 检测内容 |
|---|---|---|
| ASI01 | 提示注入相关 | 指令覆盖、隐藏注入 |
| ASI02 | 凭证窃取相关 | API 密钥、令牌暴露 |
| ASI03 | 数据外泄相关 | 敏感数据访问 |
| ASI04 | 权限提升相关 | 过度权限配置 |
| ASI05 | 工具影子供给 | 恶意工具替换 |
所有发现都会通过 mapToOwasp() 函数转换为其对应的 OWASP 分类。
提示注入检测模式
POISONING_PATTERNS 包含 37 个正则表达式模式,分布在 20 个攻击类别中。
攻击类别分类
| 类别 | 严重性 | 描述 |
|---|---|---|
| instruction-override | critical | 指令覆盖攻击 |
| concealment | critical | 隐藏指令 |
| credential-harvesting | critical | 凭证收割 |
| data-exfiltration | critical | 数据外泄 |
| coercive-execution | high | 强制执行 |
| tool-shadowing | high | 工具影子 |
| evasion-techniques | medium | 规避技术 |
每个模式定义包含 pattern(正则表达式)、type(分类类型)、severity(严重等级)和 description(描述文本)。
资料来源:CONTRIBUTING.md:POISONING_PATTERNS
检测函数工作流程
graph TD
A[工具描述文本] --> B[遍历 POISONING_PATTERNS]
B --> C{正则匹配}
C -->|匹配| D[生成 poisoning 发现]
C -->|未匹配| E{继续下一模式}
E --> B
D --> F[聚合同一工具的所有发现]
F --> G[返回发现列表]
style A fill:#e3f2fd
style D fill:#ffcdd2
style G fill:#c8e6c9退出码与状态映射
风险分级直接影响程序退出码和扫描状态。
退出码定义
| 退出码 | 触发条件 | status 值 |
|---|---|---|
| 0 | 无 critical 或 high 风险问题 | pass |
| 1 | 发现 high 风险问题 | warn |
| 2 | 发现 critical 问题、工具中毒或毒性数据流 | fail |
--json 和 --brief 输出中都包含 exitCode 字段,便于程序化处理。
资料来源:AGENTS.md:Exit Codes
状态计算逻辑
graph TD
A[扫描结果] --> B{critical 计数 > 0?}
B -->|是| C[status = fail, exitCode = 2]
B -->|否| D{poisoned 计数 > 0?}
D -->|是| C
D -->|否| E{toxicFlows 计数 > 0?}
E -->|是| C
E -->|否| F{high 计数 > 0?}
F -->|是| G[status = warn, exitCode = 1]
F -->|否| H[status = pass, exitCode = 0]
style C fill:#ff6b6b
style G fill:#ffa500
style H fill:#6bcb77策略门控
通过命令行 --policy 参数可以配置策略规则。
| 策略规则 | 失败条件 |
|---|---|
no-critical | 存在 critical 工具 |
no-high | 存在 high 工具 |
no-poisoning | 检测到提示注入 |
no-toxic-flows | 存在毒性数据流 |
no-secrets | 配置中存在暴露的密钥 |
require-tripwires | 未安装 decoy-tripwire |
策略规则在 CI/CD 环境中用于自动化安全门控。
explain 子命令
decoy-scan explain 提供风险分级的交互式解释功能。
支持的查询类型
| kind | 说明 | 示例 |
|---|---|---|
| tier | 严重等级 | explain critical |
| category | 发现类别 | explain tool-description |
| poisoning | 中毒类型 | explain prompt-override |
| tool | 工具名称 | explain read_file |
explain 解析器使用与扫描器相同的 RISK_PATTERNS 和 POISONING_PATTERNS 数据源,确保解释与实际检测结果一致。
资料来源:AGENTS.md:explain subcommand
JSON 输出结构
{
"tool": "decoy-scan",
"version": "0.5.1",
"target": "critical",
"result": {
"kind": "tier",
"key": "critical",
"title": "Critical",
"summary": "Can execute code, modify data, or cause irreversible changes.",
"body": "...",
"examples": ["execute_command", "write_file", "..."],
"advice": "..."
}
}
库导出接口
decoy-scan 作为库使用时可直接导入分类功能:
import {
classifyTool,
detectPoisoning,
mapToOwasp,
} from 'decoy-scan';
const risk = classifyTool({ name: "read_file", description: "..." });
const poisoningFindings = detectPoisoning(toolDescription);
const owaspCategory = mapToOwasp(findingType);
这使得其他安全工具可以复用 decoy-scan 的风险分级能力。
资料来源:README.md:Library
版本演进
| 版本 | 重要变更 |
|---|---|
| v0.1.0 | 初始发布,基础风险分类 |
| v0.5.4 | 修复后缀代码执行名称漏检,子字符串回退增强 |
| v0.5.6 | 增强对 evaluate_script、eval_code 等工具的检测 |
CHANGELOG.md 记录了风险分级系统的所有重要变更。
资料来源:[CONTRIBUTING.md:代码结构表]()
提示注入检测
提示注入检测(Prompt Injection Detection)是 decoy-scan 工具的核心安全功能之一,旨在识别 MCP(Model Context Protocol)服务器工具描述中隐藏的恶意提示注入攻击。该功能通过正则表达式模式匹配技术,分析工具的名称和描述文本,检测 37 种不同的攻击模式,覆盖 20 个攻击类别。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
提示注入检测(Prompt Injection Detection)是 decoy-scan 工具的核心安全功能之一,旨在识别 MCP(Model Context Protocol)服务器工具描述中隐藏的恶意提示注入攻击。该功能通过正则表达式模式匹配技术,分析工具的名称和描述文本,检测 37 种不同的攻击模式,覆盖 20 个攻击类别。
主要职责包括:
- 在工具描述中识别隐藏的指令覆盖攻击
- 检测伪装和隐蔽性攻击
- 发现数据泄露和凭证收集企图
- 识别强制执行和工具影子供给
- 映射攻击类型至 OWASP Agentic Top 10 标准
资料来源:README.md:47
架构设计
整体架构
提示注入检测系统位于扫描流程的核心位置,与工具风险分类、毒性流分析和 OWASP 映射等功能紧密协作。
graph TD
A[MCP Server 工具列表] --> B[detectPoisoning 检测器]
B --> C{匹配结果}
C -->|有匹配| D[生成 Poisoning Finding]
C -->|无匹配| E[标记为安全]
D --> F[OWASP 映射]
F --> G[风险报告输出]
E --> G
B --> H[explain 子命令]
H --> I[结构化解释 JSON]核心模块关系
| 模块 | 文件位置 | 职责 |
|---|---|---|
POISONING_PATTERNS | index.mjs / lib/patterns.mjs | 定义所有检测正则表达式模式 |
detectPoisoning() | index.mjs / lib/analyzers.mjs | 执行模式匹配和分析逻辑 |
OWASP_MAP | index.mjs | 将攻击类型映射至 OWASP 标准 |
explain 子命令 | bin/cli.mjs | 提供人可读和机器可解析的解释 |
资料来源:CONTRIBUTING.md:23
检测模式体系
攻击类别总览
decoy-scan 采用分层分类体系组织检测模式,每个模式包含正则表达式、攻击类型、严重等级和人类可读的描述。
{
pattern: /regex/i, // 正则匹配表达式
type: "category-name", // 攻击类型标识
severity: "critical", // 严重等级
description: "人类可读描述" // 输出展示
}
支持的攻击类别
系统支持检测以下 20 个攻击类别的提示注入模式:
| 类别 | 描述 | 严重等级示例 |
|---|---|---|
instruction-override | 指令覆盖攻击 | critical |
concealment | 伪装攻击 | critical/high |
data-exfiltration | 数据泄露 | critical |
credential-harvesting | 凭证收集 | critical |
coercive-execution | 强制执行 | high |
tool-shadowing | 工具影子 | high |
evasion-techniques | 规避技术 | medium/high |
| 其他 13 个类别 | 各类隐蔽攻击 | varying |
资料来源:README.md:47
严重等级定义
| 等级 | 含义 | 退出码影响 |
|---|---|---|
critical | 可执行代码、修改数据或造成不可逆变更 | 退出码 2 |
high | 高风险操作如文件读取、网络访问 | 退出码 1 |
medium | 中等风险,需关注 | 无退出码影响 |
low | 低风险操作 | 无退出码影响 |
资料来源:AGENTS.md:43-47
工作流程
扫描执行流程
sequenceDiagram
participant Scanner as 扫描器
participant Pattern as POISONING_PATTERNS
participant Analyzer as 检测引擎
participant OWASP as OWASP_MAP
participant Output as 输出系统
Scanner->>Scanner: 发现 MCP 服务器
Scanner->>Scanner: 获取工具列表
Loop 每个工具
Scanner->>Analyzer: 传入工具名称和描述
Analyzer->>Pattern: 遍历正则模式
Pattern-->>Analyzer: 匹配结果
Analyzer->>Analyzer: 分类严重等级
Analyzer->>OWASP: 映射攻击类型
OWASP-->>Analyzer: ASI 代码
end
Analyzer-->>Scanner: 检测结果
Scanner->>Output: 生成报告输出格式
#### 工具级别输出
每个被检测为存在提示注入的工具包含以下字段:
{
"name": "tool-name",
"risk": "critical",
"poisoning": [{
"type": "instruction-override",
"severity": "critical",
"description": "发现指令覆盖攻击模式"
}]
}
#### JSON 完整输出
{
"timestamp": "ISO-8601",
"servers": [{
"name": "server-name",
"tools": [{
"name": "tool-name",
"description": "...",
"risk": "critical",
"poisoning": [...]
}]
}],
"summary": {
"poisoned": 0
}
}
资料来源:AGENTS.md:59-74
API 与接口
库函数导出
decoy-scan 提供独立的 JavaScript 模块接口,可供其他项目导入使用:
import {
scan,
detectPoisoning,
classifyTool,
analyzeToxicFlows,
} from 'decoy-scan';
const results = await scan({ skills: true });
console.log(results.servers[0].tools[0].poisoning);
detectPoisoning 函数签名
| 参数 | 类型 | 描述 |
|---|---|---|
toolName | string | 工具名称 |
toolDescription | string | 工具描述文本 |
| 返回值 | array | 匹配到的 poisoning 对象数组 |
explain 子命令
用于解析特定发现含义的辅助命令:
decoy-scan explain prompt-override # 攻击类型说明
decoy-scan explain list # 列举所有可解释目标
decoy-scan explain <target> --json # 机器可读输出
#### --json 输出结构
{
"tool": "decoy-scan",
"version": "0.5.1",
"target": "instruction-override",
"result": {
"kind": "poisoning",
"key": "instruction-override",
"title": "指令覆盖",
"summary": "攻击者尝试覆盖原始指令",
"examples": ["...具体示例..."],
"advice": "建议修复措施"
}
}
资料来源:AGENTS.md:29-41
配置与扩展
添加新的检测模式
在 POISONING_PATTERNS 中添加新模式:
{
pattern: /new-malicious-pattern/i,
type: "new-attack-category",
severity: "high",
description: "新攻击类型的描述"
}
添加后需将 type 值注册到 OWASP_MAP 中:
const OWASP_MAP = {
// ... 现有映射
"new-attack-category": "ASI01",
};
OWASP Agentic Top 10 映射
所有攻击类型均映射至 OWASP Agentic Top 10 标准,便于安全合规报告:
| OWASP 代码 | 攻击类型 |
|---|---|
| ASI01 | Agentic 系统提示注入 |
| ASI02 | 敏感信息泄露 |
| ASI03 | 工具操作验证不足 |
| ASI04 | 供应链攻击 |
| ASI05 | 权限过度授予 |
资料来源:README.md:56
输出与报告
退出码机制
提示注入检测结果直接影响命令退出码:
| 退出码 | 触发条件 |
|---|---|
0 | 无 critical 或 high 风险问题 |
1 | 发现 high 风险问题 |
2 | 发现 critical 问题、工具污染或毒性流 |
--brief 摘要输出
最小化摘要对象:
{
"servers": 3,
"critical": 1,
"high": 2,
"poisoned": 0,
"status": "fail",
"exitCode": 2
}
SARIF 格式支持
支持 SARIF 2.1.0 标准输出,可上传至 GitHub Security:
decoy-scan --sarif
毒性流分析
除了单工具检测外,系统还支持跨服务器数据泄露(TF001)和破坏性(TF002)攻击链分析:
import { analyzeToxicFlows } from 'decoy-scan';
const results = await scan();
console.log(results.toxicFlows);
资料来源:README.md:66-68
版本变更历史
关键版本更新
| 版本 | 日期 | 变更内容 |
|---|---|---|
| 0.1.0 | 2026-03-15 | 初始发布,支持基础提示注入检测 |
| 0.2.0 | 2026-03-20 | 添加 SSE 传输安全检查和输入验证 |
| 0.5.0 | 2026-04-21 | 新增 explain 子命令,改进分类逻辑 |
| 0.5.6 | 2026-04-28 | 修复 classifyTool 对代码执行名称的遗漏 |
| 0.7.0 | 2026-05-10 | 增强遥测功能,完善 v2 事件信封 |
资料来源:CHANGELOG.md:1-100
设计原则
零依赖原则
检测引擎完全基于 Node.js 原生能力实现,无外部 npm 依赖:
- 仅使用内置
RegExp模块进行模式匹配 - 不依赖第三方安全扫描库
- 确保扫描速度和可靠性
无修改原则
所有检测操作均为只读扫描:
- 不修改任何 MCP 配置文件
- 不修改工具描述或服务器状态
- 及时终止检测过程中启动的服务器进程
快速完成原则
扫描应在数秒内完成:
- 主动超时机制终止响应慢的服务器
- 高效的正则表达式模式匹配
- 并行处理多服务器扫描
Agent 优先原则
所有输出格式优先考虑机器可解析性:
- JSON 输出格式稳定、结构化
- SARIF 格式符合行业标准
--json和--brief输出包含exitCode字段便于自动化决策
命令行使用
基础扫描
npx decoy-scan # 完整扫描
npx decoy-scan --json # 机器可读输出
npx decoy-scan --sarif # SARIF 格式输出
详细模式
npx decoy-scan --verbose # 显示所有工具包括 low 风险
npx decoy-scan --no-probe # 仅配置文件检测
npx decoy-scan --no-advisories # 跳过网络调用
CI/CD 集成
# .github/workflows/mcp-security.yml
name: MCP Security
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: decoy-run/decoy-scan@v1
with:
policy: no-critical,no-poisoning
sarif: true
策略规则
| 规则 | 描述 |
|---|---|
no-critical | 禁止 critical 级别工具 |
no-high | 禁止 high 级别工具 |
no-poisoning | 禁止工具描述中的提示注入 |
no-toxic-flows | 禁止跨服务器数据泄露 |
no-secrets | 禁止 MCP 配置中的敏感信息 |
require-tripwires | 要求安装 decoy-tripwire |
资料来源:README.md:89-96
局限性说明
检测范围限制
- 检测基于正则表达式模式匹配,可能无法识别未知变体攻击
- 仅分析工具名称和描述文本,不深入分析工具实现逻辑
- 依赖服务器正确响应工具列表请求
误报与漏报
- 高敏感度配置可能导致部分合法工具被标记
- 混淆或编码的恶意内容可能被遗漏
- 建议结合人工审查进行最终判断
跨语言支持
- 默认检测模式针对英文文本设计
- 非英文工具描述的检测准确度可能降低
资料来源:[README.md:47]()
扫描架构
decoy-scan 的扫描架构是一套零依赖的 MCP(Model Context Protocol)安全扫描解决方案,采用纯 Node.js 原生模块实现。该架构通过配置文件发现、服务器探测、工具风险分析、投毒检测、有毒流程分析和供应链审查等多个环节,对本地 MCP 服务器配置进行全面的安全评估。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
decoy-scan 的扫描架构是一套零依赖的 MCP(Model Context Protocol)安全扫描解决方案,采用纯 Node.js 原生模块实现。该架构通过配置文件发现、服务器探测、工具风险分析、投毒检测、有毒流程分析和供应链审查等多个环节,对本地 MCP 服务器配置进行全面的安全评估。
扫描架构的核心设计原则包括:
- 零依赖:仅使用 Node.js 内置模块,无需安装任何 npm 包
- 无构建步骤:直接运行 ES 模块
- 快速执行:对服务器进行激进超时,扫描应在数秒内完成
- 安全操作:仅读取配置,从不修改,使用后立即终止生成的服务器进程
资料来源:CONTRIBUTING.md
核心模块划分
decoy-scan 的扫描架构由多个核心模块组成,每个模块负责特定的安全检查功能:
| 模块 | 文件位置 | 核心功能 |
|---|---|---|
| 扫描编排器 | lib/scan.mjs | 协调整个扫描流程 |
| 服务器探测 | lib/probe.mjs | 通过 stdio 协议探测 MCP 服务器 |
| 策略验证 | lib/verify.mjs | 验证扫描结果是否满足策略要求 |
| 工具分类器 | index.mjs | 工具风险等级分类 |
| 投毒检测器 | index.mjs | 检测提示词注入攻击 |
| 环境分析器 | index.mjs | 分析敏感环境变量暴露 |
| 就绪检查器 | index.mjs | 生产环境就绪状态评估 |
| 配置发现器 | index.mjs | 发现本地 MCP 客户端配置 |
资料来源:CONTRIBUTING.md
扫描流程架构图
扫描流程采用流水线式的处理架构,从配置发现到最终报告生成依次执行:
graph TD
A[开始扫描] --> B[发现 MCP 配置]
B --> C{发现配置?}
C -->|无| D[生成空结果]
C -->|有| E[遍历每个服务器配置]
E --> F[解析服务器启动命令]
F --> G{是否探测服务器}
G -->|否| H[跳过探测]
G -->|是| I[通过 stdio 探测服务器]
I --> J{探测成功?}
J -->|失败| K[记录探测失败]
J -->|成功| L[获取工具列表]
L --> M[执行安全分析]
M --> N{分析完成?}
N -->|是| O[汇总结果]
K --> O
H --> O
O --> P[生成输出报告]
P --> Q[退出]
D --> Q配置发现模块
配置发现模块负责定位本地系统中各 MCP 客户端的配置文件。该模块维护了一个 HOST_CONFIGS 配置映射,支持以下 MCP 客户端:
- Claude Desktop
- Cursor
- Windsurf
- VS Code
- Claude Code
- Zed
- Cline
配置发现器针对不同操作系统(macOS、Windows、Linux)使用不同的配置文件路径:
"Claude Desktop": () => {
const p = platform();
if (p === "darwin") return join(homedir(), "path", "to", "config.json");
if (p === "win32") return join(process.env.APPDATA || "", "path", "config.json");
return join(homedir(), ".config", "path", "config.json");
}
资料来源:CONTRIBUTING.md
项目级配置支持
除系统级 MCP 客户端配置外,扫描器还支持项目级别的 .mcp.json 配置文件。从项目根目录运行时,会自动包含项目级配置扫描。
资料来源:AGENTS.md
服务器探测模块
探测模块是扫描架构的核心组件之一,负责与 MCP 服务器建立通信并获取其工具列表。
stdio 协议探测
探测模块通过 stdio 协议与 MCP 服务器交互:
- 解析服务器启动命令和参数
- 生成子进程并启动 MCP 服务器
- 发送 JSON-RPC 格式的
tools/list请求 - 接收并解析服务器返回的工具列表
- 正常终止服务器进程
探测超时机制
为保证扫描速度,探测模块采用激进超时策略:
- 探测超时后会立即终止服务器进程
- 探测失败的服务器会记录错误信息但不影响整体扫描继续
// 超时后立即终止并清理
killSpawnedServers();
资料来源:CONTRIBUTING.md
探测结果处理
探测结果包含以下信息:
| 字段 | 说明 |
|---|---|
name | 服务器名称 |
command | 启动命令 |
args | 命令参数 |
tools | 工具列表(包含名称、描述、输入模式) |
error | 探测错误信息(如有) |
资料来源:AGENTS.md
安全分析模块
安全分析模块是扫描架构的核心部分,包含多个子分析器:
工具风险分类器
工具风险分类器(classifyTool)根据工具名称和描述将工具分为四个风险等级:
| 风险等级 | 说明 | 示例 |
|---|---|---|
| critical | 可执行代码、修改数据或造成不可逆更改 | execute_command, write_file |
| high | 读取文件或发起网络请求 | read_file, fetch_url |
| medium | 访问系统信息或执行其他操作 | get_system_info |
| low | 低风险工具 | 其他工具 |
分类器使用 RISK_PATTERNS 正则表达式模式匹配工具名称,并结合工具描述进行综合判断。
关键风险模式包括:
{
pattern: /^execute[_-]?(script|code|js|javascript|python|sql)$/,
type: "critical",
severity: "critical"
}
资料来源:CONTRIBUTING.md
投毒检测器
投毒检测器(detectPoisoning)使用 37 种正则模式检测工具描述中的提示词注入攻击,涵盖 20 个攻击类别:
- 指令覆盖(instruction override)
- 隐蔽技术(concealment)
- 数据泄露(data exfiltration)
- 凭证收割(credential harvesting)
- 强制执行(coercive execution)
- 工具影子(tool shadowing)
- 规避技术(evasion techniques)
每个投毒模式包含:
{
pattern: /regex/i,
type: "category-name",
severity: "critical",
description: "Human-readable description"
}
资料来源:CONTRIBUTING.md
服务器命令分析器
命令分析器(analyzeServerCommand)检查服务器启动命令中的可疑特征:
- 管道到 shell(pipe-to-shell)
- 临时目录执行
- 内联代码注入
- 误植域名攻击(typosquatting)
- 网络工具调用
环境变量暴露分析器
环境分析器(analyzeEnvExposure)使用 SENSITIVE_ENV_PATTERNS 模式检测 12 类敏感凭证暴露:
- API 密钥
- 访问令牌
- 密码
- 数据库连接 URL
- 云服务凭证
- 其他敏感环境变量
就绪状态检查器
就绪状态检查器(analyzeReadiness)评估生产环境部署就绪程度,检查项包括:
- 缺失工具描述
- 缺失输入模式
- 缺少必需字段
- 过度授权的工具范围
- 破坏性工具缺少安全提示
OWASP 映射器
OWASP 映射器(mapToOwasp)将所有发现映射到 OWASP Agentic Top 10:
- ASI01 - Agentic AI Inventory and Tracking
- ASI02 - Sensitive Data Exposure
- ASI03 - Tool Poisoning
- ASI04 - Agentic AI Hallucinations and Mismanagement
- ASI05 - Overprivileged Agents and Tools
资料来源:README.md
有毒流程分析
除单个工具的安全分析外,扫描架构还支持跨服务器的有毒流程分析(analyzeToxicFlows):
| 流程类型 | ID | 严重性 | 说明 |
|---|---|---|---|
| 数据泄露 | TF001 | critical | 跨服务器数据泄露攻击链 |
| 破坏性操作 | TF002 | critical | 跨服务器破坏性操作链 |
有毒流程分析在库模式下可用:
import { scan, analyzeToxicFlows } from 'decoy-scan';
const results = await scan({ skills: true });
console.log(results.toxicFlows);
资料来源:AGENTS.md
供应链审查
扫描架构包含供应链安全审查功能:
已知漏洞包检测
通过 Decoy advisory 数据库(40+ MCP 包)对配置中的服务器进行已知漏洞匹配。
工具清单哈希追踪
工具清单哈希(hashToolManifest)功能可以检测工具变更:
- 工具新增
- 工具移除
- 工具描述变更
通过 detectManifestChanges 函数比较两次扫描之间的工具清单差异。
资料来源:AGENTS.md
技能扫描
扫描架构支持对 Claude Code 技能进行专项安全扫描(discoverSkills 和 analyzeSkill):
- 提示词注入检测
- 硬编码密钥检测
- 可疑 URL 检测
import { scan, discoverSkills, analyzeSkill } from 'decoy-scan';
const results = await scan({ skills: true });
console.log(results.skills);
资料来源:AGENTS.md
策略验证模块
策略验证模块(lib/verify.mjs)根据用户定义的策略规则验证扫描结果:
策略规则语法
| 规则 | 说明 |
|---|---|
no-critical | 不允许关键风险工具 |
no-high | 不允许高风险工具 |
no-poisoning | 不允许提示词注入 |
no-toxic-flows | 不允许有毒流程 |
no-secrets | 不允许暴露密钥 |
require-tripwires | 要求安装 decoy-tripwire |
max-critical=N | 限制关键问题数量 |
策略检查失败会设置相应的退出码。
资料来源:README.md
输出报告生成
SARIF 报告
SARIF(Static Analysis Results Interchange Format)是一种结构化的安全报告格式,用于 CI/CD 集成:
import { scan, toSarif } from 'decoy-scan';
const results = await scan();
const sarif = toSarif(results);
SARIF 输出会包含:
- 规则 ID 和级别
- 问题位置和描述
- 建议的修复方案
- OWASP 映射信息
退出码规范
| 退出码 | 含义 |
|---|---|
| 0 | 无关键或高风险问题 |
| 1 | 发现高风险问题 |
| 2 | 发现关键问题、工具投毒或策略违规 |
退出码在 --json 和 --brief 输出的 exitCode 字段中也会体现,便于程序化处理。
资料来源:AGENTS.md
CLI 入口
命令行入口位于 bin/cli.mjs,负责:
- 解析命令行参数
- 初始化扫描配置
- 调用扫描模块
- 格式化输出结果
- 处理退出逻辑
支持的输出模式
| 模式 | 说明 |
|---|---|
| 默认 | 人类可读的彩色输出 |
--json | 机器可解析的 JSON 格式 |
--sarif | SARIF 2.1.0 标准格式 |
--brief | 最小化摘要信息 |
--verbose | 显示所有工具包括低风险 |
可用参数
| 参数 | 说明 |
|---|---|
--no-probe | 仅扫描配置,不探测服务器 |
--no-advisories | 跳过网络请求(供应链审查) |
--quiet | 静默模式,抑制状态输出 |
--version | 显示版本信息 |
资料来源:AGENTS.md
数据流架构图
graph LR
A[MCP 配置文件] --> B[配置发现器]
B --> C[服务器列表]
C --> D{探测模式}
D -->|探测| E[stdio 探测]
D -->|跳过| F[跳过探测]
E --> G[工具列表]
F --> H[空工具列表]
G --> I[安全分析引擎]
H --> I
I --> J[风险分类结果]
I --> K[投毒检测结果]
I --> L[环境分析结果]
I --> M[就绪检查结果]
J --> N[结果汇总]
K --> N
L --> N
M --> N
N --> O[策略验证]
O --> P{SARIF 格式?}
P -->|是| Q[SARIF 报告]
P -->|否| R[JSON/文本报告]
Q --> S[GitHub Security]
R --> T[终端输出]扩展机制
添加新的投毒模式
在 POISONING_PATTERNS 中添加新模式:
{
pattern: /regex/i,
type: "category-name",
severity: "critical",
description: "Human-readable description"
}
添加后需在 OWASP_MAP 中添加对应的映射。
添加新的 MCP 客户端支持
在 HOST_CONFIGS 中添加新的客户端条目:
"New Client": () => {
const p = platform();
if (p === "darwin") return join(homedir(), "path", "to", "config.json");
if (p === "win32") return join(process.env.APPDATA || "", "path", "config.json");
return join(homedir(), ".config", "path", "config.json");
}
添加新的就绪检查
在 analyzeReadiness() 函数中添加检查逻辑:
if (/* condition */) {
findings.push({
type: "readiness-check-name",
severity: "medium",
description: "What's wrong and why it matters"
});
}
资料来源:CONTRIBUTING.md
性能特性
扫描架构的性能设计目标:
- 快速启动:无依赖安装,npx 直接运行
- 快速扫描:激进超时策略,单个服务器探测有明确时间限制
- 并行发现:配置文件发现与初步分析可并行执行
- 资源高效:无额外进程开销,服务器进程及时清理
安全特性
扫描架构的安全设计原则:
| 特性 | 实现方式 |
|---|---|
| 读取隔离 | 仅读取配置,从不修改 |
| 进程控制 | 服务器进程用后即删 |
| 无持久化 | 不在系统留下痕迹 |
| 隐私保护 | 支持 --no-telemetry 禁用遥测 |
| 安全报告 | 敏感信息脱敏处理 |
版本演进
| 版本 | 重大变更 |
|---|---|
| 0.8.0 | v2 遥测信封格式 |
| 0.7.0 | 供应链 advisories、工具清单哈希追踪 |
| 0.5.0 | 新增 explain 子命令 |
| 0.2.0 | SSE 传输安全检查、输入验证 |
| 0.1.0 | 初始版本发布 |
资料来源:CHANGELOG.md
资料来源:[CONTRIBUTING.md](https://github.com/decoy-run/decoy-scan/blob/main/CONTRIBUTING.md)
MCP 主机发现
MCP 主机发现是 decoy-scan 工具的核心功能之一,负责自动检测本地机器上所有已配置的 MCP(Model Context Protocol)客户端主机,并收集其 MCP 服务器配置信息。该功能使工具能够对用户环境中的 MCP 生态系统进行全面的安全扫描,无需用户手动指定配置文件路径。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
MCP 主机发现是 decoy-scan 工具的核心功能之一,负责自动检测本地机器上所有已配置的 MCP(Model Context Protocol)客户端主机,并收集其 MCP 服务器配置信息。该功能使工具能够对用户环境中的 MCP 生态系统进行全面的安全扫描,无需用户手动指定配置文件路径。
decoy-scan 采用零依赖设计,完全使用 Node.js 内置模块实现主机发现功能,确保扫描过程快速、轻量且可靠。发现阶段会遍历操作系统特定的配置文件路径,解析 MCP 服务器定义,并准备后续的安全分析工作。
支持的 MCP 主机
decoy-scan 目前支持 7 种主流 MCP 客户端主机,覆盖桌面 IDE、代码编辑器、AI 编程工具等多种开发环境。
| 主机名称 | 类型 | 支持平台 | 典型用途 |
|---|---|---|---|
| Claude Desktop | AI 助手 | macOS/Windows/Linux | Anthropic Claude 桌面集成 |
| Cursor | AI 代码编辑器 | macOS/Windows/Linux | AI 驱动的代码补全与生成 |
| Windsurf | AI 代码编辑器 | macOS/Windows/Linux | Cascade AI 工作流 |
| VS Code | 代码编辑器 | macOS/Windows/Linux | Microsoft Copilot 集成 |
| Claude Code | CLI 工具 | macOS/Windows/Linux | 命令行 Claude 交互 |
| Zed | 代码编辑器 | macOS/Windows/Linux | 高性能 GPU 加速编辑器 |
| Cline | VS Code 扩展 | macOS/Windows/Linux | AI 自主编程代理 |
资料来源:AGENTS.md:Supported Hosts (7)
平台感知配置路径
MCP 主机发现模块的核心设计原则是平台感知——根据不同操作系统采用相应的配置文件路径规范。这种设计确保工具在 macOS、Windows 和 Linux 三大主流平台上均能正确发现 MCP 配置。
配置路径规范
graph TD
A[启动扫描] --> B{检测操作系统}
B -->|macOS| C[使用 homedir() 路径]
B -->|Windows| D[使用 APPDATA 环境变量]
B -->|Linux| E[使用 ~/.config 目录]
C --> F[调用平台特定路径解析函数]
D --> F
E --> F
F --> G[发现 MCP 服务器配置]
G --> H[解析配置文件 JSON]
H --> I[提取服务器定义列表]路径发现机制
各平台的标准配置存储位置如下:
| 平台 | 配置目录 | 说明 |
|---|---|---|
| macOS | ~/Library/Application Support/ | 使用 homedir() 获取用户主目录 |
| Windows | %APPDATA% | 使用 process.env.APPDATA 环境变量 |
| Linux | ~/.config/ | 标准 XDG 配置目录规范 |
// 主机配置结构示例 (CONTRIBUTING.md)
"New Client": () => {
const p = platform();
if (p === "darwin") return join(homedir(), "path", "to", "config.json");
if (p === "win32") return join(process.env.APPDATA || "", "path", "config.json");
return join(homedir(), ".config", "path", "to", "config.json");
},
资料来源:CONTRIBUTING.md:Adding Host Configs
发现流程架构
MCP 主机发现模块位于 lib/discovery.mjs,是扫描管道的第一个关键环节。整个发现流程分为配置探测、服务器提取、重复数据删除三个主要阶段。
完整发现流程
graph TD
A[MCP 主机发现开始] --> B[遍历 HOST_CONFIGS]
B --> C{当前平台匹配?}
C -->|是| D[读取配置文件]
C -->|否| E[跳过该主机]
D --> F{配置文件存在?}
F -->|是| G[解析 JSON 配置]
F -->|否| E
G --> H[提取 servers 数组]
H --> I{发现 decoy-tripwire?}
I -->|是| J[去重标记]
I -->|否| K[添加至待扫描列表]
J --> L[跨主机去重]
K --> L
L --> M[返回已发现服务器列表]
E --> B配置文件解析
发现的 MCP 配置文件通常为 JSON 格式,包含服务器的启动命令、参数列表等核心定义:
{
"servers": [{
"name": "server-name",
"command": "npx",
"args": ["@modelcontextprotocol/server-filesystem"],
"env": {}
}]
}
解析后的数据将传递给后续的 probeServer() 模块进行 MCP stdio 探测。
资料来源:AGENTS.md:JSON Output Schema
服务器探测阶段
在主机发现完成后,decoy-scan 对每个已发现的 MCP 服务器执行 stdio 探测,查询其工具列表并进行分析。
探测流程
sequenceDiagram
participant 扫描器 as decoy-scan
participant 服务器 as MCP Server
participant 分析器 as 安全分析引擎
扫描器->>服务器: 启动服务器进程 (stdio)
扫描器->>服务器: 发送 initialize 请求
服务器-->>扫描器: 返回 server info
扫描器->>服务器: 发送 tools/list 请求
服务器-->>扫描器: 返回工具列表
扫描器->>分析器: 传递工具列表
分析器->>分析器: 风险分类
分析器->>分析器: 投毒检测
分析器->>分析器: 准备就绪检查
扫描器->>服务器: 终止进程探测超时控制
为确保扫描性能,服务器探测采用激进超时策略。如果服务器在规定时间内未响应,探测将被强制终止并记录错误信息。
// 探测失败处理
if (probeError) {
findings.push({
type: "probe-failed",
severity: "medium",
description: "服务器探测超时或连接失败"
});
}
资料来源:AGENTS.md:JSON Output Schema:error
输出格式
发现阶段的输出可采用多种格式,便于不同使用场景的消费:
JSON 格式
{
"timestamp": "ISO-8601",
"hosts": ["Claude Desktop", "Cursor"],
"servers": [{
"name": "server-name",
"hosts": ["Claude Desktop"],
"command": "npx",
"args": ["@modelcontextprotocol/server-filesystem"],
"tools": [{
"name": "read_file",
"description": "...",
"risk": "high",
"poisoning": [{ "type": "...", "severity": "...", "description": "..." }]
}],
"risk": "high",
"error": null
}]
}
SARIF 格式
通过 --sarif 参数可输出符合 SARIF 2.1.0 标准的格式,便于集成到 CI/CD 安全扫描流程中:
runs:
- results:
- ruleId: "critical-tool"
level: "error"
message: "发现高风险工具"
资料来源:lib/sarif.mjs
与其他模块的集成
MCP 主机发现是扫描管道的第一步,后续安全分析依赖于发现阶段提供的数据:
graph LR
A[MCP 主机发现] --> B[工具风险分类]
A --> C[投毒检测]
A --> D[服务器命令分析]
A --> E[环境变量暴露检测]
A --> F[准备就绪检查]
A --> G[供应链告警]
B --> H[结果聚合]
C --> H
D --> H
E --> H
F --> H
G --> H
H --> I[JSON/SARIF 输出]
H --> J[策略检查]
J --> K{通过?}
K -->|是| L[退出码 0]
K -->|否| M[退出码 1/2]各模块依赖关系
| 模块 | 依赖发现数据 | 功能说明 |
|---|---|---|
| 工具风险分类 | ✓ | 基于工具名称和描述进行风险评级 |
| 投毒检测 | ✓ | 检测工具描述中的提示注入模式 |
| 服务器命令分析 | ✓ | 检查启动命令的安全性 |
| 环境变量暴露检测 | ✓ | 扫描配置中的敏感凭证 |
| 准备就绪检查 | ✓ | 评估生产环境就绪程度 |
| 供应链告警 | ✓ | 对已知漏洞包进行交叉比对 |
资料来源:CONTRIBUTING.md:Code Structure
扩展主机支持
decoy-scan 支持通过修改 HOST_CONFIGS 配置对象来添加新的 MCP 主机支持。
添加新主机步骤
- 在
index.mjs中的HOST_CONFIGS对象添加新条目 - 实现平台感知的路径解析逻辑
- 确保配置文件格式符合 MCP 规范
- 运行
npm test验证测试通过
配置模板
HOST_CONFIGS: {
// ... 现有配置
"New MCP Client": () => {
const p = platform();
if (p === "darwin") {
return join(homedir(), "Library", "Application Support", "NewClient", "config.json");
}
if (p === "win32") {
return join(process.env.APPDATA || "", "NewClient", "config.json");
}
// Linux
return join(homedir(), ".config", "newclient", "config.json");
}
}
资料来源:CONTRIBUTING.md:Adding Host Configs
错误处理与鲁棒性
主机发现模块具备完善的错误处理机制,确保在各种异常情况下仍能提供有用的诊断信息。
常见错误场景
| 错误类型 | 处理方式 | 用户提示 |
|---|---|---|
| 配置文件不存在 | 静默跳过 | 无 |
| JSON 解析失败 | 记录错误 | 显示解析错误详情 |
| 权限不足 | 捕获异常 | 提示权限问题 |
| 探测超时 | 强制终止 | 显示 ? probe failed |
探针失败展示
当服务器探测失败时,CLI 输出会显示明确的错误标识:
? filesystem-server probe failed
Error: Connection timeout after 5000ms
资料来源:CHANGELOG.md:0.5.3:Fixed
设计原则
MCP 主机发现模块遵循 decoy-scan 的核心设计理念:
| 原则 | 实现方式 | 优势 |
|---|---|---|
| 零依赖 | 纯 Node.js 内置模块 | 无需安装额外包 |
| 零配置 | 自动探测本机配置 | 开箱即用 |
| 快速 | 异步 I/O + 超时控制 | 秒级完成扫描 |
| 安全 | 只读扫描不修改配置 | 不影响用户环境 |
| Agent 优先 | JSON/SARIF 结构化输出 | 便于自动化集成 |
资料来源:CONTRIBUTING.md:Design Principles
命令行使用
主机发现功能通过以下命令行参数进行控制:
| 参数 | 功能 | 说明 |
|---|---|---|
| 无参数 | 全量扫描 | 发现所有主机和服务器 |
--no-probe | 仅配置发现 | 跳过服务器探测,仅读取配置 |
--no-advisories | 跳过网络请求 | 跳过供应链告警检查 |
--verbose | 显示所有工具 | 包括低风险工具 |
--json | JSON 输出 | 结构化机器可读输出 |
--sarif | SARIF 输出 | 符合 SARIF 2.1.0 标准 |
# 仅发现配置,不探测服务器
npx decoy-scan --no-probe
# 跳过供应链告警检查
npx decoy-scan --no-advisories
# 详细输出模式
npx decoy-scan --verbose
资料来源:AGENTS.md:CLI Flags
技术规格
| 规格项 | 值 |
|---|---|
| 支持平台 | macOS, Windows, Linux |
| Node.js 最低版本 | 18+ |
| 依赖数量 | 0 (零依赖) |
| 配置格式 | JSON |
| 默认超时 | 5000ms |
| 并发探测 | 串行执行 |
总结
MCP 主机发现是 decoy-scan 实现自动化安全扫描的基础能力,通过平台感知的配置路径解析和结构化的服务器发现机制,为后续的安全分析提供了完整的目标清单。该模块的零依赖设计和只读扫描原则确保了工具的便携性和安全性,使其能够在各种开发环境中无缝集成到 CI/CD 流程中。
资料来源:[AGENTS.md:Supported Hosts (7)]()
有毒数据流分析
有毒数据流分析(Tainted Flow Analysis 或 Toxic Flow Analysis)是 decoy-scan 安全扫描器的核心检测模块之一。该模块通过追踪 MCP 服务器之间的数据传递路径,识别潜在的安全威胁链,包括跨服务器数据泄露和破坏性操作链。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
在 MCP(Model Context Protocol)生态系统中,多个服务器通常协同工作,每个服务器拥有不同的工具和权限。有毒数据流分析模块专门检测以下两类攻击链:
| 攻击类型 | 标识符 | 严重级别 | 描述 |
|---|---|---|---|
| 跨服务器数据泄露 | TF001 | Critical | 敏感数据通过多个服务器传递后被不当暴露 |
| 破坏性攻击链 | TF002 | Critical | 多个工具组合执行导致不可逆的破坏性操作 |
资料来源:README.md:1
核心功能
攻击链检测机制
有毒数据流分析通过分析工具调用序列和数据传递路径来识别潜在威胁。当扫描器探测 MCP 服务器时,会收集所有可用工具的元数据,包括工具名称、描述和参数模式。然后通过图分析算法构建工具调用依赖图,检测是否存在恶意的数据传递链。
该模块的核心逻辑位于 lib/analyzers.mjs 中的 analyzeToxicFlows 函数。该函数接收扫描到的服务器列表和工具信息,返回检测到的有毒数据流列表。
扫描结果数据结构
扫描完成后,有毒数据流结果通过 results.toxicFlows 属性暴露:
import { scan } from 'decoy-scan';
const results = await scan();
console.log(results.toxicFlows);
// 输出格式:
// [{ id: "TF001", severity: "critical", roles: {...} }]
每个有毒数据流包含以下字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | string | 攻击链标识符(如 TF001、TF002) |
| severity | string | 严重级别(critical/high/medium/low) |
| roles | object | 涉及的角色和权限信息 |
资料来源:AGENTS.md:1
工作流程
graph TD
A[扫描 MCP 配置] --> B[探测服务器工具列表]
B --> C[收集工具元数据]
C --> D[构建工具依赖图]
D --> E{分析数据传递路径}
E -->|检测到 TF001| F[跨服务器数据泄露]
E -->|检测到 TF002| G[破坏性攻击链]
E -->|未检测到威胁| H[扫描通过]
F --> I[生成安全报告]
G --> I
H --> I策略控制
decoy-scan 提供了细粒度的策略控制机制,允许用户在 CI/CD 环境中根据安全需求配置扫描行为。
策略规则
通过 --policy 参数可以配置以下与有毒数据流相关的策略:
no-toxic-flows Fail on cross-server data leak / destructive chains
资料来源:README.md:1
退出码机制
有毒数据流检测结果直接影响扫描器的退出码:
| 退出码 | 含义 |
|---|---|
| 0 | 无 critical 或 high 级别问题 |
| 1 | 发现 high 级别风险问题 |
| 2 | 发现 critical 级别问题、工具投毒或有毒数据流 |
资料来源:AGENTS.md:1
集成使用
作为库函数导入
decoy-scan 提供了模块化接口,可以直接导入 analyzeToxicFlows 函数用于自定义分析场景:
import {
scan,
analyzeToxicFlows,
} from 'decoy-scan';
// 执行完整扫描
const results = await scan();
// 仅执行有毒数据流分析
const toxicFlows = analyzeToxicFlows(results.servers);
console.log(toxicFlows);
完整扫描配置
使用 scan() 函数时,可以通过选项对象配置扫描行为:
const results = await scan({
skills: true, // 包含技能扫描
advisories: true, // 包含供应链告警
verbose: false, // 显示所有工具
noProbe: false // 跳过服务器探测
});
扫描结果对象包含完整的分析数据:
{
servers: [...], // 服务器列表及工具信息
toxicFlows: [...], // 有毒数据流分析结果
skills: [...], // 技能分析结果
summary: {
total: 2,
critical: 1,
high: 2,
medium: 4,
low: 5,
poisoned: 0,
status: "fail",
exitCode: 2
}
}
资料来源:AGENTS.md:1
GitHub Action 集成
在 CI/CD 流程中使用 decoy-scan 时,可以通过 GitHub Action 启用有毒数据流检测:
name: MCP Security
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- uses: actions/checkout@v4
- uses: decoy-run/decoy-scan@v1
with:
policy: no-critical,no-poisoning,no-toxic-flows
sarif: true
Action 输入参数
| 参数 | 默认值 | 说明 |
|---|---|---|
| policy | no-critical,no-poisoning | 策略规则列表 |
| sarif | true | 上传 SARIF 到 GitHub Security |
| report | false | 上传到 Decoy Guard 仪表板 |
| token | — | Decoy API 令牌(用于 report) |
| verbose | false | 显示所有工具包括低风险 |
资料来源:README.md:1
威胁场景示例
TF001:跨服务器数据泄露
当一个服务器拥有读取敏感文件的能力,而该数据随后被传递给另一个具有网络访问权限的服务器时,就会形成数据泄露攻击链。decoy-scan 会检测这种跨服务器的敏感数据传递模式。
TF002:破坏性攻击链
当多个工具按特定顺序组合使用时,可能导致文件系统破坏或数据不可逆损失。例如,读取配置 → 修改权限 → 删除文件的连续操作可能被识别为破坏性攻击链。
输出格式
JSON 结构
{
"timestamp": "ISO-8601",
"hosts": ["Claude Desktop", "Cursor"],
"servers": [...],
"summary": {
"total": 2,
"critical": 1,
"high": 2,
"medium": 4,
"low": 5,
"poisoned": 0,
"toxicFlows": 1,
"status": "fail",
"exitCode": 2
}
}
Brief 输出
对于简化的概要输出:
{
"servers": 3,
"critical": 1,
"high": 2,
"medium": 4,
"low": 5,
"poisoned": 0,
"toxicFlows": 1,
"status": "fail",
"exitCode": 2
}
资料来源:AGENTS.md:1
版本历史
有毒数据流分析功能在以下版本中逐步完善:
| 版本 | 更新内容 |
|---|---|
| 0.2.0 | 引入有毒数据流分析模块 |
| 0.5.0 | 增强分析精度,修复边界情况 |
| 0.5.8 | 优化性能,减少误报 |
资料来源:CHANGELOG.md:1
相关模块
有毒数据流分析与其他安全检测模块协同工作:
| 模块 | 功能 |
|---|---|
| 工具风险分类 | 评估单个工具的风险级别 |
| 工具投毒检测 | 检测工具描述中的提示注入 |
| 服务器命令分析 | 检查服务器启动命令的安全性 |
| 环境变量暴露检测 | 识别敏感凭证的泄露风险 |
所有模块的检测结果统一汇总到 scan() 函数的返回结果中,形成完整的安全态势报告。
资料来源:[README.md:1]()
GitHub Action 集成
decoy-scan 提供官方的 GitHub Action,用于在 CI/CD 流水线中自动化扫描 MCP 配置。该 Action 无需安装依赖,一行配置即可将 MCP 安全扫描集成到现有的 GitHub 工作流中,支持策略强制执行和 SARIF 结果上传功能。资料来源:[README.md:52-60]()
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
decoy-scan 提供官方的 GitHub Action,用于在 CI/CD 流水线中自动化扫描 MCP 配置。该 Action 无需安装依赖,一行配置即可将 MCP 安全扫描集成到现有的 GitHub 工作流中,支持策略强制执行和 SARIF 结果上传功能。资料来源:README.md:52-60
核心功能
| 功能 | 说明 |
|---|---|
| 自动发现 | 扫描仓库中的 MCP 配置文件 |
| 策略强制 | 根据规则失败构建 |
| SARIF 上传 | 将结果上传至 GitHub Security Tab |
| 多主机支持 | 支持 Claude Desktop、Cursor、Windsurf、VS Code、Claude Code、Zed、Cline |
工作原理
graph TD
A[触发工作流] --> B[检出代码]
B --> C[运行 decoy-scan]
C --> D{扫描结果}
D -->|通过| E[✅ 成功]
D -->|有风险| F[🚨 失败 + 上传 SARIF]
D -->|仅 SARIF| G[上传 SARIF]
F --> H[GitHub Security Tab]
G --> H使用方式
基础配置
在 .github/workflows/mcp-security.yml 中添加以下内容:
name: MCP Security
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- uses: actions/checkout@v4
- uses: decoy-run/decoy-scan@v1
资料来源:README.md:52-66
完整配置示例
name: MCP Security
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- uses: actions/checkout@v4
- uses: decoy-run/decoy-scan@v1
with:
policy: no-critical,no-poisoning,no-toxic-flows
sarif: true
report: true
token: ${{ secrets.DECOY_TOKEN }}
verbose: false
输入参数
| 参数 | 默认值 | 必填 | 说明 |
|---|---|---|---|
policy | no-critical,no-poisoning | 否 | 逗号分隔的策略规则 |
sarif | true | 否 | 上传 SARIF 到 GitHub Security Tab |
report | false | 否 | 上传到 Decoy Guard 仪表板 |
token | — | 条件 | Decoy API 令牌(仅 report: true 时需要) |
verbose | false | 否 | 显示所有工具包括低风险项 |
资料来源:README.md:68-76
策略规则
| 规则 | 说明 |
|---|---|
no-critical | 遇到关键工具(代码执行、文件写入)时失败 |
no-high | 遇到高风险工具(文件读取、网络请求)时失败 |
no-poisoning | 检测到提示词注入时失败 |
no-toxic-flows | 检测到跨服务器数据泄露或破坏性链时失败 |
no-secrets | 检测到 MCP 配置中暴露的密钥时失败 |
require-tripwires | decoy-tripwire 未安装时失败 |
max-critical=N | 关键工具数量超过阈值时失败 |
输出变量
Action 执行后生成以下输出供后续步骤使用:
| 输出 | 说明 |
|---|---|
exit-code | 扫描退出码(0=通过, 1=高风险, 2=严重/投毒) |
sarif-file | 生成的 SARIF 文件路径 |
summary | 扫描摘要信息 |
steps:
- id: scan
uses: decoy-run/decoy-scan@v1
- name: 使用结果
run: |
echo "Exit code: ${{ steps.scan.outputs.exit-code }}"
echo "Summary: ${{ steps.scan.outputs.summary }}"
资料来源:action.yml:55-60
SARIF 集成
启用 sarif: true 后,Action 会自动:
- 生成 SARIF 2.1.0 格式的扫描报告
- 上传到 GitHub Security Tab
- 在 Pull Request 中显示安全警告
- name: Upload SARIF to GitHub Security
if: always() && inputs.sarif == 'true' && steps.scan.outputs.sarif-file != ''
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: ${{ steps.scan.outputs.sarif-file }}
category: decoy-scan
continue-on-error: true
资料来源:action.yml:68-76
工作流状态处理
graph TD
A[decoy-scan 执行] --> B{退出码}
B -->|0| C[✅ Clean - 无问题]
B -->|1| D[⚠️ Warnings - 高风险问题]
B -->|2| E[🚨 Failed - 严重/投毒]
C --> F[写入 GITHUB_STEP_SUMMARY]
D --> F
E --> F
F --> G[Exit 1 失败构建]Action 使用 set +e 捕获退出码,不会立即失败 step,确保 SARIF 上传和摘要写入在所有情况下都能执行。资料来源:action.yml:38-50
GitHub Step Summary
Action 会在 GitHub Actions 运行日志中生成摘要:
## Decoy Scan
✅ **Clean** — no issues found
或
## Decoy Scan
🚨 **Issues found** — N servers scanned, N critical, N high
Run `npx decoy-scan -v` locally for full details.
版本管理
| 版本 | 说明 |
|---|---|
@v1 | 主版本,稳定接口 |
@latest | 始终指向最新发布 |
@0.x.x | 指定具体版本 |
建议使用 @v1 以接收 bug 修复和安全更新,同时保持接口稳定性。
与 decoy-scan CLI 的对比
| 特性 | GitHub Action | CLI |
|---|---|---|
| 部署方式 | GitHub 市场 | npx |
| SARIF 上传 | 内置 | 需手动配置 |
| 策略强制 | 通过 policy 参数 | 通过 --policy 参数 |
| CI 集成 | 原生 | 需编写 YAML |
| 密钥管理 | GitHub Secrets | 环境变量 |
故障排除
SARIF 未上传
确保 permissions: security-events: write 已配置:
permissions:
security-events: write
构建未失败但有安全问题
检查 policy 参数是否包含所需的规则:
with:
policy: no-critical,no-poisoning
令牌相关错误
验证 Decoy API 令牌格式正确且未过期:
with:
token: ${{ secrets.DECOY_TOKEN }}
相关文档
资料来源:[README.md:52-66]()
失败模式与踩坑日记
保留 Doramagic 在发现、验证和编译中沉淀的项目专属风险,不把社区讨论只当作装饰信息。
假设不成立时,用户拿不到承诺的能力。
新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
下游已经要求复核,不能在页面中弱化。
用户安装前需要知道权限边界和敏感操作。
Pitfall Log / 踩坑日志
项目:decoy-run/decoy-scan
摘要:发现 7 个潜在踩坑项,其中 0 个为 high/blocking;最高优先级:能力坑 - 能力判断依赖假设。
1. 能力坑 · 能力判断依赖假设
- 严重度:medium
- 证据强度:source_linked
- 发现:README/documentation is current enough for a first validation pass.
- 对用户的影响:假设不成立时,用户拿不到承诺的能力。
- 建议检查:将假设转成下游验证清单。
- 防护动作:假设必须转成验证项;没有验证结果前不能写成事实。
- 证据:capability.assumptions | github_repo:1185640470 | https://github.com/decoy-run/decoy-scan | README/documentation is current enough for a first validation pass.
2. 维护坑 · 维护活跃度未知
- 严重度:medium
- 证据强度:source_linked
- 发现:未记录 last_activity_observed。
- 对用户的影响:新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
- 建议检查:补 GitHub 最近 commit、release、issue/PR 响应信号。
- 防护动作:维护活跃度未知时,推荐强度不能标为高信任。
- 证据:evidence.maintainer_signals | github_repo:1185640470 | https://github.com/decoy-run/decoy-scan | last_activity_observed missing
3. 安全/权限坑 · 下游验证发现风险项
- 严重度:medium
- 证据强度:source_linked
- 发现:no_demo
- 对用户的影响:下游已经要求复核,不能在页面中弱化。
- 建议检查:进入安全/权限治理复核队列。
- 防护动作:下游风险存在时必须保持 review/recommendation 降级。
- 证据:downstream_validation.risk_items | github_repo:1185640470 | https://github.com/decoy-run/decoy-scan | no_demo; severity=medium
4. 安全/权限坑 · 存在安全注意事项
- 严重度:medium
- 证据强度:source_linked
- 发现:No sandbox install has been executed yet; downstream must verify before user use.
- 对用户的影响:用户安装前需要知道权限边界和敏感操作。
- 建议检查:转成明确权限清单和安全审查提示。
- 防护动作:安全注意事项必须面向用户前置展示。
- 证据:risks.safety_notes | github_repo:1185640470 | https://github.com/decoy-run/decoy-scan | No sandbox install has been executed yet; downstream must verify before user use.
5. 安全/权限坑 · 存在评分风险
- 严重度:medium
- 证据强度:source_linked
- 发现:no_demo
- 对用户的影响:风险会影响是否适合普通用户安装。
- 建议检查:把风险写入边界卡,并确认是否需要人工复核。
- 防护动作:评分风险必须进入边界卡,不能只作为内部分数。
- 证据:risks.scoring_risks | github_repo:1185640470 | https://github.com/decoy-run/decoy-scan | no_demo; severity=medium
6. 维护坑 · issue/PR 响应质量未知
- 严重度:low
- 证据强度:source_linked
- 发现:issue_or_pr_quality=unknown。
- 对用户的影响:用户无法判断遇到问题后是否有人维护。
- 建议检查:抽样最近 issue/PR,判断是否长期无人处理。
- 防护动作:issue/PR 响应未知时,必须提示维护风险。
- 证据:evidence.maintainer_signals | github_repo:1185640470 | https://github.com/decoy-run/decoy-scan | issue_or_pr_quality=unknown
7. 维护坑 · 发布节奏不明确
- 严重度:low
- 证据强度:source_linked
- 发现:release_recency=unknown。
- 对用户的影响:安装命令和文档可能落后于代码,用户踩坑概率升高。
- 建议检查:确认最近 release/tag 和 README 安装命令是否一致。
- 防护动作:发布节奏未知或过期时,安装说明必须标注可能漂移。
- 证据:evidence.maintainer_signals | github_repo:1185640470 | https://github.com/decoy-run/decoy-scan | release_recency=unknown
来源:Doramagic 发现、验证与编译记录