MCP(Model Context Protocol)火了以后,各种MCP Server像雨后春笋一样冒出来。连接数据库的、操作文件系统的、调API的,什么都有。但有个问题大家都在忽略:这些Server的安全性谁来保证?
你给Claude、Cursor配了一堆MCP Server,等于给AI开了一扇直通你基础设施的门。数据库密码硬编码在代码里、eval()随便用、HTTP明文传输——这些问题在传统Web开发里早就被骂烂了,到了MCP生态又全部复活。
前两天在HN上看到一个开源工具mcp-security-auditor,专门扫描MCP Server的安全问题。拿来测了几个流行的MCP Server,结果挺触目惊心的。
工具安装
零安装,直接npx跑:
npx mcp-security-auditor scan ./your-mcp-server
也可以全局装:
npm install -g mcp-security-auditor mcp-audit scan ./your-mcp-server
它能检测7大类问题:硬编码密钥、危险函数调用、注入风险、权限配置、网络安全、配置问题、依赖风险。支持TypeScript、JavaScript和Python写的MCP Server。
实测:扫描几个真实MCP Server
测试1:postgres-mcp
postgres-mcp是一个让AI直接操作PostgreSQL的MCP Server,GitHub上星不少。克隆下来扫一下:
git clone https://github.com/crystaldba/postgres-mcp.git mcp-audit scan ./postgres-mcp
数据库相关的MCP Server天然就是高危目标。AI能执行SQL,意味着一个prompt injection就可能导致数据泄露。该工具会检查是否有SQL注入防护、是否限制了可执行的SQL类型、连接字符串是否硬编码。
测试2:filesystem MCP Server
Anthropic官方出的filesystem MCP Server,让Claude能读写本地文件。听起来就很刺激。
git clone https://github.com/modelcontextprotocol/servers.git mcp-audit scan ./servers/src/filesystem
重点关注:是否限制了可访问的目录范围、是否有路径遍历防护、写操作是否有确认机制。
测试3:自己写的MCP Server
为了测试工具的检出能力,我故意写了一个”有问题”的MCP Server:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
const API_KEY = "sk-proj-abc123def456"; // 硬编码密钥
const server = new McpServer({ name: "bad-example", version: "1.0.0" });
server.tool("run_query", { query: z.string() }, async ({ query }) => {
// 直接拼接SQL,经典注入
const result = eval(`db.query("${query}")`);
return { content: [{ type: "text", text: JSON.stringify(result) }] };
});
server.tool("exec_cmd", { cmd: z.string() }, async ({ cmd }) => {
const { execSync } = require("child_process");
// 直接执行用户传入的命令
const output = execSync(cmd).toString();
return { content: [{ type: "text", text: output }] };
});
扫描结果不出所料,红了一片:
- CRITICAL – 硬编码API密钥(
sk-proj-前缀被识别为OpenAI key) - CRITICAL –
eval()执行动态代码 - CRITICAL –
execSync直接执行外部命令 - HIGH – 字符串拼接构造查询(SQL注入风险)
- HIGH – 没有输入验证和sanitization
该工具对这些经典安全问题的检出率很高,基本上一个没漏。
MCP Server常见安全问题
扫了一圈下来,几个MCP生态里最普遍的安全问题:
1. 硬编码凭证
大量MCP Server的示例代码甚至正式代码里,数据库密码、API Key直接写在源码里。很多开发者把示例代码直接拿来用,改都不改。
正确做法:
// 错误
const API_KEY = "sk-xxxxx";
// 正确
const API_KEY = process.env.API_KEY;
if (!API_KEY) throw new Error("API_KEY environment variable required");
2. 缺乏输入验证
MCP的tool接收参数后直接使用,不做任何校验。AI传过来的参数可能被prompt injection污染,如果不验证就执行,等于把系统控制权交给了攻击者。
用zod做schema验证只是第一步,还需要对值本身做安全检查:
server.tool("query", { sql: z.string().max(1000) }, async ({ sql }) => {
// schema验证只管类型和长度
// 还需要检查是否包含危险操作
if (/DROP|DELETE|TRUNCATE|ALTER/i.test(sql)) {
throw new Error("Dangerous SQL operation blocked");
}
// 更好的方案:用参数化查询,彻底杜绝注入
});
3. 权限过大
文件系统类MCP Server默认允许访问整个磁盘,数据库类默认给的是root权限。最小权限原则在MCP生态里几乎不存在。
4. 没有传输加密
很多MCP Server用HTTP而不是HTTPS,stdio模式虽然不走网络,但SSE模式下明文传输等于裸奔。
CI/CD集成
安全扫描最大的价值是自动化。手动扫一次没用,要集成到CI里每次提交都扫。
GitHub Actions配置:
name: MCP Security Scan
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npx mcp-security-auditor ci . --fail-on high -o results.sarif
- uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: results.sarif
--fail-on high表示发现HIGH及以上级别的问题就让CI失败。SARIF格式可以直接对接GitHub的Security tab,在PR里显示安全告警。
也支持pre-commit hook,提交前就拦截:
#!/bin/sh # .git/hooks/pre-commit npx mcp-security-auditor ci . --fail-on critical
报告格式
除了终端输出,还支持HTML、JSON、SARIF、Markdown格式:
# HTML报告,可以发给团队看 mcp-audit scan ./server -f html -o report.html # JSON,方便程序处理 mcp-audit scan ./server -f json -o results.json # SARIF,对接GitHub/Azure DevOps mcp-audit scan ./server -f sarif -o results.sarif
HTML报告是暗色主题的,视觉上做得不错,分类清晰,每个问题都标注了文件位置和修复建议。
局限性
工具目前的局限也得说清楚:
- 静态分析为主:只分析源码,不会真正启动MCP Server做运行时检测。一些需要运行时才能发现的问题(比如权限提升、竞态条件)检测不到
- 误报存在:比如测试代码里的eval()也会报,注释里的密钥格式字符串也会报。需要人工过滤
- Python支持弱一些:对TypeScript/JavaScript的检测规则明显比Python多,Python的MCP Server扫描结果偏少
- 不检查MCP协议层面的问题:比如tool description是否会被利用做prompt injection,这类语义层面的安全问题不在检测范围内
该不该用
如果你在用MCP Server(不管是自己写的还是开源的),跑一次扫描基本上零成本。npx一行命令的事,能发现问题就赚了。
但别指望它能解决所有安全问题。MCP生态的安全挑战远不止代码层面——协议设计本身的信任模型、AI Agent的权限边界、prompt injection的防护,这些都是更深层的问题,不是一个静态扫描工具能搞定的。
MCP让AI能操作真实世界的基础设施,这是能力的飞跃,也是风险的飞跃。工具链跟不上能力的扩张,安全就是那个最容易被忽略的短板。