CobaltoSec/corvus

GitHub: CobaltoSec/corvus

Corvus 是一款针对 MCP 服务器的安全测试框架,通过静态分析与动态探测覆盖 OWASP MCP Top 10 漏洞,帮助开发者在接入 LLM 工具链前发现并修复安全风险。

Stars: 1 | Forks: 0

# Corvus [![PyPI](https://img.shields.io/pypi/v/cobaltosec-corvus)](https://pypi.org/project/cobaltosec-corvus/) [![测试](https://static.pigsec.cn/wp-content/uploads/repos/cas/39/39faa54be350a1dab8afd3b2fb8c1c83e4d9cff84abfef2374d19a18053687c4.svg)](https://github.com/CobaltoSec/corvus/actions) [![Python](https://img.shields.io/pypi/pyversions/cobaltosec-corvus)](https://pypi.org/project/cobaltosec-corvus/) MCP server 安全测试框架。针对 MCP server 进行 [OWASP MCP Top 10](https://owasp.org/www-project-top-10-for-large-language-model-applications/) 测试 —— 包含静态分析和实时动态探测。 ``` Corvus v1.3.1 MCP Security Scanner Target : python my_mcp_server.py Transport : stdio Modules : tool-poisoning, scope-audit, shadow-tool, supply-chain, osv-supply-chain, github-advisory, npm-behavior, supply-chain-python, auth-audit, log-audit, schema-audit, resource-uri, tool-chaining, cmd-injection, token-exposure, ssrf, endpoint-probe, param-smuggling, schema-bypass, proto-fuzz, batch-dos, output-encoding, response-flood, response-injection, rug-pull, init-audit, oauth-bypass, sampling-probe, elicitation-probe, completion-probe, logging-probe, prompts-injection, cursor-probe, cancellation-probe Enumerating surface... Tools : 12 Resources : 3 Prompts : 2 Server : my-server 1.0.0 [MCP03] Tool Poisoning (static) [HIGH] Potential prompt injection in description of 'execute_code' [MCP05] Command Injection (dynamic) [HIGH] Command injection confirmed in tool 'run_shell', param 'command' [MEDIUM] Path traversal accepted in tool 'read_file', param 'path' ... ─── Summary ────────────────────────────────────────────────────────────────── CRITICAL 0 HIGH 2 MEDIUM 1 LOW 3 INFO 4 Risk Score: 56 / 100 (HIGH) Session : corvus-sessions/20260608-143022/ ``` ## 安装 ``` pip install cobaltosec-corvus ``` 或从源码安装: ``` git clone https://github.com/CobaltoSec/corvus cd corvus pip install -e ".[dev]" ``` ## 快速开始 ``` # 立即尝试 — 使用单个命令扫描真实的 MCP server(需要 Node.js): pip install cobaltosec-corvus corvus scan "npx -y @modelcontextprotocol/server-filesystem /tmp" ``` ``` # 扫描 stdio MCP server corvus scan --transport stdio --cmd "python my_server.py" # 扫描 HTTP MCP server corvus scan --transport http --url http://localhost:8080 # 带有 authentication header corvus scan --transport http --url http://localhost:8080 --header "Authorization: Bearer token" # 仅静态分析(无 live tool calls) corvus scan --transport stdio --cmd "python my_server.py" --module static # 特定 module corvus scan --transport stdio --cmd "python my_server.py" --module cmd-injection # SARIF 输出(用于 CI/CD 集成) corvus scan --transport stdio --cmd "python my_server.py" --sarif # 在发现的问题超过阈值时使 CI 失败 corvus scan --transport stdio --cmd "python my_server.py" --fail-on high # 从文件加载 config corvus scan --config corvus.toml # 过滤低置信度的发现(0-100) corvus scan --transport stdio --cmd "python my_server.py" --min-confidence 70 # 捕获原始 JSON-RPC 交换 corvus scan --transport stdio --cmd "python my_server.py" --log-requests # Rate-limit 探测(请求之间的毫秒数) corvus scan --transport stdio --cmd "python my_server.py" --delay 500 # 将环境变量传递给 server 进程 corvus scan --transport stdio --cmd "python my_server.py" --env API_KEY=secret --env DEBUG=1 # 在结束时打印 Risk Score corvus scan --transport stdio --cmd "python my_server.py" --score # 列出可用的 modules corvus list-modules ``` ## 批量扫描 在一次调用中扫描多个 MCP server: ``` # targets.yaml targets: - name: filesystem transport: stdio cmd: ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/tmp"] - name: my-http-server transport: http url: http://localhost:8080 ``` ``` corvus batch targets.yaml --output-dir results/ --sarif --min-confidence 70 ``` 生成针对每个目标的 `report.json` 以及一个顶层的 `summary.md` 表格。 ## 模块 34 个内置模块,涵盖完整的 OWASP MCP Top 10 以及协议、诱导、采样、OAuth 和供应链扩展: ### 静态模块(无实时工具调用) | 名称 | OWASP | 测试内容 | |------|-------|---------------| | `tool-poisoning` | MCP03 | 工具描述中的隐藏指令、混淆和提示词注入模式 | | `shadow-tool` | EXT03 | 指示危险操作的工具名称 —— 命名空间抢注、隐蔽链式调用、信任劫持 | | `scope-audit` | MCP02 | 工具 inputSchema 中的凭据和 PII 字段 —— 请求密码、token 或 SSN 的工具 | | `supply-chain` | MCP04 | 从 server 命令提取的已知易受攻击的 npm 包 (npm audit) | | `supply-chain-python` | MCP04 | 从 server 环境提取的已知易受攻击的 Python 包 (pip list) | | `osv-supply-chain` | MCP04 | 查询 OSV.dev API 以获取检测到的依赖项中的已知漏洞 | | `github-advisory` | MCP04 | 查询 GitHub Security Advisories 以获取检测到的包中的已知漏洞 | | `npm-behavior` | MCP04 | 查询 npm registry 以获取检测到的包中可疑的安装脚本 (postinstall, preinstall) | | `auth-audit` | MCP07 | 暗示缺少、可选或可绕过身份验证的工具名称和描述 | | `log-audit` | MCP08 | 暴露或篡改审计日志的工具 —— 反取证技术或运营数据泄露 | | `schema-audit` | EXT02 | 扩大攻击面的弱 schema 定义(缺少必填字段、不受约束的类型) | | `resource-uri` | EXT05 | 对 resources/list URI 的静态分析 —— 检测敏感 scheme(file://, env://, exec://) | | `tool-chaining` | EXT03 | 检测隐蔽链式调用额外工具调用或绕过用户确认的工具描述 | ### 动态模块(实时工具调用) | 名称 | OWASP | 测试内容 | |------|-------|---------------| | `cmd-injection` | MCP05 | 针对每个参数的命令、路径、SQL 和提示词注入 payload —— schema 感知,需确认 | | `token-exposure` | MCP01 | 工具响应中泄露的凭据、文件系统路径、堆栈跟踪和 token | | `ssrf` | EXT04 | 通过 URL/host 参数进行 SSRF —— 探测内部元数据 endpoint,测量时间异常 | | `endpoint-probe` | MCP01 | 通过 resources/read 和 prompts/get 进行路径遍历、SSRF、模板注入和凭据暴露 | | `param-smuggling` | EXT01 | 隐藏参数后门 —— 追加未声明的参数并测量行为差异 | | `schema-bypass` | EXT01 | 工具是否正确拒绝违反其声明 schema 的输入 | | `proto-fuzz` | EXT01 | 协议级崩溃测试 —— 未知方法、超长方法名、空 request ID | | `batch-dos` | EXT01 | 发送 JSON-RPC 2.0 批量数组和超大 payload 以检测崩溃/DoS 条件 | | `output-encoding` | MCP10 | 工具输出中的不可见 Unicode —— 控制字符、零宽字符、双向重写 (bidi overrides) | | `response-flood` | MCP10 | 溢出 LLM 上下文窗口的过大或重复响应 | | `response-injection` | MCP10 | 检测良性工具响应中注入的内容(HTML/JS/markdown 指令) | | `rug-pull` | MCP06 | 动态测试后重新枚举 server;通过 diff 检测会话中途添加、删除或变异的工具 | | `init-audit` | MCP07 | 审计 initialize 握手 —— serverInfo 注入字符、协议版本降级接受 | | `oauth-bypass` | MCP07 | 测试 HTTP 传输 endpoint 的身份验证绕过:缺少身份验证、无效 Bearer、URL 内嵌凭据 | | `sampling-probe` | EXT08 | 检测恶意 MCP sampling/createMessage —— 提示词注入、上下文泄露、未经请求的调用 | | `elicitation-probe` | EXT09 | 检测 MCP elicitation/create 滥用 —— 凭据钓鱼、敏感数据 schema | | `completion-probe` | EXT10 | 通过参数上下文探测 MCP completion/complete endpoint 的提示词注入 | | `logging-probe` | EXT11 | 测试 server 是否允许未经身份验证的外部日志级别操作 | | `prompts-injection` | EXT12 | 通过 MCP prompts/get 检测提示词注入 —— 静态模式 + 实时参数注入 | | `cursor-probe` | EXT13 | 测试 MCP 分页游标处理是否存在路径遍历、超大值和注入 | | `cancellation-probe` | EXT14 | 测试 MCP notifications/cancelled 处理是否存在竞争条件以及因未知 requestId 导致的崩溃 | ### 模块组 ``` # 所有 modules(默认) --module all # 仅静态(不对 server 进行 live calls) --module static # 仅动态 --module dynamic # 单个 module --module cmd-injection ``` ## 传输方式 ### stdio 生成 server 进程并通过 stdin/stdout 进行通信。支持任何命令: ``` corvus scan --transport stdio --cmd "python server.py" corvus scan --transport stdio --cmd "npx @modelcontextprotocol/server-filesystem /tmp" corvus scan --transport stdio --cmd "uvx my-mcp-server --arg value" ``` ### HTTP 连接到正在运行的 HTTP/SSE MCP server: ``` corvus scan --transport http --url http://localhost:8080 # 带有 auth corvus scan --transport http --url http://localhost:8080 --header "Authorization: Bearer $TOKEN" corvus scan --transport http --url http://localhost:8080 --header "X-API-Key: secret" ``` ## 配置文件 创建 `corvus.toml` 以避免重复使用 CLI 标志: ``` [scan] transport = "stdio" cmd = "python my_server.py" modules = "all" timeout = 30 sarif = false fail_on = "high" [scan.headers] "Authorization" = "Bearer my-token" ``` 然后运行: ``` corvus scan --config corvus.toml ``` CLI 标志会覆盖配置文件中的值。`--config` 标志也支持绝对路径。 ## CLI 参考 ``` Usage: corvus scan [OPTIONS] Scan an MCP server for security vulnerabilities. Options: -t, --transport TEXT stdio | http (overrides config) --cmd TEXT Command to launch MCP server (stdio) --url TEXT URL of MCP server (http) -m, --module TEXT all | static | dynamic | (overrides config) -o, --output-dir PATH --fail-on TEXT Exit 1 if findings at this severity or above (critical|high|medium|low) --timeout INTEGER Request timeout in seconds (overrides config) --sarif Also write SARIF 2.1.0 report --header TEXT HTTP header "Key: Value" (repeatable, for http transport) -c, --config PATH Path to corvus.toml config file --plugin-dir TEXT Directory to load external modules from (repeatable) --help Show this message and exit. ``` 其他命令: ``` corvus list-modules # list available modules with OWASP ID and type corvus list-modules --plugin-dir ./plugins/ # include external plugins corvus version # print version corvus init # generate a corvus.toml skeleton in the current directory corvus report REPORT.json # regenerate MD/SARIF/HTML from an existing report.json corvus diff OLD.sarif NEW.sarif # compare two SARIF files: new / fixed / unchanged findings corvus score REPORT.json # print Risk Score (0-100) for a report ``` ## 输出 每次扫描都会在 `corvus-sessions//` 下创建一个会话目录: ``` corvus-sessions/20260608-143022/ ├── report.json # full structured result ├── report.md # human-readable with remediation guidance └── report.sarif # SARIF 2.1.0 (only when --sarif is passed) ``` ### SARIF 集成 SARIF 输出兼容 GitHub Advanced Security、VS Code SARIF Viewer 以及任何使用 SARIF 的 CI pipeline: ``` # GitHub Actions 示例 - name: Run Corvus run: corvus scan --transport stdio --cmd "python server.py" --sarif --fail-on high - name: Upload SARIF uses: github/codeql-action/upload-sarif@v3 with: sarif_file: corvus-sessions/ ``` ## CI 集成 ``` # 如果有任何 CRITICAL 发现则 Exit 1 corvus scan --transport stdio --cmd "python server.py" --fail-on critical # 如果有任何 HIGH 或以上发现则 Exit 1 corvus scan --transport stdio --cmd "python server.py" --fail-on high ``` 严重性级别(由低到高):`info` → `low` → `medium` → `high` → `critical` ## 插件系统 添加自定义模块而无需修改 Corvus 源码。 ### 基于目录的插件 ``` corvus scan --transport stdio --cmd "python server.py" --plugin-dir ./my-modules/ ``` 目录中的每个 `.py` 文件都会作为模块被加载。该文件必须定义一个继承自 `BaseModule` 的类: ``` from corvus.modules.base import BaseModule, Finding, Severity class MyCustomModule(BaseModule): name = "my-check" owasp_id = "MCP-CUSTOM" module_type = "static" description = "Custom check for my organization" async def run(self, surface, transport): findings = [] for tool in surface.tools: if "dangerous_pattern" in tool.description: findings.append(Finding( rule_id="MY001", tool_name=tool.name, severity=Severity.HIGH, title="Dangerous pattern detected", description=f"Tool '{tool.name}' contains a dangerous pattern.", remediation="Remove or sanitize the pattern.", )) return findings ``` ### 基于包的插件 通过 `pyproject.toml` 的 entry points 注册: ``` [project.entry-points."corvus.modules"] my-check = "my_package.modules.my_check:MyCustomModule" ``` 在 `pip install my-package` 之后,Corvus 会自动发现该模块。 ## 研究:MCP 生态系统安全审计 Corvus 已在真实的 MCP 生态系统中通过 17 个案例研究进行了实战测试 —— 审计了 397 个 server,涵盖官方的 `@modelcontextprotocol` 包、社区 server 以及更广泛的 npm 和 PyPI 生态系统。 | 指标 | 总计(17 个案例研究) | |--------|-------------------------------| | 审计的 server 数量 | **397** | | 原始发现 | **~5566** | | 真阳性 | **~1325** | 来自真实环境的关键发现: - **100% 被测试的 MCP server 在遇到带有未知 requestId 的 37 字节 notifications/cancelled payload 时发生崩溃 (EXT14) —— 零身份验证即可实现的普遍 DoS** - **37% 的 server 在遇到符合规范的 JSON-RPC 批量数组或超大的方法名时崩溃 —— 无需身份验证即可复现的 DoS** - **71% 的 server 在 initialize 握手期间接受任意的 protocolVersion 字符串 —— 接受协议降级** - **3 个 server (myclaw-toolkit, @sap-ux/fiori-mcp-server, markitdown-mcp) 确认存在 SSRF —— 可从工具参数访问内部元数据 endpoint** - **供应链级联:@modelcontextprotocol/sdk ≤1.25.1 安全公告影响生态系统中的大多数基于 JS 的 server** - **通过 5 次校准迭代,误报率从 ~40% (v0.5.0,早期校准) 降至 ~7% (CS03,v1.0.1)** - **CS04 引入了 3 种新的系统性误报模式:docs server 懒加载 (MCP06,来自 sveltejs 的 195 个误报),Python strptime 错误反射 (MCP05,33 个误报),以及第三方 API 错误消息回显 (MCP05,11 个 server 中 62+ 个误报)** - **发现新的攻击模式:SaaS 描述变异 rug-pull —— mcp-devutils 在会话期间根据计费逻辑将 29 个工具描述从 '[PRO — trial]' 更改为 '[PRO — trial expired]'** - **通过 MCP 范围蔓延进行隐蔽 AI 代理监控:clarvia-mcp-server 指示代理“在每次工具调用后使用”以将所有活动报告给外部 server** - **带有时间证据的 SSRF:pulsemcp-pulse-fetch scrape.url 访问 169.254.169.254 AWS 元数据 endpoint(相比 2.3s 基线有 8.3s 的时间差)** - **存储型 SQL 注入模式:arxiv-mcp-server watch_topic.topic 将 SQL payload 存储在数据库中而未进行净化(极有可能,需要 check_alerts 验证)** - **反取证日志清除:godot-mcp-server 暴露了 clear_console_log 工具(严重,MCP08)—— 结合 save_resource_to_file/take_screenshot 中的写入路径遍历,构成了“泄露后掩盖踪迹”的攻击链** - **在各生态系统中确认了 XSS 响应注入模式:functype-mcp-server (npm) 和 awslabs.amazon-kendra-index-mcp-server (PyPI) 都在错误消息中原样反映了未经净化的 XSS payload —— 系统性的跨 SDK 问题** 完整的数据集、精选发现和方法论请见 [`case-studies/`](case-studies/)。 ### 负责任的披露 在 17 个案例研究中提交了 56 份安全公告 —— 7 份已发布,49 份正在进行积极的协调披露(90 天窗口期)。 **已发布:** | 公告 | 包 | 严重程度 | 发现 | |----------|---------|----------|---------| | [GHSA-43j9-hmpq-cgv7](https://github.com/advisories/GHSA-43j9-hmpq-cgv7) | remnux-mcp-server | MEDIUM | 在非本地环回部署上通过 HTTP 传输实现的未经身份验证的 RCE | | [GHSA-hv3x-m9fv-4vhf](https://github.com/advisories/GHSA-hv3x-m9fv-4vhf) | mcp-server-git | HIGH | 通过符合规范的 JSON-RPC 批量数组和超大方法名实现的 DoS | | [GHSA-3f55-qgq4-f88c](https://github.com/advisories/GHSA-3f55-qgq4-f88c) | server-sequential-thinking | MEDIUM | 通过超大 JSON-RPC 方法名实现的 DoS (CWE-755) | | [GHSA-jgxf-j67w-w284](https://github.com/advisories/GHSA-jgxf-j67w-w284) | campertunity-ai-tools | HIGH | 通过预订 API URL 参数实现的 SSRF —— 内部元数据 endpoint 可访问 | | [GHSA-prc4-649r-564g](https://github.com/advisories/GHSA-prc4-649r-564g) | localparse-mcp | HIGH | 在 parse_url 中确认存在 SSRF —— 时间和超时信号已确认 (CWE-918) | | [GHSA-32vx-mq6h-p8f3](https://github.com/advisories/GHSA-32vx-mq6h-p8f3) | emilia-protocol | HIGH | 通过 trust_decision/receipt_quality_check + 强制合规网关实现的提示词模板注入EXT03/EXT12) | | [GHSA-wx78-8jx3-wcv9](https://github.com/advisories/GHSA-wx78-8jx3-wcv9) | @tensorfeed/mcp-server | HIGH | 跨越 6 个工具的 XSS 反射集群 —— 原样回显未净化的 payload (MCP05) | **积极的协调披露(49 份公告):** 包含的包有 @playwright/mcp, mcp-server-sqlite, mcp-shell-server, myclaw-toolkit(严重), @sap-ux/fiori-mcp-server 及其他 —— 90 天禁发窗口期正在进行中。 完整公告索引:[`case-studies/DISCLOSURE-PROCESS.md`](case-studies/DISCLOSURE-PROCESS.md) ## 常见问题 **Corvus 与 mcp-scan / Snyk Agent Scan 相比如何?** [mcp-scan](https://github.com/invariantlabs-ai/mcp-scan)(于 2025 年被 Snyk 收购,现为 [Snyk Agent Scan](https://github.com/snyk/agent-scan))是部署最广泛的 MCP 安全工具,在提示词注入和工具投毒方面表现出色。如果这是您的主要关注点,两者都值得运行。 这些工具从不同角度处理 MCP 安全性: | | mcp-scan / Snyk Agent Scan | Corvus | |---|---|---| | **范围** | 提示词注入、工具投毒、有毒流、跨源提权 | 完整的 [OWASP MCP Top 10](https://owasp.org/www-project-top-10-for-large-language-model-applications/) —— 34 个模块 | | **视角** | 客户端:读取您的 MCP 配置文件 | 服务端:通过 stdio 或 HTTP 直接连接 | | **探测** | 静态分析 + 可选的代理监控 | 静态分析 + 实时动态探测(带 payload 的实际工具调用) | | **CI/CD** | 基础 | SARIF 输出,`--fail-on high`,批量扫描 | | **覆盖范围** | 专注于提示词注入 / 投毒 | 增加了命令注入、SSRF、身份验证绕过、供应链、schema 绕过、参数走私、DoS、OAuth、采样/诱导滥用 | | **实时** | ✅ 用于实时监控的代理模式 | ❌ 仅限单点时间扫描 | | **披露** | 无公开公告计划 | 已提交 50 份协调的 GHSA | | **支持** | Snyk(企业级) | 独立,专注于安全研究 | **何时使用 mcp-scan:** 您希望对代理流量进行实时代理监控,或者您需要 Snyk 企业级集成。 **何时使用 Corvus:** 您正在进行全面的安全审计,需要兼容 CI/CD 的输出,或者希望测试提示词注入之外的攻击面(命令注入、SSRF、身份验证绕过、供应链等)。 它们是互补的 —— mcp-scan 擅长运行时监控,Corvus 擅长单点时间的深度检测。 ## 开发 ``` git clone https://github.com/CobaltoSec/corvus cd corvus pip install -e ".[dev]" pytest ``` ## 许可证 MIT
标签:AI安全, Chat Copilot, CISA项目, LNA, MCP, Python, 云安全监控, 安全测试, 攻击性安全, 文档结构分析, 无后门, 无服务器架构, 逆向工具, 静态分析