Now in early access, book a 30-minute demo →
← Back to blog AdvisoryHigh

LangChain unsafe deserialization - CVE-2026-44843

Secrets & Config Exposure·High·CVE-2026-44843·
Affected langchain-core >= 1.0.0 and <= 1.3.2, and langchain-core <= 0.3.84 (pip); fixed in 1.3.3 and 0.3.85

LangChain unsafe deserialization, tracked as CVE-2026-44843 (GHSA-pjwx-r37v-7724), is a High-severity flaw in the langchain-core package that lets untrusted serialized data instantiate arbitrary trusted objects. It is a CWE-502 deserialization-of-untrusted-data bug: when load() or loads() runs with allowed_objects="all", an attacker who controls structured input preserved in run data can inject a LangChain constructor dictionary that revives objects of the attacker's choosing. The flaw affects langchain-core >= 1.0.0 and <= 1.3.2 and langchain-core <= 0.3.84, and is fixed in 1.3.3 and 0.3.85. This advisory covers what happened, why an agent framework's deserialization path is a secrets-and-config-exposure problem, and how Anomity surfaces and governs the agents that depend on it.

What happened

LangChain is the core framework that most Python AI agents are built on, and langchain-core carries its serialization layer. That layer can turn LangChain objects into structured dictionaries and revive them later, which is how message history, run traces, and stored prompts survive across a run. The revival step is where the trust boundary breaks.

The deserialization mechanism lets untrusted LangChain-serialized constructor dictionaries instantiate arbitrary trusted objects when load() or loads() is called with allowed_objects="all". An attacker who controls structured input that is preserved in run data can inject a payload shaped like a constructor dict, and the revival logic will build the object it names rather than rejecting it as untrusted input.

{
  "lc": 1,
  "type": "constructor",
  "id": ["langchain_core", "messages", "ai", "AIMessage"],
  "kwargs": { }
}

A secondary flaw compounds the first: a bypass of the _is_lc_secret marker validation lets attacker-controlled dictionaries evade the escaping that is supposed to protect secret-marked fields during serialization round-trips, so a crafted value can survive the round-trip and reach the object-revival logic. Several common runtime surfaces reach the vulnerable path, including RunnableWithMessageHistory, astream_log(), and astream_events(version="v1"), which means data that flows back through message history or streamed run events can carry the payload into a permissive load call.

DetailValue
IdentifierCVE-2026-44843 (GHSA-pjwx-r37v-7724)
TypeDeserialization of untrusted data (CWE-502)
SeverityHigh
Packagelangchain-core (pip)
Affectedlangchain-core >= 1.0.0 and <= 1.3.2, and langchain-core <= 0.3.84
Fixed inlangchain-core 1.3.3 and 0.3.85
Triggerload()/loads() with allowed_objects="all"; reachable via RunnableWithMessageHistory, astream_log(), astream_events(version="v1")

Why this is an agentic-endpoint risk

LangChain is the core framework the AI-agent layer is built on, so a deserialization flaw in langchain-core is not confined to one service. The objects the revival logic can instantiate are the same objects that carry agent configuration: model clients, tool wrappers, and message history that reference API keys and connection settings. When untrusted serialized data can revive arbitrary trusted objects, the boundary between attacker input and trusted config collapses, which is why this sits in the Secrets and Config Exposure cluster rather than being treated as a generic library bug.

The exposure follows the data, not a single request. Deserialized objects come from run data, message history, and stored prompts, and any of those can be attacker-influenced in a multi-tenant agent, a shared conversation store, or a pipeline that replays saved traces. The _is_lc_secret bypass makes the secrets angle concrete: it undermines the escaping meant to keep secret-marked fields safe across round-trips, so a crafted config or stored message can carry a payload past the marker and into revival. That is a secrets-and-config-exposure problem first, and an RCE-adjacent one because arbitrary trusted objects are being constructed from untrusted input.

This is the same artifact-layer blind spot we track across the agent-framework cluster, including the sibling cases in LangChain prompt template injection - CVE-2026-40087, LangSmith SDK arbitrary file read - GHSA-f4xh-w4cj-qxq8, Langflow shareable playground RCE - CVE-2026-48519, and MLflow AI Gateway secrets exfiltration - CVE-2026-4035. It also rhymes with the pickle and object-revival RCE pattern seen in LightLLM pickle deserialization RCE - CVE-2026-26220 and vLLM prompt-embeds deserialization RCE - CVE-2025-62164. The framework is one node in a graph of AI artifacts, and you can't govern what you can't see, so fleet-wide inventory of every AI artifact is the precondition for scoping a deserialization flaw like this one.

How Anomity surfaces and governs it

Anomity inventories eight AI artifact types on every managed endpoint: AI agents, MCP servers, extensions, skills, plugins, secrets, hooks, and CLIs. For CVE-2026-44843 that means the LangChain-based agents on the endpoint, and the secrets and hooks around them, are catalogued so you can answer "which agents depend on an affected langchain-core build" from the fleet inventory instead of grepping requirements files by hand, and confirm whether they have moved to 1.3.3 or 0.3.85.

