Listen to this Post

Introduction:
LangGraph, an open-source framework for building stateful AI agents, is downloaded over 50 million times a month from PyPI. Its checkpointer system — the persistence layer that saves every step of an agent’s execution — was found to contain a critical vulnerability chain. Check Point Research demonstrated that a simple SQL injection in the SQLite checkpointer’s metadata filter could be chained with unsafe msgpack deserialization to achieve full remote code execution (RCE) on self-hosted agent servers. The managed LangSmith service, which runs Postgres, is not affected — but every self-hosted deployment using SQLite or Redis checkpointers with user-controlled filters is at risk.
Learning Objectives:
- Understand the technical chain connecting SQL injection (CVE-2025-67644) to unsafe deserialization (CVE-2026-28277) and RCE.
- Learn to identify vulnerable LangGraph checkpointer configurations in your own deployments.
- Apply patches, configuration hardening, and defensive coding practices to mitigate these risks.
You Should Know:
- The Vulnerability Chain: How a Quote in a Filter Key Becomes a Server Takeover
LangGraph’s checkpointer saves the agent’s state at every step to a persistence layer (SQLite, Redis, or Postgres). Applications read that history through the `get_state_history()` function, and many expose a metadata filter to users.
The SQL Injection (CVE-2025-67644, CVSS 7.3):
The SQLite checkpointer binds filter values as parameters — but pastes the filter keys directly into the SQL string. The vulnerable `_metadata_predicate()` function constructs queries like this:
VULNERABLE CODE (before fix)
for query_key, query_value in metadata_filter.items():
operator, param_value = _where_value(query_value)
predicates.append(
f"json_extract(CAST(metadata AS TEXT), '$.{query_key}') {operator}"
)
param_values.append(param_value)
While `query_value` is parameterized, `query_key` is interpolated directly via f-string without validation. An attacker controlling the filter key can inject arbitrary SQL:
malicious_filter = {"x') OR '1'='1": "dummy"}
Results in: WHERE json_extract(..., '$.x') OR '1'='1') = ?
This makes the WHERE clause always true, returning all checkpoints.
The Deserialization Payload (CVE-2026-28277, CVSS 6.8):
Using UNION SELECT, the attacker returns a fake checkpoint row containing a crafted msgpack payload. When the server reads that row back, the `JsonPlusSerializer` deserializes the msgpack data and — prior to the patch — would reconstruct arbitrary Python objects. A payload like `os.system` inside the deserialized data executes when the checkpoint is loaded.
Redis Checkpointer (CVE-2026-27022, CVSS 6.5):
The Redis checkpointer repeats the same mistake in RediSearch’s query language, though it stops at data exposure rather than RCE.
The Complete Attack Chain:
- Attacker sends a malicious filter key with SQL injection payload.
- SQL injection uses `UNION SELECT` to return a fake checkpoint row with attacker-controlled msgpack data.
3. Server deserializes the fake checkpoint.
- Unsafe deserialization triggers execution of attacker-supplied code (e.g.,
os.system).
5. Attacker achieves RCE on the agent server.
- Who Is Affected — and How to Check Your Deployment
You are at HIGH RISK if:
- You run a custom self-hosted LangGraph server.
- You use the SQLite (
SqliteSaver) or Redis checkpointer. - Your application exposes an endpoint that calls `get_state_history()` with metadata filter keys from untrusted sources.
You are NOT affected if:
- You use LangSmith managed service (Postgres-based, no custom checkpointer configuration).
- You use the Postgres checkpointer (not vulnerable to SQL injection).
- You do not expose the filter to untrusted input.
Check your versions:
Check installed LangGraph packages pip list | grep langgraph Vulnerable versions: langgraph-checkpoint-sqlite < 3.0.1 langgraph-checkpoint-redis < 1.0.2 langgraph-checkpoint (core) < 4.0.1
Example of vulnerable code pattern (DO NOT use):
❌ VULNERABLE: User controls filter key names
@app.post("/api/history")
def get_history(request):
filter_field = request.json.get("filter_field") Untrusted
filter_value = request.json.get("filter_value")
history = list(graph.get_state_history(
config,
filter={filter_field: filter_value} 💀 Injection point
))
return history
3. Immediate Remediation: Patch and Harden
Step 1: Update all affected packages
Upgrade core checkpointer package pip install --upgrade langgraph-checkpoint>=4.0.1 Upgrade SQLite checkpointer pip install --upgrade langgraph-checkpoint-sqlite>=3.0.1 Upgrade Redis checkpointer pip install --upgrade langgraph-checkpoint-redis>=1.0.2
Step 2: Enable strict msgpack deserialization (defense in depth)
Set the environment variable to restrict deserialization to known-safe types:
export LANGGRAPH_STRICT_MSGPACK=true
Or pass explicitly when creating your checkpointer:
from langgraph.checkpoint.sqlite import SqliteSaver Strict mode - only built-in safe types allowed saver = SqliteSaver.from_conn_string( "checkpoints.db", allowed_msgpack_modules=None Strict mode )
Step 3: Audit your code for untrusted filter keys
Search your codebase for `get_state_history()` calls. If the `filter` parameter accepts any key from user input, refactor to:
– Whitelist allowed filter keys — only permit known-safe field names.
– Never interpolate user input into SQL or query languages.
– Use parameterized queries for all database interactions.
✅ SAFE: Whitelist allowed filter keys
ALLOWED_FILTER_KEYS = {"user_id", "session_id", "status"}
@app.post("/api/history")
def get_history(request):
filter_field = request.json.get("filter_field")
if filter_field not in ALLOWED_FILTER_KEYS:
raise ValueError("Invalid filter field")
filter_value = request.json.get("filter_value")
history = list(graph.get_state_history(
config,
filter={filter_field: filter_value}
))
return history
- Postgres Checkpointer: The Safe Alternative (with Proper Configuration)
If you’re self-hosting, migrate to Postgres — it’s not vulnerable to the SQL injection and offers better security defaults.
Installation:
pip install langgraph-checkpoint-postgres
Configuration (with strict msgpack):
from langgraph.checkpoint.postgres import PostgresSaver import os DB_URI = "postgres://user:password@localhost:5432/langgraph" Enable strict msgpack deserialization os.environ["LANGGRAPH_STRICT_MSGPACK"] = "true" with PostgresSaver.from_conn_string(DB_URI) as checkpointer: Call .setup() the first time to create tables checkpointer.setup() Use the checkpointer with your graph graph = builder.compile(checkpointer=checkpointer)
Important: When manually creating connections, include `autocommit=True` and row_factory=dict_row:
from psycopg.rows import dict_row import psycopg conn = psycopg.connect(DB_URI, autocommit=True, row_factory=dict_row) checkpointer = PostgresSaver(conn)
5. Redis Checkpointer: Update and Restrict
If you must use Redis, update to the patched version and restrict access:
pip install --upgrade langgraph-checkpoint-redis>=1.0.2
Configuration:
from langgraph.checkpoint.redis import RedisSaver
import os
os.environ["LANGGRAPH_STRICT_MSGPACK"] = "true"
saver = RedisSaver.from_host_and_port("localhost", 6379)
Also consider Redis network isolation and authentication
6. Linux and Windows Commands for Forensic Investigation
If you suspect your LangGraph server may have been compromised:
Linux: Check for unauthorized processes:
List all running processes with full command lines ps auxf Check for unusual network connections ss -tulpn | grep -E 'LISTEN|ESTAB' Review recent authentication logs sudo journalctl -u your-langgraph-service --since "1 hour ago" Check for modified checkpoint database files find /path/to/checkpoints -type f -1ame ".db" -mtime -1 -ls
Windows (PowerShell):
Check running processes
Get-Process | Format-Table -AutoSize
Check network connections
netstat -an | findstr LISTEN
Review Event Logs for suspicious activity
Get-WinEvent -LogName Security -MaxEvents 50 | Where-Object {$_.Id -in 4624,4625}
Check for msgpack payloads in your database:
-- SQLite: Look for suspicious BLOB data in checkpoints SELECT id, checkpoint, metadata FROM checkpoints WHERE checkpoint LIKE '%os.system%' OR checkpoint LIKE '%<strong>import</strong>%' OR checkpoint LIKE '%eval%';
7. Long-Term Security Hardening for AI Agent Deployments
Beyond patching, consider these additional measures:
- Environment Isolation: Run LangGraph agents in containers with minimal privileges. Use read-only filesystems where possible.
-
Network Segmentation: Ensure the checkpoint database is not directly accessible from the internet. Use VPCs, firewalls, or service meshes.
-
Secrets Management: Never store credentials in environment variables accessible to the agent runtime. Use secret managers (AWS Secrets Manager, HashiCorp Vault, Azure Key Vault).
-
Cryptographic Signing: Consider using `kanon-langgraph` — a drop-in replacement that cryptographically signs every checkpoint. If stored state is altered, it raises an error before returning the checkpoint.
-
Regular Audits: Run vulnerability scanners against your Python dependencies:
Using safety pip install safety safety check -r requirements.txt Using pip-audit pip install pip-audit pip-audit -r requirements.txt
What Undercode Say:
-
Memory poisoning is now a two-front war. We’ve seen attackers poison AI memory on the write side (injecting false facts). This attack proves the read side is just as dangerous — the database that powers agent memory is itself a SQL injection target, and reading it back can trigger code execution.
-
This is classic vulnerability classes in a new context. SQL injection and unsafe deserialization are decades-old problems. They’re especially dangerous here because code execution on an agent server exposes every credential, conversation, and tool the agent has ever accessed.
-
The deserializer is the real killer. The SQL injection is just the way in. The unsafe msgpack deserialization lives in the core `langgraph-checkpoint` package shared by both backends. That’s why upgrading the core package to 4.0.1 is non-1egotiable, even if you don’t use SQLite.
-
A public PoC already exists. This isn’t theoretical — proof-of-concept exploit code is publicly available. Every self-hosted LangGraph deployment should be patched immediately.
-
The blast radius is severe. An RCE on the agent server means attackers can access cloud credentials, environment variables, API keys, and other internal systems the runtime can reach. This isn’t just an AI security issue — it’s a full infrastructure compromise.
Expected Output:
Introduction:
LangGraph’s checkpointer system, downloaded over 50 million times monthly, was found to contain a critical vulnerability chain enabling remote code execution. Check Point Research demonstrated how a SQL injection in metadata filters (CVE-2025-67644) chains with unsafe msgpack deserialization (CVE-2026-28277) to achieve full server takeover on self-hosted deployments. The managed LangSmith service remains unaffected, but every self-hosted LangGraph using SQLite or Redis checkpointers with user-controlled filters is at immediate risk.
What Undercode Say:
- Two-front memory warfare: Attackers can now exploit both write-side (poisoning) and read-side (SQLi → RCE) memory vectors. The database that powers agent memory is a SQL injection target, and reading it back triggers code execution.
- Patch the core, not just the backend: The unsafe deserializer sits in `langgraph-checkpoint` (core), shared by both SQLite and Redis backends. Upgrade to 4.0.1 immediately.
Prediction:
- +1 Expect a surge in automated scanning for exposed LangGraph `get_state_history()` endpoints. Attackers will weaponize the public PoC within days.
-
+1 The AI security industry will increasingly treat “agent memory” as a critical attack surface, driving demand for memory encryption, cryptographic signing, and strict deserialization controls.
-
-1 Organizations that fail to patch will face credential theft and lateral movement attacks, as RCE on an agent server exposes every secret the agent has ever accessed.
-
-1 This incident will erode trust in self-hosted AI frameworks, pushing more enterprises toward managed services like LangSmith — even as open-source adoption continues to grow.
-
+1 The vulnerability disclosure and rapid patching (three CVEs fixed across multiple packages) demonstrate that the LangChain ecosystem is maturing its security response.
-
-1 Expect copycat vulnerabilities in other AI agent frameworks that use similar checkpointing patterns with unsafe deserialization — this is a class vulnerability, not an isolated incident.
▶️ Related Video (66% Match):
https://www.youtube.com/watch?v=1qp72Ioh-bw
🎯Let’s Practice For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
IT/Security Reporter URL:
Reported By: Ilyakabanov A – Hackers Feeds
Extra Hub: Undercode MoN
Basic Verification: Pass ✅


