接入陌生 MCP Server 前,先做完这套安全体检

你以为自己只是给 AI 加了一个工具,操作系统看到的却是:你启动了一段能读文件、拿环境变量、还能联网的第三方代码。

一个标注为“文档整理”的 MCP Server,可能在启动后读取了与任务无关的 .env;一个声称只做本地搜索的工具,也可能遍历用户主目录,并向文档没有披露的域名发起请求。

日志里可能出现这样的记录:

OPEN    /workspace/normal-document.txt

OPEN /home/user/.env

OPEN /home/user/.ssh/config

CONNECT unknown-example.net:443

READ_ENV UNRELATED_SECRET

这并不意味着“MCP 都不安全”。真正的问题是:很多人把 MCP Server 当成浏览器插件安装,却没有按照第三方程序的标准检查它。

接入陌生 MCP Server,正确顺序应该是:

1. 先看来源

2. 再查权限

3. 最后受控运行

点下“连接”之前,你实际上授权了什么?

MCP 解决的是 AI 应用与外部工具之间如何通信,但它本身不是安全沙箱。

用户

↓ 授权

MCP Client

↓ 启动或连接

MCP Server

├── 本地文件

├── 环境变量与密钥

├── 系统命令

└── 外部网络

重点:MCP 协议负责通信,

不会自动替用户隔离操作系统权限。

如果 MCP Client 以你的日常账号启动本地 Server,那么这段第三方代码通常会在操作系统允许的范围内运行。你的账号能读取哪些目录、拥有多少环境变量、能否执行命令和访问网络,Server 就可能获得相应能力。

本地与远程 MCP Server 的风险重点也不完全相同:

  • 本地 Server: 重点检查文件、环境变量、系统命令和子进程权限。
  • 远程 Server: 重点检查上传了什么数据、如何认证、数据由谁保存,以及服务端是否可信。

不要只问“它是不是 MCP”,而要问:

它作为一个进程运行时,究竟拥有什么权限?

第一轮静态体检:先别运行,查清来源和代码

静态检查的价值,是在代码尚未获得本机权限前,先排除最明显的问题。

先查项目从哪里来

至少检查以下信息:

  • 仓库是否来自项目文档公布的官方地址
  • 维护者身份和包发布账号是否一致
  • 提交记录是否连续,还是突然出现大量替换代码
  • 是否有明确的版本、Release 和变更说明
  • 是否提交依赖锁文件,如 package-lock.jsonpnpm-lock.yamluv.lock
  • 安装脚本是否会下载额外文件
  • 实际发布包是否与仓库源码一致
开源只代表代码理论上可见,不代表代码已经被审计。

尤其需要注意“仓库里看起来干净,发布包里却多出文件”的情况。对于 npm 包,可以先下载而不安装:

npm pack package-name@fixed-version

tar -tf package-name-fixed-version.tgz

对于 Python 包,也可以先下载到独立目录:

pip download package-name==fixed-version --no-deps

检查完成前,不要直接运行来历不明的“一键安装脚本”。

看不懂源码,也能搜索这些关键词

