
मुझे langchain में एक ज़ीरो-डे कमज़ोरी मिली — यहाँ बताया गया है कि यह कैसे हुआ
AI के सबसे लोकप्रिय फ्रेमवर्क में से एक में एक भूला हुआ legacy API कैसे चुपचाप लाखों एप्लिकेशनों को arbitrary file reads के लिए उजागर कर रहा था।
एक खास एहसास होता है जब proof-of-concept पहली कोशिश में काम कर जाता है। बिल्कुल उत्साह नहीं — बल्कि एक धीमी, असहज अहसास कि कुछ वास्तविक घटित हुआ है। यही महसूस हुआ जब मैंने अपना test config load_prompt_from_config() के खिलाफ चलाया और एक फ़ाइल की सामग्री को देखा जिसे पढ़ने का उसे कोई अधिकार नहीं था — वह सीधे मेरे टर्मिनल पर प्रिंट हो गई।
यह CVE-2026-34070 की कहानी है: langchain-core में एक path traversal vulnerability, जिसे अब version 1.2.22 में पैच किया गया है।
अगर आपने पिछले कुछ वर्षों में AI के साथ कुछ भी बनाया है, तो आपने लगभग निश्चित रूप से LangChain को छुआ है। यह आधुनिक AI स्टैक का connective tissue है — वह फ्रेमवर्क जो language models, vector stores, tools, और prompt management को सुसंगत एप्लिकेशनों में जोड़ता है। GitHub पर 130k+ stars और छोटे weekend projects से लेकर enterprise deployments तक हर जगह adoption के साथ, यहाँ एक vulnerability सीमित नहीं रहती।
मैं prompts subsystem का code review कर रहा था जब मेरी नज़र एक चीज़ पर पड़ी: langchain_core/prompts/loading.py नामक एक module। यह deserialized config dictionaries से सीधे निकाले गए मानों के आधार पर disk से files लोड कर रहा था। कोई validation नहीं। कोई path sanitization नहीं। बस ।
open(path)मैं पढ़ता रहा।
तीन internal functions इसके केंद्र में थीं:
_load_template() — template_path, suffix_path, और prefix_path द्वारा संदर्भित files को पढ़ता है_load_examples() — examples key द्वारा संदर्भित files को पढ़ता है जब यह एक string होती है_load_few_shot_prompt() — example_prompt_path द्वारा संदर्भित files को पढ़ता हैFile-extension checks मौजूद थे। Templates के लिए .txt। Examples के लिए .json, .yaml, .yml। लेकिन उन paths को absolute (/etc/passwd) या traversal-based (../../../../home/user/.ssh/) होने से रोकने वाला कुछ भी नहीं था। Extension filter ने सुरक्षा का झूठा एहसास दिया — इसका मतलब सिर्फ यह था कि attacker को सही extension चुननी थी, न कि attack अवरुद्ध था।
ये functions दो public-facing APIs के माध्यम से पहुंच योग्य हैं: load_prompt() और load_prompt_from_config()।
सबसे सरल संस्करण इस तरह दिखता था:
from langchain_core.prompts.loading import load_prompt_from_config
config = {
"_type": "prompt",
"template_path": "/tmp/secret.txt",
"input_variables": [],
}
prompt = load_prompt_from_config(config)
print(prompt.template) # /tmp/secret.txt की सामग्री, साफ-साफ प्रिंट हुई
बस इतना ही। Absolute path पास करें, file contents को PromptTemplate में लिपटा हुआ वापस पाएं। कोई authentication नहीं। कोई विशेष privileges नहीं। यदि आप config dict को प्रभावित कर सकते हैं, तो आप files पढ़ सकते हैं।
Directory traversal उतनी ही सफाई से काम करती थी:
config = {
"_type": "prompt",
"template_path": "../../etc/secret.txt",
"input_variables": [],
}
JSON/YAML variant उन files के प्रकारों के कारण अधिक खतरनाक था जिन तक यह पहुंच सकता था:
config = {
"_type": "few_shot",
"examples": "../../../../.docker/config.json",
"example_prompt": {
"_type": "prompt",
"input_variables": ["input", "output"],
"template": "{input}: {output}",
},
"prefix": "",
"suffix": "{query}",
"input_variables": ["query"],
}
prompt = load_prompt_from_config(config)
.docker/config.json में आपके Docker Hub credentials होते हैं। ~/.azure/accessTokens.json में आपके Azure tokens होते हैं। Kubernetes manifests, CI/CD configs, internal application settings — सही extension वाली कोई भी चीज़ filesystem पर कहीं भी fair game थी।
CVSS score 7.5 High आया, जिसका vector AV:N/AC:L/PR:N/UI:N था — network-accessible, low complexity, कोई privileges नहीं, कोई user interaction आवश्यक नहीं।
Score 9+ से नीचे सीमित है क्योंकि file-extension check कुछ हद तक सीमित करता है कि कौन सी files पढ़ी जा सकती हैं। लेकिन 7.5 फिर भी कुछ deployment patterns में real-world impact को कम आंकता है।
सोचिए यह production में कहाँ पहुंचता है:
load_prompt_from_config() में पास करता है, तो हर user एक संभावित attacker है।उन environments में, "file extension द्वारा सीमित" limitation बहुत कम मायने रखती है। एक attacker बस उन files को target कर सकता है जिनके बारे में वह जानता है कि सही extension के साथ मौजूद हैं। एक सामान्य cloud instance पर: requirements.txt, config.yaml, .env.yaml, .json extensions वाली mounted secret files — सूची लंबी है।
प्रभावित functions को advisory में "undocumented legacy APIs" के रूप में वर्णित किया गया है। वे वर्तमान langchain_core.load serialization system (dumpd/dumps/load/loads) से पहले के हैं, जो allowlist-based model का उपयोग करता है और filesystem reads नहीं करता।
नए APIs मौजूद हैं। वे बेहतर हैं। लेकिन पुराना code कभी साफ नहीं किया गया — यह बस वहीं पड़ा रहा, पहुंच योग्य, बिना किसी validation के, इंतज़ार करता हुआ।
यह एक pattern है जिस पर ध्यान देने योग्य है। तेज़ी से बढ़ते open-source projects में, विशेष रूप से जो LangChain जितनी तेज़ी से बढ़े, technical debt कोनों में जमा होती है। Legacy code जो "वास्तव में users के लिए कभी intended नहीं था" को primary API surface के समान scrutiny नहीं मिलती। लेकिन यह अभी भी callable है। यह अभी भी package में है। और यदि यह disk से files पढ़ता है, तो यह एक संभावित vulnerability है।
Patch langchain-core 1.2.22 में आया। Fix path validation जोड़ता है जो किसी भी file को खोलने से पहले absolute paths और .. traversal sequences दोनों को अस्वीकार करता है। एक escape hatch — allow_dangerous_paths=True — उन applications के लिए उपलब्ध है जिन्हें वास्तव में trusted paths से पढ़ने की आवश्यकता है, इस स्पष्ट स्वीकृति के साथ कि caller risk में opt-in कर रहा है।
Legacy APIs को भी इस release के साथ औपचारिक रूप से deprecated कर दिया गया है। उन्हें 2.0.0 में पूरी तरह से हटा दिया जाएगा। यदि आप कहीं भी load_prompt() या load_prompt_from_config() का उपयोग कर रहे हैं, तो breaking change की प्रतीक्षा करने के बजाय अभी langchain_core.load equivalents पर migrate करें।
तुरंत अपडेट करें:
pip install --upgrade langchain-core
सत्यापित करें कि आप 1.2.22 या नए पर हैं:
python -c "import langchain_core; print(langchain_core.__version__)"
यदि आप LangChain पर निर्माण कर रहे हैं, तो एक त्वरित audit चलाने लायक है:
load_prompt और load_prompt_from_config खोजें। यदि वे दिखाई देते हैं, तो जाँचें कि उन्हें क्या पास किया जा रहा है।.txt, .json, या .yaml extensions वाली कौन सी files मौजूद हैं और उनमें क्या है।AI infrastructure में Security bugs अधिक मायने रखने वाले हैं, कम नहीं, क्योंकि ये systems अधिक संवेदनशील workloads संभालते हैं। LangChain की टीम ने अच्छी प्रतिक्रिया दी — fix साफ है, deprecation path स्पष्ट है, और advisory documentation संपूर्ण है।
लेकिन यह एक अच्छा अनुस्मारक है कि AI application का attack surface सिर्फ model नहीं है। यह stack की हर library है, हर legacy function जो कभी साफ नहीं हुआ, हर जगह जहाँ "user शायद यहाँ untrusted input पास नहीं करेगा" एक assumption निकला, गारंटी नहीं।
Code पढ़ें। विशेष रूप से पुराने हिस्से।
CVE-2026-34070 इस vulnerability को assigned किया गया था। पूर्ण advisory LangChain GitHub Security Advisory पर उपलब्ध है।