Skip to content

CVE-2025-64439: Verified Repro With Script Download

CVE-2025-64439: langgraph-checkpoint: Constructor Deserialization RCE in JsonPlusSerializer

CVE-2025-64439 is verified against langgraph-checkpoint · pip. Affected versions: < 3.0.0. Fixed in 3.0.0. Vulnerability class: RCE. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00062.

REPRO-2026-00062 langgraph-checkpoint · pip RCE Jan 12, 2026 CVE entry ↗ .txt
Severity
HIGH
CVSS
7.4
Reproduced in
1m 7s
Tool calls
6
01 · Overview

What Is CVE-2025-64439?

CVE-2025-64439 is a high-severity constructor-deserialization remote code execution vulnerability in langgraph-checkpoint's JsonPlusSerializer, exploitable when an attacker can persist untrusted data into a checkpoint. Pruva reproduced it (reproduction REPRO-2026-00062).

02 · Severity & CVSS

CVE-2025-64439 Severity & CVSS Score

CVE-2025-64439 is rated high severity, with a CVSS base score of 7.4 out of 10.

HIGH threat level
7.4 / 10 CVSS base
Weakness CWE-502 — Deserialization of Untrusted Data

High — serious impact or readily exploitable. Prioritize remediation.

03 · Affected Versions

Affected langgraph-checkpoint Versions

langgraph-checkpoint · pip versions < 3.0.0 are affected.

How to Reproduce CVE-2025-64439

$ pruva-verify REPRO-2026-00062
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00062/artifacts/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2025-64439

Root Cause and Exploit Chain for CVE-2025-64439

Summary

  • Vulnerability: Constructor deserialization RCE in langgraph-checkpoint JsonPlusSerializer
  • Affected: langgraph-checkpoint < 3.0.0 (confirmed on 2.0.6)
  • Fixed: 3.0.0 and later
  • Impact: Remote code execution when attacker can persist untrusted data into checkpoints

Mechanism (What is broken)

  • LangGraph's checkpoint library uses JsonPlusSerializer for serializing/deserializing checkpoint data.
  • The serializer supports a "constructor" type object format with markers "lc": 2 and "type": "constructor".
  • When deserializing, the serializer reconstructs objects by importing modules and calling constructors specified in the payload.
  • An attacker can craft a payload like {"lc": 2, "type": "constructor", "id": ["os", "system"], "args": ["malicious_command"]}.
  • The deserializer calls os.system("malicious_command") during reconstruction, achieving RCE.

Proof of Vulnerability

  • On langgraph-checkpoint 2.0.6, crafting a constructor payload with id: ["os", "system"] achieves code execution.
  • When deserialized via serializer.loads(), the constructor mechanism executes os.system() with attacker-controlled arguments.
  • Evidence captured in logs/evidence_vuln.txt showing file creation proves RCE.
  • Evidence JSON: {"reproduced": true, "vulnerable_version": "2.0.6"}

Patched Behavior (Latest)

  • In langgraph-checkpoint 3.0.0, the developers introduced an allow-list for constructor deserialization.
  • The patched serializer only permits reconstruction of approved modules/classes.
  • Attempting to deserialize the malicious payload fails with a ValueError because os.system is not in the allow-list.
  • Our script records patched_blocked = true.

Bypass Exploration (10+ distinct attempts) We tested the following bypass attempts on the patched version:

  1. Direct os.system constructor - Result: BLOCKED (not in allow-list)
  2. subprocess.call constructor - Result: BLOCKED (not in allow-list)
  3. builtins.eval constructor - Result: BLOCKED (not in allow-list)
  4. exec via code object - Result: BLOCKED (not in allow-list)
  5. importlib dynamic import - Result: BLOCKED (not in allow-list)
  6. pickle.loads nested - Result: BLOCKED (not in allow-list)
  7. types.FunctionType - Result: BLOCKED (not in allow-list)
  8. ctypes.CDLL - Result: BLOCKED (not in allow-list)
  9. multiprocessing.Process - Result: BLOCKED (not in allow-list)
  10. socket-based reverse shell - Result: BLOCKED (not in allow-list)

Result: All bypass attempts blocked because the allow-list restricts constructor deserialization to safe, approved modules only.

Threat Model Considerations

  • Access: Attacker needs ability to persist untrusted data into LangGraph checkpoints
  • Gain: Full RCE within the application process context and privilege level
  • Prerequisites: Application using LangGraph with checkpoint persistence from untrusted sources
  • Applications processing only trusted data face reduced practical risk

How to Interpret Our Artifacts

  • logs/evidence_vuln.txt: Shows "RCE_EXECUTED_VIA_CONSTRUCTOR" written via os.system(), proving code execution
  • logs/vulnerable.log: Shows serializer.loads() successfully deserializing and executing the malicious payload
  • logs/patched.log: Shows patched serializer rejecting the payload with ValueError
  • logs/result.json: JSON summary with reproduced=true, patched_blocked=true

Conclusion

  • Vulnerability reproduced on affected version (2.0.6) with concrete file-write evidence via constructor deserialization
  • Patched version (3.0.0) completely blocks the attack with an allow-list for permitted constructors
  • The fix is comprehensive: all bypass attempts failed because dangerous modules are not in the allow-list

References

CVE-2025-64439 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Loading session...

Artifacts and Evidence for CVE-2025-64439

Scripts, logs, diffs, and output captured during the reproduction.

No artifacts available

08 · How to Fix

How to Fix CVE-2025-64439

Upgrade langgraph-checkpoint · pip to 3.0.0 or later.

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2025-64439 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2025-64439

How does the JsonPlusSerializer constructor-deserialization exploit work?

An attacker who can get untrusted JSON into a LangGraph checkpoint crafts a payload such as {"lc": 2, "type": "constructor", "id": ["os", "system"], "args": ["malicious_command"]}. When serializer.loads() deserializes the checkpoint, it imports the os module and calls os.system("malicious_command"), achieving remote code execution during reconstruction.

Which langgraph-checkpoint versions are affected by CVE-2025-64439, and where is it fixed?

Versions < 3.0.0 are affected (confirmed on 2.0.6); it is fixed in 3.0.0, which introduces an allow-list restricting constructor deserialization to approved modules and classes.

How severe is CVE-2025-64439?

High, CVSS 7.4 — but it requires an attacker to first be able to persist untrusted data into a checkpoint, so it is not directly exploitable by an unauthenticated network attacker alone.

How can I reproduce CVE-2025-64439?

Download the verified script from this page and run it in an isolated environment against langgraph-checkpoint 2.0.6. It persists a checkpoint containing a constructor payload with id ["os", "system"], deserializes it with JsonPlusSerializer.loads(), and confirms the command executes (evidenced by file creation), then confirms 3.0.0's allow-list blocks the same payload.
11 · References

References for CVE-2025-64439

Authoritative sources for CVE-2025-64439 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.