On agents that expose a hook, such as Claude Code PreToolUse, Anomity returns allow, deny, or log on each tool call before it runs. That is the enforcement point in runtime governance: a tool call that would load untrusted serialized data or drive an affected agent path can be denied or logged in line rather than discovered after arbitrary objects have already been revived. Anomity collects metadata only and redacts secrets on the endpoint, so the API keys and connection settings the _is_lc_secret bypass puts at risk never pass through Anomity, and are governed the same way described for secrets management for AI agents.

Every decision is written to a queryable 90-day audit trail. After a disclosure like this, that trail is what lets responders scope the event: which agents ran an affected build, when, and what serialized data they were asked to load. Anomity routes those decisions to SIEM, Slack, email, or Jira so the right team sees them in the tool they already use, producing the timeline and enforcement record described under outcomes.

Anomity complements your existing Network, EDR, DLP, and GRC controls rather than replacing them; it adds the agentic-endpoint layer those tools cannot see. See how it works and how Anomity compares for where it fits, and the AI security framework report for the governance model behind it.

What to check across your fleet

  • Resolve the actual langchain-core version behind every LangChain agent and treat 1.0.0 through 1.3.2, and anything at or below 0.3.84, as affected; upgrade to 1.3.3 or 0.3.85 or later.
  • Find every call to load() and loads() and remove allowed_objects="all" wherever the input is not fully trusted, restricting revival to an explicit allowlist of expected classes.
  • Audit the runtime surfaces that reach the vulnerable path, including RunnableWithMessageHistory, astream_log(), and astream_events(version="v1"), and confirm none deserialize attacker-influenced run data.
  • Trace where serialized LangChain objects originate: message history stores, saved run traces, and stored prompts that could carry untrusted constructor dictionaries into a load call.
  • Verify that secret-marked fields survive serialization round-trips with escaping intact, since the _is_lc_secret bypass can let attacker-controlled dictionaries evade it.
  • Enumerate which agents, CLIs, and MCP servers on each endpoint embed LangChain, using a fleet-wide AI artifact inventory, so no affected build is missed as a transitive dependency.
  • Confirm hook-based allow/deny/log enforcement is active on agents that drive LangChain, so a tool call that loads untrusted serialized data can be blocked before it runs.
  • Rotate any API keys or credentials referenced by LangChain configs that an untrusted deserialization path could have exposed, and record the rotation in your audit trail.

CVE-2026-44843 turns untrusted serialized data in run data, message history, and stored prompts into a way to revive arbitrary trusted objects and undercut the escaping that protects secret-marked config, which is exactly why the AI artifact layer needs its own inventory and enforcement. For the full cluster context, see the pillar on securing AI agent frameworks, and the related guidance on securing AI coding agents and CLIs. To see Anomity inventory your agents, govern tool calls at the hook, and keep a 90-day audit trail, request early access.

Frequently asked questions

What versions of langchain-core are affected by CVE-2026-44843?

The flaw affects langchain-core in two ranges: from 1.0.0 up to and including 1.3.2, and every release at or below 0.3.84. It is fixed in langchain-core 1.3.3 on the 1.x line and 0.3.85 on the 0.3.x line. Because langchain-core is a transitive dependency of most LangChain agent stacks, a service can be exposed without ever importing it directly, so pin and verify the resolved version rather than the top-level langchain package. Treat any endpoint or agent runtime that resolves langchain-core inside the affected ranges as vulnerable until it is upgraded to 1.3.3 or 0.3.85 or later.

How is CVE-2026-44843 actually triggered?

The deserialization path is reached when load() or loads() is called with allowed_objects set to "all". In that configuration a LangChain-serialized constructor dictionary can instantiate arbitrary trusted objects, so an attacker who controls structured input preserved in run data can inject a payload shaped like a constructor dict. Runtime surfaces that reach the vulnerable path include RunnableWithMessageHistory, astream_log(), and astream_events(version="v1"). A secondary flaw bypasses the _is_lc_secret marker validation, letting attacker-controlled dictionaries evade escaping during serialization round-trips and reach the object-revival logic. The practical trigger is untrusted serialized data flowing back through message history or run data into a permissive load call.

Why does this belong in the Secrets and Config Exposure cluster?

The objects LangChain revives during deserialization are the same objects that carry agent configuration and credential material: model clients, tool wrappers, and message history that reference API keys and connection settings. The _is_lc_secret bypass is what makes this a secrets problem rather than only a code-execution one, because it undermines the escaping that is supposed to keep secret-marked fields safe across serialization round-trips. When untrusted serialized data in a config, a stored prompt, or a run record can revive arbitrary trusted objects, the boundary between attacker input and trusted configuration disappears, which is precisely the exposure this cluster tracks.

How does Anomity help when an agent framework like LangChain is vulnerable?

Anomity treats the LangChain runtime as an AI artifact on the endpoint, so it inventories the agents that depend on langchain-core alongside the secrets, hooks, and CLIs around them. On agents that expose a hook, such as Claude Code PreToolUse, Anomity returns allow, deny, or log on each tool call before it runs, so a call that would load untrusted serialized data or reach an affected build can be denied or logged in line. Every decision lands in a queryable 90-day audit trail, and Anomity collects metadata only and redacts secrets on the endpoint, so credential values the deserialization flaw might touch never pass through Anomity.

Ask AI about Anomity
ChatGPT Claude Perplexity Google AI Grok