flawopen.com/AI Security/langgraph-js-custom-auth-cross-user-store-access
LangGraph JS Auth: Cross-User Store Access
langgraph-api <0.15.0 could drop JS/TS custom-auth Store namespace rewrites, enabling cross-user access. Upgrade to 0.15.0.[1], [2]
Imagine a librarian who checks your library card, then asks a separate desk to fetch a book. The desk writes your own shelf number on the request, but the handoff silently loses that change and fetches the shelf number the visitor originally supplied. LangGraph’s affected JavaScript/TypeScript auth path could lose the namespace rewrite between its authorization runtime and Store operation. The fix carries the authorized namespace across that boundary and validates it before using the Store.[1]
Core Concepts & Subsystem Terms
GHSA-4hm6-w6qq-w73v- A high-severity LangGraph advisory published September 28, 2026. It has no assigned CVE. The affected package is langgraph-api, fixed in 0.15.0.[1]
Store namespace- A hierarchical name used to group LangGraph Store records. Applications often place a user or tenant identifier in the namespace to separate data.[1]
Custom authorization handler- Application code that decides whether an authenticated request may access a resource and can rewrite the Store namespace before the operation.[1]
Framework mappings
Step-by-Step Attack Flow
Confirm the deployment matches the advisory
Check langgraph-api is >=0.1.2 and <0.15.0, and the server uses a JavaScript or TypeScript custom-auth handler.[1]
Identify the namespace rewrite
The handler changes a requested Store namespace to include or enforce the authenticated user’s identity, instead of rejecting a request outside that namespace.[1]
The authorization result crosses a runtime boundary
In affected versions the handler’s namespace change may not be propagated back to the Store operation. The original caller-supplied namespace can remain in use.[1]
An authenticated user targets another namespace
A normal account can request Store operations against records outside its own namespace. The advisory lists read, overwrite, search, and delete as possible impacts.[1]
Root Cause Analysis
The LangGraph maintainers’ GHSA published September 28, 2026 describes a flaw in langgraph-api versions >=0.1.2 and <0.15.0 when all of the following hold: the deployment uses JavaScript or TypeScript custom authentication; its Store authorization handler rewrites a requested namespace to scope data to the current user; a regular authenticated user can send Store operations; and multiple users’ data flows through that authorization path. The advisory says Python custom-auth handlers are not affected, and JavaScript/TypeScript handlers that reject unauthorized namespace requests instead of rewriting them are not affected. The authorization handler’s namespace change could be lost across a runtime boundary, so the Store operation used the original requested namespace. An authenticated user could then read, overwrite, search, or delete records outside their authorized namespace. This does not bypass login and is not an unauthenticated remote attack. The advisory scores it High, CVSS 4.0 8.6, and assigns CWE-639 and CWE-863. Version 0.15.0 carries the handler’s changes across the boundary, validates the resulting namespace, and rejects malformed or unapplied authorization changes. If upgrade is delayed, the maintainer’s workaround is to reject unauthorized namespace requests rather than rewrite them, for every exposed Store action. The code pair is a reduced TypeScript illustration of the data-flow invariant, not copied SDK source.[1]
Source Code: Flaw vs. Secure Implementation
This reduced TypeScript example illustrates a boundary contract; the function names and result shape are illustrative, not LangGraph SDK source. The advisory establishes that JS/TS authorization changes could be lost before the Store operation, but does not publish this exact internal implementation. The vulnerable side therefore models only the documented invariant: the Store uses the request namespace instead of the authorized namespace. The fixed side consumes and validates the authorized result. The maintainer’s documented workaround is to reject unauthorized namespaces rather than rewrite them, for every Store action.[1]
Source excerpt: LangGraph API authorization-to-Store boundary — reduced illustrative bridge contract
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.
}
Engineering & System Hardening Checklist
- ✓Inventory
langgraph-apiversions and identify JavaScript/TypeScript custom-auth deployments; Python custom-auth deployments are outside this advisory’s scope.[1] - ✓Upgrade affected deployments to
langgraph-api>=0.15.0and verify the deployed artifact, not just the lockfile or source branch.[1], [2] - ✓Until upgraded, make every Store authorization handler reject requests outside the authenticated user’s namespace; do not rely on a rewrite whose result might be dropped.[1]
- ✓Test
get,put,search,delete, and namespace-list operations with two test identities; assert every operation is bound to the authorized namespace and cross-user access is denied.[1] - ✓Review available Store access and mutation logs for cross-user namespace reads, searches, or writes. If you find unauthorized changes, preserve evidence and assess affected records before cleanup.[1], [5]