mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-09-13 13:17:52 +02:00
docs: document LANGGRAPH_STRICT_MSGPACK for checkpoint security (#7517)
## Summary - Add `LANGGRAPH_STRICT_MSGPACK=true` guidance to `JsonPlusSerializer` docstring and inline comments - Update the warning message emitted for unregistered types to mention the env var - Add module docstring to `_msgpack.py` explaining the safety controls - Add Security sections to checkpoint, checkpoint-postgres, and checkpoint-sqlite READMEs ## Context Multiple security advisories have reported the same msgpack deserialization pattern (`ext_hook` → `importlib.import_module` → `getattr` → call). The underlying behavior is documented in the repo's threat model as T1, but the `LANGGRAPH_STRICT_MSGPACK` env var that mitigates it is not surfaced in user-facing docs, docstrings, or warning messages. This PR closes that gap. ## Test plan - [x] Verify READMEs render correctly on GitHub (callout boxes use `> [!IMPORTANT]` syntax) - [x] Verify `JsonPlusSerializer` docstring renders in IDE tooltips - [x] Confirm warning message format: `LANGGRAPH_STRICT_MSGPACK=true PYTHON_CMD 2>&1 | grep -i strict` --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
6719d34023
commit
7fa49bd550
@@ -6,6 +6,11 @@ Implementation of LangGraph CheckpointSaver that uses Postgres.
|
||||
|
||||
By default `langgraph-checkpoint-postgres` installs `psycopg` (Psycopg 3) without any extras. However, you can choose a specific installation that best suits your needs [here](https://www.psycopg.org/psycopg3/docs/basic/install.html) (for example, `psycopg[binary]`).
|
||||
|
||||
## Security
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Set `LANGGRAPH_STRICT_MSGPACK=true` or pass an explicit `allowed_msgpack_modules` list when creating your checkpointer. This restricts checkpoint deserialization to known-safe types, preventing code execution if the database is compromised. See the [langgraph-checkpoint README](https://github.com/langchain-ai/langgraph/tree/main/libs/checkpoint#serde) for details.
|
||||
|
||||
## Usage
|
||||
|
||||
> [!IMPORTANT]
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
Implementation of LangGraph CheckpointSaver that uses SQLite DB (both sync and async, via `aiosqlite`)
|
||||
|
||||
## Security
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Set `LANGGRAPH_STRICT_MSGPACK=true` or pass an explicit `allowed_msgpack_modules` list when creating your checkpointer. This restricts checkpoint deserialization to known-safe types, preventing code execution if the database is compromised. See the [langgraph-checkpoint README](https://github.com/langchain-ai/langgraph/tree/main/libs/checkpoint#serde) for details.
|
||||
|
||||
## Usage
|
||||
|
||||
```python
|
||||
|
||||
@@ -26,6 +26,9 @@ You must pass these when invoking the graph as part of the configurable part of
|
||||
|
||||
`langgraph_checkpoint` also defines protocol for serialization/deserialization (serde) and provides an default implementation (`langgraph.checkpoint.serde.jsonplus.JsonPlusSerializer`) that handles a wide variety of types, including LangChain and LangGraph primitives, datetimes, enums and more.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **Checkpoint deserialization security:** By default the serializer allows any Python type found in checkpoint data. New applications should set the environment variable `LANGGRAPH_STRICT_MSGPACK=true` or pass an explicit `allowed_msgpack_modules` list to `JsonPlusSerializer` to restrict deserialization to known-safe types.
|
||||
|
||||
### Pending writes
|
||||
|
||||
When a graph node fails mid-execution at a given superstep, LangGraph stores pending checkpoint writes from any other nodes that completed successfully at that superstep, so that whenever we resume graph execution from that superstep we don't re-run the successful nodes.
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
"""Msgpack deserialization safety controls.
|
||||
|
||||
Set ``LANGGRAPH_STRICT_MSGPACK=true`` to restrict checkpoint deserialization
|
||||
to the types listed in ``SAFE_MSGPACK_TYPES``. Without this, any Python
|
||||
callable stored in checkpoint data will be imported and executed on load.
|
||||
"""
|
||||
|
||||
import os
|
||||
from collections.abc import Iterable
|
||||
from typing import cast
|
||||
|
||||
@@ -56,6 +56,10 @@ class JsonPlusSerializer(SerializerProtocol):
|
||||
class and called within the Pregel loop. It should not be used on untrusted
|
||||
python objects. If an attacker can write directly to your checkpoint database,
|
||||
they may be able to trigger code execution when data is deserialized.
|
||||
|
||||
Set the environment variable ``LANGGRAPH_STRICT_MSGPACK=true`` to restrict
|
||||
deserialization to a built-in allowlist of safe types. You can also pass
|
||||
an explicit ``allowed_msgpack_modules`` to the constructor.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@@ -70,8 +74,11 @@ class JsonPlusSerializer(SerializerProtocol):
|
||||
) -> None:
|
||||
if allowed_msgpack_modules is _lg_msgpack._SENTINEL:
|
||||
if _lg_msgpack.STRICT_MSGPACK_ENABLED:
|
||||
# Strict: only SAFE_MSGPACK_TYPES are allowed.
|
||||
allowed_msgpack_modules = None
|
||||
else:
|
||||
# Permissive (default): all types allowed with a warning.
|
||||
# Set LANGGRAPH_STRICT_MSGPACK=true to lock this down.
|
||||
allowed_msgpack_modules = True
|
||||
self.pickle_fallback = pickle_fallback
|
||||
self._allowed_json_modules: set[tuple[str, ...]] | Literal[True] | None = (
|
||||
@@ -530,7 +537,8 @@ def _create_msgpack_ext_hook(
|
||||
logger.warning(
|
||||
"Deserializing unregistered type %s.%s from checkpoint. "
|
||||
"This will be blocked in a future version. "
|
||||
"Add to allowed_msgpack_modules to silence: [(%r, %r)]",
|
||||
"Set LANGGRAPH_STRICT_MSGPACK=true to block now, or add "
|
||||
"to allowed_msgpack_modules to allow explicitly: [(%r, %r)]",
|
||||
module,
|
||||
name,
|
||||
module,
|
||||
|
||||
Reference in New Issue
Block a user