A LangGraph agent is mid-task: it called three APIs, accumulated tool results, and is one resume() call from completing a privileged action. Between its last step and the next, an attacker writes 64 bytes to the checkpoint table. The agent resumes. The attacker now controls what the agent believes happened.
AI agent frameworks checkpoint conversation history, tool results, and task goals to disk or database for resume capability. That serialized state is an attack surface with no integrity controls. An adversary who modifies one checkpoint row controls every decision the agent makes after resuming. CVE-2026-28277 is the proof: SQLi into LangGraph's SQLite checkpointer chains to RCE via fabricated msgpack rows on resume.
Checkpoints Are Conversation History at Rest — and No One Treats Them That Way
An agent checkpoint is not a simple progress marker. It contains the full serialized conversation history, tool call results, goal context, and accumulated artifacts. In LangGraph, the checkpoint store includes the complete messages list with HumanMessage, AIMessage, and ToolMessage entries. Routing fields determine which node runs next; custom TypedDict fields carry domain-specific context.
CrewAI captures full crew configuration, agent memory and knowledge sources, task progress, intermediate outputs, and event history. No major agent framework documentation mentions encryption, signing, or access control for checkpoint storage. Checkpoint files are treated as infrastructure artifacts, stored in SQLite databases or Postgres tables without integrity controls.
An attacker who writes one row to the checkpoint store can inject a fabricated tool result. The agent will treat that result as authoritative on resume. The threat model is that simple.
The Serialization Stack Was Built for Speed, Not Trust
LangGraph's default serializer is JsonPlusSerializer using ormsgpack. The pickle_fallback=True is a documented production option for objects that ormsgpack cannot handle. The LangGraph AsyncPostgresSaver stores checkpoint blobs using pickle directly, not as a fallback, but as the default storage format.
The Python documentation states: "The pickle module is not secure. Only unpickle data you trust." That warning has existed since Python 2.3. A pickle payload can call any callable on deserialization, including os.system(), subprocess.run(), or arbitrary imports. CVE-2025-32444 (vLLM, CVSS 10.0) demonstrated RCE via pickle deserialization in vLLM's distributed inference state. Same root cause, different transport layer.
CVE-2025-1716 documented four bypass techniques against picklescan, the standard tool for detecting malicious pickle files. If your defense is scanning the checkpoint for known-malicious payloads, that defense has been published-bypassed. AutoGen uses JSON for conversation history, which eliminates pickle RCE, but remains semantically tamper-vulnerable: editing a JSON file fabricates any conversation history.
CVE-2026-28277 Is the Proof of Concept the Industry Needed
Check Point Research (2026) published a working exploit chain from SQL injection in LangGraph's checkpointer to arbitrary code execution. The chain has four steps. The get_state_history() method accepts a filter parameter passed unsanitized to the SQLite query. The SQLi payload appends a fabricated row to the checkpoint_blobs table.
The fabricated row contains a msgpack payload using the EXT_CONSTRUCTOR_SINGLE_ARG handler, a legitimate msgpack extension that imports and calls an arbitrary constructor on deserialization. On the next agent.resume() call, LangGraph deserializes the fabricated blob. The handler imports os and calls os.system() with an attacker-controlled argument.
The attack surface covers any web endpoint or API that passes user-controlled data to get_state_history(). Agentic SaaS products commonly expose this parameter to let users filter their own conversation history. arXiv 2506.17318 documents context manipulation attacks against web agents: injecting fabricated memory entries causes the agent to act on false information in subsequent tasks. Patches: langgraph-checkpoint-sqlite 3.0.1+, langgraph 1.0.10+, langgraph-checkpoint-redis 1.0.2+.
Semantic Tampering Is More Dangerous Than RCE When the Agent Has Tool Access
RCE via pickle gets code execution as the process user, typically limited by OS permissions. Semantic tampering gets the agent to execute actions within its authorized tool set. That set may include API calls, file writes, database queries, and external service calls the process user cannot make directly.
Take an agent with access to a code deployment tool. OS-level RCE via pickle gives the attacker shell access as the agent process user. A fabricated ToolMessage in the checkpoint can claim any tool returned success. Its tool authorization is not revoked by checkpoint tampering; the tamper causes the agent to use those tools against its principal's interests.
arXiv 2506.17318 demonstrated this at benchmark scale. Agents with fabricated memory entries completed tasks serving the attacker's goal, not the user's, using only their authorized tool set. arXiv 2607.02514 found that distributed attacks across persistent agent state evaded monitors in 93% of trials. Each modified state made the next modification easier to conceal.
This Is a Systemic Pattern, Not a LangGraph Bug
LangGraph is a case study. The pattern holds across the ecosystem. AutoGen without signing allows any conversation history file to be edited and saved; the agent trusts what it reads.
CrewAI serializes intermediate outputs: the results of tools the crew has already called. Injecting a fabricated intermediate output changes what the crew believes it has already done. CVE-2025-32444 in vLLM (CVSS 10.0) calls pickle.loads() on ZeroMQ socket data without authentication. arXiv 2607.02514 confirms the attack pattern is model-agnostic: it evaded Claude Sonnet 4.5, Gemini 3.1 Pro, and Kimi K2.5.
Any agentic system that serializes state to a location writable by an attacker inherits this vulnerability. The serialization format determines the blast radius.
OWASP LLM Top 10 2025, LLM03 Supply Chain, cites unsafe pickle deserialization as an RCE vector in AI pipelines. Checkpoint state is an internal artifact, not a supply chain component; the current taxonomy does not fully capture this threat class. There is no dedicated OWASP item for agent state integrity. The MAGO Intel tool (intel.mago.team) monitors agent checkpoint integrity and flags checkpoint files modified since the last verified agent write.
The Defense Is Three Lines of Code and a File Permission Check
Reject pickle entirely. Configure LangGraph to use JsonPlusSerializer without pickle_fallback. If an object cannot serialize to JSON+msgpack without pickle, that object does not belong in agent state. CVE-2025-1716 shows post-hoc scanning is bypassed; the defense must be pre-deserialization.
HMAC-sign every checkpoint write. On each write, compute HMAC-SHA256(checkpoint_blob, secret_key) and store the signature alongside the blob. On resume, verify before deserializing. Three lines of Python:
import hmac, hashlib
sig = hmac.new(secret, blob, hashlib.sha256).hexdigest()
# store sig alongside blob; verify before loads()
For SQLite checkpoints, the database file should be owned by the agent process user and not world-readable. chmod 600 checkpoints.db eliminates the most common opportunistic attack path. This is not a cryptographic defense, but access controls layer with HMAC verification to make attacks both harder and detectable. The OWASP Deserialization Cheat Sheet is clear: HMAC or digital signature is the primary preventive control when serialized data crosses a trust boundary.
Apply to the checkpoint store the same access controls you apply to .env files. If a developer can cat the checkpoint database on the production host without elevation, the controls are insufficient.
The agent's resume() call is a trust decision. Every framework that lets checkpoint data flow into agent context without a signature check is making that trust decision silently. It makes that decision on behalf of every user whose task the agent is running. Sign the checkpoint. Restrict the path. Verify before resume.
Top comments (0)