A three-vulnerability chain in LangGraph, disclosed today by Check Point researcher Yarden Porat, lets an attacker escalate from a single SQL injection in a metadata filter to full remote code execution on self-hosted AI agents, by using the agent's own checkpoint store as the deserialization payload. The blast radius is narrower than the worst-case framing suggests: only self-hosted deployments running the SQLite or Redis checkpointer, with an exposed endpoint that accepts user-controlled filter input, are exploitable. The managed LangSmith Deployment platform is not affected.
The chain reads, in order: CVE-2025-67644, a SQL injection in langgraph-checkpoint-sqlite that scores 7.3 on CVSS and is classified CWE-89; CVE-2026-28277, an unsafe msgpack deserialization in the core langgraph package, scoring 6.8 and classified CWE-502; and CVE-2026-27022, a sibling RediSearch query injection in @langchain/langgraph-checkpoint-redis that scores 6.5 on CVSS. The first two link into a pre-auth RCE; the third stands on its own for Redis-based deployments.
The trigger is a single application pattern. LangGraph's get_state_history() endpoint lets a caller retrieve historical checkpoints by metadata filter. If a self-hosted deployment routes untrusted input into that filter and runs the SQLite checkpointer, the _metadata_predicate() function interpolates the filter key directly into a SQL query via f-string, with no validation. The SQLi returns attacker-controlled bytes. Those bytes are a msgpack payload, and on the way back into the LangGraph checkpoint loader they get deserialized into live Python objects, completing the chain.
Two threat models, one chain. LangChain maintainers describe CVE-2026-28277 as a post-exploitation issue, defense-in-depth against a compromised checkpoint store, while Check Point's disclosure frames the SQLi-plus-deserialization pair as a pre-auth RCE path. Both are correct, at different links in the same chain. The practical disagreement is about which defense you trust first, not about whether the chain works.
Patches are out, and the version cutoffs are precise. Operators running langgraph-checkpoint-sqlite need at least 3.0.1, fixed by commit 29724291. Core langgraph needs 1.0.10, which adds a new LANGGRAPH_STRICT_MSGPACK environment variable and an allowed_msgpack_modules allowlist on JsonPlusSerializer covering a built-in safe set and curated LangGraph types. @langchain/langgraph-checkpoint-redis needs 1.0.1. The accompanying msgpack advisory is GHSA-g48c-2wqr-h844.
The mitigation stack, in order: update to the patched versions; audit any endpoint that passes untrusted filter keys into get_state_history(); set LANGGRAPH_STRICT_MSGPACK even on the patched line, because it constrains the deserializer to the allowlist and blunts future unsafe-type regressions; treat the agent as a privileged identity, with network segmentation around the checkpoint store; and rotate any long-lived static secrets that the deployment uses to talk to it.
Two NVD entries lag the GitHub advisories. NVD currently lists "no known patch is public" for CVE-2026-28277 and has not yet assigned a CVSS to either CVE. Treat the GitHub Security Advisories as the source of truth for affected versions and remediation; the 7.3, 6.8, and 6.5 scores above come from Check Point's original disclosure and have not yet been ratified by NVD.
The question worth sitting with is the checkpoint-trust-boundary one. The same persistence layer that makes a LangGraph agent stateful and useful, the layer the agent reads from every time it resumes a conversation, is the layer that turns a SQLi into RCE. Self-hosters who can answer yes to "is get_state_history() reachable from untrusted input, and is the checkpoint store writeable from anything I would not let run code on the agent host" can scope the rest of their response. Those who cannot answer that question yet have the actual triage work to do.