Skip to content

chore: Restrict "json" type deserialization#6269

Merged
William FH (hinthornw) merged 9 commits into
mainfrom
wfh/jsonplus
Oct 20, 2025
Merged

chore: Restrict "json" type deserialization#6269
William FH (hinthornw) merged 9 commits into
mainfrom
wfh/jsonplus

Conversation

@hinthornw

Copy link
Copy Markdown
Contributor
  • Rm untyped loads/dumps
  • Restrict to an allow list

@vercel

vercel Bot commented Oct 10, 2025

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Preview Comments Updated (UTC)
langgraph-docs-preview Ignored Ignored Preview Oct 20, 2025 2:47pm

💡 Enable Vercel Agent with $100 free credit for automated AI reviews

@hinthornw William FH (hinthornw) merged commit c5744f5 into main Oct 20, 2025
127 of 129 checks passed
@hinthornw William FH (hinthornw) deleted the wfh/jsonplus branch October 20, 2025 17:18
@10ca1h0st

Copy link
Copy Markdown

checkpoint\langgraph\checkpoint\memory_init_.py
line 152: checkpoint_: Checkpoint = self.serde.loads_typed(checkpoint)

there exists the same problem. Should it be fixed?

Sydney Runkle (sydney-runkle) added a commit that referenced this pull request Apr 27, 2026
…ist (#7582)

## Summary

Fixes #7498 — `MESSAGE_COERCION_FAILURE` when resuming threads
checkpointed before v1.0.1.

**Root cause:** PR #6269 (v1.0.1) added an `_allowed_json_modules`
security gate to `JsonPlusSerializer._reviver`. The gate defaults to
`None`, so old `"json"`-format checkpoint blobs containing `lc=2`
constructor dicts (the pre-msgpack serialization format for pydantic
objects like `HumanMessage`) are now returned as raw dicts instead of
being reconstructed. Those raw dicts reach `add_messages →
convert_to_messages`, which sees `type="constructor"` and raises
`MESSAGE_COERCION_FAILURE`. Fresh first-turn messages are unaffected
because current `dumps_typed` only writes `"msgpack"` blobs.

**Fix:** `_reviver` now reconstructs `lc=2` blobs whose target class is
already in `SAFE_MSGPACK_TYPES` — the same curated allowlist already
used by the msgpack deserialization path (includes all standard
LangChain message types). Unknown classes are still blocked, preserving
the security intent of #6269.

## Changes

- `libs/checkpoint/langgraph/checkpoint/serde/jsonplus.py` — add
`_is_safe_json_type()` helper; update `_reviver` and
`_check_allowed_json_modules` to allow safe types without an explicit
allowlist
- `libs/checkpoint/tests/test_jsonplus.py` — two new regression tests:
safe-type `lc=2` blobs revive correctly; unknown-type `lc=2` blobs stay
blocked

## Test plan

- [ ] `test_lc2_json_safe_type_revives_without_allowlist` —
`HumanMessage`/`AIMessage` lc=2 JSON blobs round-trip to proper
`BaseMessage` objects with no allowlist configured
- [ ] `test_lc2_json_unknown_type_stays_blocked_without_allowlist` —
`pprint.pprint` lc=2 blob still returns raw dict (not reconstructed)
- [ ] `test_deserde_invalid_module` — existing behaviour unchanged
- [ ] Full `test_jsonplus.py` suite: 93/93 passing

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
xingshuozhu1998 pushed a commit to xingshuozhu1998/langgraph that referenced this pull request May 1, 2026
- Rm untyped loads/dumps
- Restrict to an allow list

---------

Co-authored-by: Sydney Runkle <sydneymarierunkle@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants