Rationale
Prompt injection and tool execution: LangGraph’s
ToolNode validates tool names against the registered set
but does not inspect or sanitize argument values. This is the correct
boundary — the framework cannot know what constitutes a “safe” argument
for an arbitrary user-defined tool. The tool’s own Pydantic schema and
implementation must validate inputs. The framework’s responsibility is
to not execute unregistered tools and to correctly route registered
ones. The injection system (InjectedState/InjectedStore/ToolRuntime) is
safe because system-injected values always overwrite LLM-supplied
collisions via dict merge order, and injected parameter names are hidden
from the LLM’s tool schema.
State integrity: LangGraph channels enforce type
contracts (e.g., LastValue accepts one value per step,
BinaryOperatorAggregate applies a reducer). The framework
validates graph structure at compile time
(libs/langgraph/langgraph/pregel/_validate.py:validate_graph).
However, the semantic correctness of state updates is the user’s
responsibility — the framework cannot know what values are “valid” for a
user-defined state schema.
Checkpoint access control: The framework provides
BaseCheckpointSaver as an abstract interface and the
Auth handler system for authorization
(libs/sdk-py/langgraph_sdk/auth/__init__.py:Auth). It does
not enforce authentication by default because it operates as a library,
not a server. The langgraph-api server layer (out of scope)
is responsible for enforcing auth on API endpoints. Users embedding
LangGraph directly must implement their own access controls.
Encryption handler safety: The SDK Encryption module
(libs/sdk-py/langgraph_sdk/encryption/) provides a
registration framework for developer-authored encryption handlers. These
handlers run server-side with full process access, identical to any
application code. A buggy or malicious handler could return crafted
data, but this is the same trust model as any developer-written code.
The SDK validates handler shape (async, 2-param) but not handler
behavior — this is the correct boundary for developer-trust-level
code.