LangGraph checkpointers can load msgpack-encoded checkpoints that reconstruct Python objects during deserialization. If an attacker can modify checkpoint data in the backing store (for example, after a database compromise or other privileged write access to the persistence layer), they can potentially supply a crafted payload that triggers unsafe object reconstruction when the checkpoint is loaded.
This is a post-exploitation / defense-in-depth issue. Exploitation requires the ability to write attacker-controlled checkpoint bytes at rest. In most deployments that prerequisite already implies a serious incident; the additional risk is turning “checkpoint-store write access” into code execution in the application runtime, which can expand blast radius (for example by exposing environment variables or cloud credentials available to the runtime).
There is no evidence of exploitation in the wild, and LangGraph is not aware of a practical exploitation path in existing deployments today. This change is intended to reduce the blast radius of a checkpoint-store compromise.
Users may be affected if they:
This issue requires the attacker to be able to modify persisted checkpoint bytes (or to compromise a trusted component that writes them). It is generally not reachable by an unauthenticated remote attacker in a correctly configured deployment.
LangGraph provides an allowlist-based hardening mechanism for msgpack checkpoint deserialization.
LANGGRAPH_STRICT_MSGPACK
1, true, yes), the default msgpack deserialization policy becomes strict.JsonPlusSerializer() will default allowed_msgpack_modules to None (strict) instead of True (warn-and-allow), unless allowed_msgpack_modules=... is explicitly passed.allowed_msgpack_modules (serializer/checkpointer config)This setting controls what msgpack “ext” types are allowed to be reconstructed.
True (default when strict mode is not enabled): allow all ext types, but log a warning when deserializing a type that is not explicitly registered.None (strict): only a built-in safe set is reconstructed; other ext types are blocked.[(module, class_name), ...] (strict allowlist): the built-in safe set plus exactly the listed symbols are reconstructed (exact-match).A small set of types is always treated as safe to reconstruct (for example datetime types, uuid.UUID, decimal.Decimal, set/frozenset/deque, ipaddress types, pathlib paths, zoneinfo.ZoneInfo, compiled regex patterns, and selected LangGraph internal types).
When LANGGRAPH_STRICT_MSGPACK is enabled and StateGraph is compiled, LangGraph derives an allowlist from the graph’s schemas and channels and applies it to the checkpointer.
Annotated).This derived allowlist is only applied if the selected checkpointer supports with_allowlist(...). If a user is constructing serializers/checkpointers manually (or using a checkpointer that does not support allowlist propagation), they will need to configure allowed_msgpack_modules themselves.
LANGGRAPH_STRICT_MSGPACK=true) in production if feasible, and rely on schema-driven allowlisting to reduce incompatibilities.with_allowlist), allowlist enforcement may be skipped (with a warning). In that situation, strict expectations may not hold.ext_hook), the custom hook controls reconstruction and can bypass the default allowlist checks (intentional escape hatch, but it weakens the protection).LangSmith is not aware of this issue presenting risk to existing LangSmith-hosted deployments. The described threat model requires an attacker to tamper with the checkpoint persistence layer used by the deployment; typical hosted configurations are designed to prevent such access.
First reported by: yardenporat353
{
"cwe_ids": [
"CWE-502"
],
"github_reviewed": true,
"github_reviewed_at": "2026-03-05T20:19:49Z",
"nvd_published_at": "2026-03-05T20:16:15Z",
"severity": "MODERATE"
}