Skip to content

Commit 44d4e8f

Browse files
INTPYTHON-825 LangGraph-Checkpoint CVE fix (#263)
[Issue Key](https://jira.mongodb.org/browse/INTPYTHON-825) ## Summary <!-- What is this PR introducing? If context is already provided from the JIRA ticket, still place it in the Pull Request as you should not make the reviewer do digging for a basic summary. --> This PR addresses a critical security vulnerability found in langgraph-checkpoint's serializer, "JsonSerializer". It is described in detail here: [RCE in json mode of JsonPlusSerializer](GHSA-wwqv-p2pp-99h5). ## Changes in this PR <!-- What changes did you make to the code? What new APIs (public or private) were added, removed, or edited to generate the desired outcome explained in the above summary? --> The primary change was to bump to "langggraph-checkpoint >= 3.0". The base checkpointer removed dumps/loads in preference of typed versions. We had previously only used the defaults so a few changes were made to update to these. ## Test Plan <!-- How did you test the code? If you added unit tests, you can say that. If you didn’t introduce unit tests, explain why. All code should be tested in some way – so please list what your validation strategy was. --> This change does not change any of our API so no changes to tests were made. All pass. [INTPYTHON-826](https://jira.mongodb.org/browse/INTPYTHON-826) will add tests of the serialization types once we expose them. ### Screenshots (optional) <!-- Usually a great supplement to a test plan, especially if this requires local testing. --> ## Checklist <!-- Do not delete the items provided on this checklist --> ### Checklist for Author - [X] Did you update the changelog (if necessary)? - [X] Is the intention of the code captured in relevant tests? - [x] Has a MongoDB Employee run [the patch build of this PR](https://github.com/mongodb-labs/ai-ml-pipeline-testing?tab=readme-ov-file#running-a-patch-build-of-a-given-pr)? ### Checklist for Reviewer {@primary_reviewer} - [ ] Does the title of the PR reference a JIRA Ticket? - [ ] Do you fully understand the implementation? (Would you be comfortable explaining how this code works to someone else?) - [ ] Have you checked for spelling & grammar errors? - [ ] Is all relevant documentation (README or docstring) updated?
1 parent d29d12e commit 44d4e8f

File tree

10 files changed

+218
-152
lines changed

10 files changed

+218
-152
lines changed

libs/langgraph-checkpoint-mongodb/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
---
44

5+
## Changes in version 0.2.2 (2025/11/13)
6+
7+
- Bumps minimum version of langgraph-checkpoint to 3.0 to address the Remode Code Execution CVE in JsonPlusSerializer's "json" mode, described [here](https://osv.dev/vulnerability/GHSA-wwqv-p2pp-99h5).
8+
- Fixed teardown step in release.yml GitHub workflow.
9+
510
## Changes in version 0.2.1 (2025/09/25)
611

712
- Fixes bug when graph interrupted leading to DuplicateKeyError when TTL is set.

libs/langgraph-checkpoint-mongodb/langgraph/checkpoint/mongodb/utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def loads_metadata(metadata: dict[str, Any]) -> CheckpointMetadata:
4141
output[key] = loads_metadata(value)
4242
return output
4343
else:
44-
return serde.loads(metadata)
44+
return serde.loads_typed(metadata)
4545

4646

4747
def dumps_metadata(
@@ -57,4 +57,4 @@ def dumps_metadata(
5757
output[key] = dumps_metadata(value)
5858
return output
5959
else:
60-
return serde.dumps(metadata)
60+
return serde.dumps_typed(metadata)

libs/langgraph-checkpoint-mongodb/pyproject.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ description = "Library with a MongoDB implementation of LangGraph checkpoint sav
99
readme = "README.md"
1010
requires-python = ">=3.10"
1111
dependencies = [
12-
"langgraph-checkpoint>=2.0.23,<3.0.0",
13-
"langchain-mongodb>=0.6.1",
12+
"langgraph-checkpoint>=3.0.0",
13+
"langchain-mongodb<1.0.0",
1414
"pymongo>=4.12,<4.16",
1515
]
1616

@@ -21,7 +21,6 @@ dev = [
2121
"langchain-ollama>=0.2.2",
2222
"langchain-openai>=0.2.14",
2323
"langgraph>=0.3.23",
24-
"langgraph-checkpoint>=2.0.9",
2524
"pytest-asyncio>=0.21.1",
2625
"pytest>=7.2.1",
2726
"pytest-mock>=3.11.1",

libs/langgraph-checkpoint-mongodb/tests/unit_tests/test_sync.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,8 @@ def test_nested_filter() -> None:
154154
assert (
155155
isinstance(doc["metadata"], dict)
156156
and isinstance(doc["metadata"]["writes"], dict)
157-
and isinstance(doc["metadata"]["writes"]["message"], bytes)
157+
and doc["metadata"]["writes"]["message"][0] == "msgpack"
158+
and isinstance(doc["metadata"]["writes"]["message"][1], bytes)
158159
)
159160

160161
# Test values of checkpoint

libs/langgraph-checkpoint-mongodb/tests/unit_tests/test_time_travel.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,13 @@ def checkpointer(request: Any) -> Generator[MongoDBSaver]:
5353
saver = MongoDBSaver(
5454
client=client,
5555
db_name=db_name,
56-
collection_name=checkpoint_collection_name,
57-
WRITES_COLLECTION_NAME=writes_collection_name,
56+
checkpoint_collection_name=checkpoint_collection_name,
57+
writes_collection_name=writes_collection_name,
5858
ttl=request.param,
5959
)
6060

6161
# Can use this to compare
62+
# from langgraph.checkpoint.memory import InMemorySaver
6263
# saver = InMemorySaver()
6364

6465
yield saver
@@ -93,7 +94,7 @@ def test(checkpointer: MongoDBSaver) -> None:
9394
graph = workflow.compile(checkpointer=checkpointer)
9495

9596
# Run the graph
96-
graph.invoke(input=initial_state, config=config) # type:ignore[arg-type]
97+
graph.invoke(input=initial_state, config=config, stream_mode="checkpoints") # type:ignore[arg-type]
9798

9899
# Check to see whether the final state is approved
99100
final_state = graph.get_state(config=config)
@@ -108,10 +109,12 @@ def test(checkpointer: MongoDBSaver) -> None:
108109

109110
target_checkpoint = None
110111
for checkpoint in checkpoints:
111-
# Look for checkpoint after increment but before final processing
112+
# Look for checkpoint after add_expense but before validate_expense
112113
if (
113-
checkpoint.metadata and checkpoint.metadata.get("step") == 1
114-
): # Before validate node
114+
checkpoint.metadata
115+
and checkpoint.metadata.get("step") == 1
116+
and "validate_expense" in checkpoint.next
117+
):
115118
target_checkpoint = checkpoint
116119
break
117120

@@ -126,15 +129,16 @@ def test(checkpointer: MongoDBSaver) -> None:
126129
assert target_checkpoint
127130
past_state = graph.get_state(target_checkpoint.config)
128131

129-
# Update the expense amount to 200 that validate amounts
132+
# Update the expense amount to 200 that validates amounts
130133
updated_state = dict(**past_state.values)
131-
# updated_state = {}
132-
updated_state["amount"] = 200
133-
updated_state["version"] = 2
134+
updated_state["amount"] += 100
135+
updated_state["version"] += 1
134136
updated_state["messages"] += ["Updated state"]
135137

136138
updated_config = graph.update_state(
137-
config=target_checkpoint.config, values=updated_state
139+
config=target_checkpoint.config,
140+
values=updated_state,
141+
as_node="add_expense",
138142
)
139143

140144
# Continue from the checkpoint

libs/langgraph-checkpoint-mongodb/uv.lock

Lines changed: 74 additions & 51 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libs/langgraph-store-mongodb/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
---
44

5+
## Changes in version 0.1.1 (2025/11/13)
6+
7+
- Bumps minimum version of langgraph-checkpoint to 3.0 to address the Remode Code Execution CVE in JsonPlusSerializer's "json" mode, described [here](https://osv.dev/vulnerability/GHSA-wwqv-p2pp-99h5).
8+
- Only lists authorized collections when listing collections.
9+
510
## Changes in version 0.1.0 (2025/08/20)
611

712
- Add additional client metadata to ``collection`` objects consumed by ``langgraph-store-mongodb``.

libs/langgraph-store-mongodb/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ description = "MongoDB implementation of the LangGraph long-term memory store."
99
readme = "README.md"
1010
requires-python = ">=3.10"
1111
dependencies = [
12-
"langgraph-checkpoint>=2.0.23,<3.0.0",
12+
"langgraph-checkpoint>=3.0.0",
1313
"langchain-mongodb>=0.6.1",
1414
]
1515

0 commit comments

Comments
 (0)