FlawOpen

flawopen.com/AI Security/langgraph-js-custom-auth-cross-user-store-access

● CWE-639 / CWE-863 · CVSS v4 8.6[1] · 高危
安全研究 · FlawOpen

LangGraph JS Auth:跨用户 Store 数据访问

langgraph-api 0.15.0之前可能丢失JS/TS自定义认证对Store命名空间的重写,导致跨用户访问。请升级至0.15.0。[1], [2]

CVSS 向量CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N[1]
💡 通俗易懂的原理解析 (ELI5)

想象图书管理员检查了你的借书证,然后让另一个柜台取书。第二个柜台把你的书架编号写进请求,但交接时修改丢失,最终按访客最初提供的书架编号取书。受影响的 JavaScript/TypeScript 认证路径可能在授权运行时与 Store 操作之间丢失 namespace 重写。修复会传递授权后的 namespace,并在使用 Store 前进行验证。[1]

核心概念与专有名词

GHSA-4hm6-w6qq-w73v
LangGraph 于 2026 年 9 月 28 日发布的高危安全公告。未分配 CVE。受影响软件包为 langgraph-api,0.15.0 已修复。[1]
Store namespace
用于对 LangGraph Store 记录分组的层级名称。应用通常将用户或租户标识放入其中以隔离数据。[1]
自定义授权处理器
应用代码,用于判断已认证请求是否可访问资源,并可在 Store 操作前重写 namespace。[1]
CWE-639 / CWE-863
通过用户可控键绕过授权以及授权错误。问题在于未应用处理器设定的 namespace 限制。[1], [3], [4]

框架映射

攻击执行流程分解

步骤 1

确认部署是否符合条件

检查 langgraph-api 是否 >=0.1.2 且 <0.15.0,以及服务端是否使用 JavaScript 或 TypeScript 自定义认证处理器。[1]

步骤 2

定位 namespace 重写逻辑

处理器会修改请求的 namespace,以加入或强制执行已认证用户的身份,而不是拒绝超出其 namespace 的请求。[1]

步骤 3

授权结果跨越运行时边界

受影响版本可能无法将 namespace 修改传递给 Store 操作,导致继续使用请求方最初提供的 namespace。[1]

步骤 4

已认证用户访问其他 namespace

普通账号可以针对自身 namespace 之外的 Store 记录请求操作。公告列出的影响包括读取、覆盖、搜索和删除。[1]

步骤 5

升级或拒绝未授权 namespace

升级至 langgraph-api>=0.15.0。若暂不能升级,则所有 Store 操作都应拒绝未授权 namespace,并确认 Store 收到的仅是授权后的 namespace。[1], [2]

根本原因剖析 (Root Cause)

LangGraph 维护者于 2026 年 9 月 28 日发布的 GHSA 描述了 langgraph-api >=0.1.2 且 <0.15.0 中的问题,且必须同时满足以下条件:部署使用 JavaScript 或 TypeScript 自定义认证;Store 授权处理器通过重写请求的 namespace 将数据限制到当前用户;普通已认证用户可以发起 Store 操作;多个用户的数据经过该授权路径。公告指出 Python 自定义认证处理器不受影响;若 JavaScript/TypeScript 处理器选择拒绝未授权 namespace,而不是重写它们,也不受影响。处理器对 namespace 的修改可能在运行时边界丢失,因此 Store 操作使用了原始请求中的 namespace。已认证用户可能读取、覆盖、搜索或删除授权 namespace 之外的记录。这不绕过登录,也不是未认证远程攻击。公告评级为高危,CVSS 4.0 为 8.6,并列出 CWE-639 和 CWE-863。0.15.0 会跨边界传递处理器修改,验证最终 namespace,并拒绝格式错误或未能安全应用的授权更改。若暂时不能升级,维护者建议所有 Store 操作都拒绝未授权 namespace。代码对比是数据流的简化 TypeScript 示意,并非 SDK 源码。[1]

源代码对比:漏洞与安全实现

此精简 TypeScript 示例用于说明边界契约;函数名称和结果格式仅为示意,并非 LangGraph SDK 源码。公告确认 JS/TS 授权修改可能在 Store 操作前丢失,但未公开这一确切的内部实现。因此,易受影响的一侧只表示公告中的不变量:Store 使用请求中的 namespace,而不是授权后的 namespace。修复一侧使用并验证授权结果。维护者记录的临时方案是对每项 Store 操作拒绝未授权 namespace,而不是重写它。[1]

源码摘录: LangGraph API 授权到 Store 的边界——精简示意契约

存在漏洞的实现
type StoreRequest = { namespace: string[]; key: string };
type AuthorizationResult = { allowed: boolean; namespace: string[] };

async function readStore(userId: string, request: StoreRequest) {
  const authorization = await authorizeStore(userId, request); // Illustrative bridge contract.
  return store.get(request.namespace, request.key); // The bridge drops the authorized result.
}
加固后的安全修复
type StoreRequest = { namespace: string[]; key: string };
type AuthorizationResult = { allowed: boolean; namespace: string[] };

async function readStore(userId: string, request: StoreRequest) {
  const authorization = await authorizeStore(userId, request); // Illustrative bridge contract.
  if (!authorization.allowed) throw new Error("forbidden");
  const namespace = validateAuthorizedNamespace(userId, authorization.namespace);
  return store.get(namespace, request.key); // Apply the authorized result.
}

工程与系统安全加固清单

参考来源

← AI Security Directory →