every *2shell, one place
← all bugs

LangChain Core Serialization Injection (LangGrinch)

aka LangGrinch
Product
LangChain langchain-core
CVE
CVE-2025-68664
Disclosed
2025-12-23
CVSS
9.3
Auth
pre-auth
CISA KEV
no
Affected
langchain-core < 0.3.81 and >= 1.0.0, < 1.2.5
Fixed
0.3.81, 1.2.5

Summary

Reported by Yarden Porat and nicknamed LangGrinch, this flaw let attacker-controlled data masquerade as trusted LangChain objects when serialized and loaded again. It can leak environment secrets and instantiate LangChain classes with attacker parameters. Not strictly RCE by itself, but a critical primitive in agent pipelines that persist or stream LLM output.

Root cause

dumps()/dumpd() did not escape free-form dictionaries containing the reserved 'lc' key that marks serialized LangChain objects. Data such as LLM-produced metadata or additional_kwargs could therefore embed {'lc': 1, 'type': 'secret', ...} or constructor payloads that load() later treated as trusted. With secrets_from_env=True (the old default) this resolved environment secrets; constructor payloads could instantiate Serializable classes in trusted namespaces (e.g. Jinja2-backed prompt templates, which the fix now blocks by default).

Impact

Exfiltration of API keys from the environment and attacker-controlled object instantiation, potentially leading to code execution.

Public PoC

attacker_dict = {
    "user_data": {
        "lc": 1,
        "type": "secret",
        "id": ["OPENAI_API_KEY"]
    }
}
serialized = dumps(attacker_dict)  # Bug: does NOT escape the 'lc' key
loads(serialized)  # resolves the env secret

Source: GHSA-c67j-w6g6-q2cm

Detection

Audit for langchain-core versions below the fixed releases and for load()/loads() on data that originated from users or LLM output; search stored payloads for '"lc": 1' with type 'secret'.

Mitigation

Upgrade langchain-core, disable secrets_from_env, and only deserialize data you produced.

References