| 风险类型 | 建议搜索的关键词 | | 环境变量 | process.envos.environgetenv | | 文件读取 | readFileopen(read_textreaddir | | 敏感目录 | .ssh.aws.config.npmrc.env | | 外部请求 | fetchaxiosrequestshttpxurllib | | 命令执行 | child_processexecspawnsubprocess | | 安装脚本 | postinstallprepare、远程下载脚本 |

可以在项目目录内执行:

grep -RInE \

'process\.env|os\.environ|getenv|readFile|read_text|readdir|\.ssh|\.aws|\.npmrc|fetch|axios|requests|httpx|child_process|subprocess|postinstall' .

但要注意:关键词命中只是调查线索,不能单独证明恶意。

例如 GitHub MCP 读取专用 GitHub Token,属于功能所需;文件搜索工具出现 readFile 也很正常。真正要判断的是:它读取什么、在什么时候读取,以及是否超出了功能需要。

进阶用户还应继续检查:

  • package.json 中的 scripts
  • Python 构建配置与安装钩子
  • 是否动态下载二进制文件
  • 是否存在难以解释的混淆代码
  • 是否通过 eval 或动态导入执行远程内容
  • 依赖是否固定到具体版本

三项动态体检:文件、网络和密钥

静态检查只能说明“代码可能做什么”。动态检查要回答的是:它实际上做了什么。

首先建立一个完全不含真实数据的测试目录:

mcp-test-data/

├── normal-document.txt

├── private-note-canary.txt

└── subfolder/

└── unrelated-secret.txt

再准备两个假环境变量:

export TEST_API_KEY="canary_mcp_audit_123456"

export UNRELATED_SECRET="should_never_be_read"

全程禁止使用生产数据库密码、真实云服务凭证、SSH 私钥或正式模型 API Key。

第一项:它打开了哪些文件?

给 Server 一个明确任务,例如:“搜索 normal-document.txt 中包含 MCP 的段落”。

随后观察它是否:

  • 只打开任务指定文件
  • 顺带扫描了同目录其他文件
  • 递归遍历所有子目录
  • 尝试访问测试目录之外的位置
  • 读取 .env.ssh.aws 等敏感目录

Linux 可以记录文件访问:

strace -f -e trace=file -o file-audit.log \

your-mcp-server-command

macOS 可以使用:

sudo fs_usage -w -f filesystem | grep -i mcp

Windows 可使用 Process Monitor,按进程名过滤 CreateFileReadFile 等事件。

截图1:进程文件访问记录
09:31:02 OPEN /workspace/normal-document.txt

09:31:02 OPEN /workspace/private-note-canary.txt

09:31:03 OPEN /workspace/subfolder/unrelated-secret.txt

如果任务只要求读取第一个文件,后两条记录就值得继续调查。

第二项:它连接了哪里?

记录以下信息:

  • 目标域名和 IP
  • 端口及协议
  • 请求发生时间
  • 是否与用户操作对应
  • 请求正文中包含哪些数据

Linux 可结合使用:

lsof -i -n -P

ss -tpn

需要检查请求内容时,可以在合法、可控的测试环境中配置 mitmproxy 或测试代理。对于 HTTPS,请避免在生产设备上随意安装代理证书。

截图2:网络连接记录
TIME      PROCESS       TARGET                  PORT

09:35:11 demo-mcp api.expected.test 443

09:35:14 demo-mcp unknown-example.net 443

访问网络不一定有问题。天气查询、代码托管或网页读取类 MCP 本来就需要联网。风险在于:目标是否合理、是否提前披露、发送的数据是否超出任务范围。

第三项:它有没有碰不该碰的密钥?

让测试环境只包含假 Key,再检查:

  • Server 是否读取 TEST_API_KEY
  • 是否同时枚举其他环境变量
  • UNRELATED_SECRET 是否出现在日志中
  • 假 Key 是否进入请求头、请求正文或错误上报
  • 调试日志是否明文打印凭证
截图3:假密钥追踪结果
READ_ENV TEST_API_KEY

READ_ENV UNRELATED_SECRET

POST unknown-example.net/report

BODY {"token":"should_never_be_read"}

如果某个 GitHub 工具读取专用 GitHub Token,行为可以解释;如果一个本地文件搜索工具读取 UNRELATED_SECRET,甚至将其发送出去,就是明显的高风险信号。

做一次可复现的沙箱接入实验

最简单的隔离思路,是先断网、只读挂载测试目录,并只传入假 Key:

docker run --rm -it \

--network=none \

--read-only \

-v "$PWD/mcp-test-data:/workspace:ro" \

-e TEST_API_KEY="fake_key_for_audit_only" \

unknown-mcp-server:fixed-version

这里有四个关键限制:

  • --network=none:第一次运行不允许联网
  • --read-only:容器文件系统只读
  • :ro:测试目录只读挂载
  • fixed-version:固定版本,不使用 latest

确认文件行为符合预期后,再分阶段开放网络,并限制到测试环境所需目标。不同 MCP Client 的启动配置格式不同,上述命令表达的是隔离思路,不是所有客户端都能直接复制的固定配置。

配置前后应该有什么变化?

下面是概念性对比,并非某个客户端的标准格式。

{

"command": "unknown-mcp-server",

"environment": "inherit-all",

"filesystem": "user-home",

"network": "unrestricted"

}

调整后:

{

"command": "unknown-mcp-server@fixed-version",

"environment": {

"TEST_API_KEY": "fake_key_for_audit_only"

},

"filesystem": {

"path": "./mcp-test-data",

"mode": "read-only"

},

"network": "disabled-first"

}

如果 Docker 不方便,也可以使用虚拟机或独立低权限系统账号。监控工具可按平台选择:

  • Linux: stracelsofss
  • macOS: fs_usagelsof
  • Windows: Process Monitor、TCPView
  • 请求内容: mitmproxy 或受控测试代理

正常与异常:同样叫“文件搜索”,行为可能完全不同

为了避免给真实开发者扣上“恶意”标签,可以自建两个功能相同的演示 Server。

正常版本

  • 只读取用户传入的文件路径
  • 不递归扫描其他目录
  • 不读取任何环境变量
  • 不访问网络
  • 错误日志不输出文件正文

异常版本

  • 启动时遍历用户主目录
  • 主动查找 .env.ssh.aws
  • 枚举所有环境变量
  • 将文件名与假密钥发送到未披露域名

二者对外都可以声明“提供文件搜索功能”,区别不在宣传页,而在运行日志。

安全判断不能停留在“它说自己会做什么”,而要落实到“系统记录它实际做了什么”。

复现实验时,应保存四类材料:

1. MCP 启动配置

2. 文件访问日志

3. 网络连接与抓包记录

4. 测试版本号和镜像摘要

这样下一次版本更新后,才有可比较的基线。

不是只有“接”或“不接”

可以将五项检查分别记为低风险 0 分、中风险 1 分、高风险 2 分,总分为 10 分。这个分数不是行业认证,而是一套帮助个人决策的自查方法。

| 检查项 | 低风险:0分 | 中风险:1分 | 高风险:2分 | | 文件权限 | 只读指定目录 | 需读取用户目录 | 扫描无关敏感目录 | | 外部请求 | 无请求或目标明确 | 依赖多个第三方域名 | 请求目标未披露 | | 密钥读取 | 只读专用 Key | 继承较多环境变量 | 读取无关凭证 | | 代码来源 | 维护者与版本清楚 | 项目较新、审计不足 | 包与仓库不一致 | | 安装行为 | 无额外脚本 | 下载公开依赖 | 执行不明远程脚本 |

对应的处理建议是:

  • 绿色,0—2分: 权限与功能匹配,可在保留日志的前提下接入。
  • 黄色,3—5分: 只在隔离环境运行,限制目录、网络和专用 Key。
  • 红色,6分及以上: 暂停接入,直到开发者解释异常行为或完成整改。

即使总分不高,只要出现“上传无关密钥”“执行不明远程脚本”等单项严重问题,也应直接拒绝接入,不能被总分稀释。

接入后,还要做持续防护

一次体检只能证明:这个版本在这次测试环境中,表现出了这些行为。

它不能永久证明一个 MCP Server 安全。正式使用后还应:

  • 固定 Server 与依赖版本
  • 关闭未经验证的自动更新
  • 使用独立低权限账号运行
  • 为每个工具分配专用 Key
  • 定期轮换测试与生产凭证
  • 保存文件访问和网络日志
  • 更新前比较代码、依赖和网络目标变化
  • 发现泄露后立即吊销凭证,而不是只删除配置

MCP Server 要使用专用权限,模型 API 同样不建议直接暴露生产凭证。完成工具侧体检后,可以前往 api.884819.xyz 查看可用接口与接入方式,为测试环境单独配置 API,先用非生产数据跑通整条调用链,再决定是否正式接入。

8848AI 无月租、无订阅,按量付费;国产模型如 Deepseek、千问等可免费使用。平台内置 AI 对话功能,使用用户名和密码即可注册,无需邮箱验证。

新用户注册即送体验token。

陌生 MCP Server 不是绝对不能接,而是不能在来源不明、权限不清、没有隔离的情况下直接接。

这次我们解决的是“接入前,怎么判断一个 MCP Server 会做什么”。但真正棘手的问题是:已经接入之后,如何知道它某次更新有没有偷偷扩大权限?

下一篇将实测一套 MCP 更新差异审计与持续监控方案,包括版本锁定、依赖变更、网络目标变化,以及如何在密钥泄露后快速止损。

本文由8848AI原创,转载请注明出处。关注8848AI,带你从零开始学AI。

#MCP #MCP安全 #AI教程 #网络安全 #Docker #人工智能 #8848AI #AI工具