Bind authenticated identity to sessions in StreamableHTTPSessionManager

用户使用 MCP Python SDK 构建 HTTP 服务端,启用了 Bearer 令牌认证(如 BearerAuthBackend / RequireAuthMiddleware ),且使用了 StreamableHTTPSessionManager 管理有状态会话。当多个用户共享同一 Sess

Bind authenticated identity to sessions in StreamableHTTPSessionManager

Bind authenticated identity to sessions in StreamableHTTPSessionManager

快速结论:该安全问题发生在 MCP Python SDK 的 StreamableHTTPSessionManager 中,当启用身份认证(Auth)时,Session 管理器仅依赖 Mcp-Session-Id 头路由请求,未验证当前请求的认证身份是否与创建该 Session 的身份一致。优先排查 SDK 版本是否升级到 v1.27.2(v1.x 分支)或 main 分支最新提交 #2718。

问题场景

用户使用 MCP Python SDK 构建 HTTP 服务端,启用了 Bearer 令牌认证(如 BearerAuthBackend / RequireAuthMiddleware),且使用了 StreamableHTTPSessionManager 管理有状态会话。当多个用户共享同一 Session ID(例如日志泄露、非 TLS 网络窃听、共享基础设施)时,可能发生身份冒充。

报错原文

StreamableHTTPSessionManager._handle_stateful_request routes incoming requests to existing sessions based solely on the Mcp-Session-Id header value. There is no check that the authenticated identity on the incoming request matches the identity that originally created the session.

原因分析

认证中间件(Auth Middleware)与会话路由(Session Manager)是解耦的两层:认证层验证令牌并将认证上下文存储在 contextvar 中;而 Session 管理器仅通过 Mcp-Session-Id 头进行字典查找。两者从不交叉验证,导致泄露的 Session ID 可被任意持有者使用,绕过新增的身份认证。

环境排查

  • MCP Python SDK 版本:确认当前版本(v1.x 分支需要 ≥ v1.27.2;v2 分支需要包含 #2718 的版本)
  • 认证中间件:是否启用了 BearerAuthBackend / RequireAuthMiddleware 等认证组件
  • Session 管理器类型:是否使用了 StreamableHTTPSessionManager(有状态会话模式)

解决步骤

  1. 升级 MCP Python SDK:
    • v1.x 分支:升级到 v1.27.2 或更高版本(包含 PR #2719,基于 #2690 新增的 AccessToken subject/claims 功能)
    • main 分支(v2):合并 PR #2718 的提交
  2. 升级后,StreamableHTTPSessionManager 在创建 Session 时会自动记录认证主体(client_id、令牌签发者/主题),并在每次请求时将其与当前请求的认证身份比对,身份不匹配时返回 404 “Session not found”(与未找到 Session 的错误一致,避免信息泄露)。
  3. 该绑定逻辑也同时应用于 SSE(Server-Sent Events)传输层。

验证方法

更新后,使用不同认证身份的令牌(不同 client_id 或不同 subject)访问同一 Session ID:应当收到 404 响应,无法访问原会话资源。同时检查日志确认后端记录的身份比对过程正常。

参考来源

modelcontextprotocol/python-sdk #2100

celebrityanime
celebrityanime
文章: 8189

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注