flawopen.com/Teardowns/cve-2026-71433-langgraph-store-namespace-boundary
LangGraph CVE-2026-71433: namespace सीमा रिसाव
LangGraph के Postgres और SQLite scoped reads namespace सीमा पार करके पड़ोसी tenant का डेटा दिखा सकते थे। दोनों checkpoint पैकेज को 3.1.1 पर अपडेट करें।
CVSS वेक्टर
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:N/A:Nमान लीजिए लाइब्रेरियन से “team” से शुरू होने वाले फ़ोल्डर माँगे गए। अगर सूची केवल शुरुआती अक्षर देखती है, तो “team2” भी मिल सकता है। LangGraph namespace लेबल को dot से जोड़ता था, लेकिन prefix खोज में dot को सीमा मानना ज़रूरी नहीं था। सुधार अब सटीक namespace या वास्तविक अगले segment की माँग करता है, इसलिए एक tenant का फ़ोल्डर दूसरे के साथ नहीं मिलता।
इस पेज के मुख्य शब्द
Namespace- लेबलों का tuple, जिससे LangGraph Store आइटम समूहित करता है। एप्लिकेशन इसे user या tenant सीमा के रूप में इस्तेमाल कर सकता है।
Prefix scope- एक namespace और उसके descendants पढ़ने का अनुरोध। सही मिलान segment सीमा का सम्मान करता है:
fooमेंfoo.childआता है, पड़ोसीfoobarनहीं। SQL `LIKE` pattern- टेक्स्ट pattern जिसमें
%किसी भी क्रम और_एक अक्षर से मेल खाता है। Namespace लेबल को शाब्दिक रखने के लिए इन चिह्नों को escape करना चाहिए। CWE-863- गलत authorization: Store ने ऐसे namespace के रिकॉर्ड लौटाए जिन्हें caller को पढ़ने की अनुमति नहीं थी।
फ्रेमवर्क मैपिंग
- इस गाइड में बताई गई कमजोरी के लिए CWE संदर्भ: CWE-863
मूल कारण विश्लेषण (Root Cause)
3.1.1 से पहले Postgres और SQLite checkpoint stores namespace tuples को dot से जोड़ते थे और search को LIKE '<namespace>%' से सीमित करते थे। LIKE namespace separator को नहीं समझता, इसलिए foo के लिए खोज पड़ोसी foobar से भी मेल खा सकती थी; वैध % और _ लेबल wildcard की तरह काम कर सकते थे। list_namespaces में prefix और suffix के ऐसे ही दोष थे। सामान्य scoped read पर्याप्त था; malformed input की जरूरत नहीं थी। यह केवल Postgres/SQLite Store के search और namespace-list read paths को प्रभावित करता है, जब एप्लिकेशन tenant isolation के लिए namespace पर निर्भर हो। get, put, और delete exact equality का उपयोग करते हैं और प्रभावित नहीं थे; InMemoryStore namespace elements की अलग-अलग तुलना करता है और वह भी प्रभावित नहीं था। सुधार exact equality या descendants से पहले dot अनिवार्य करता है, LIKE metacharacters को escape करता है, और namespace listing के लिए segment-aware patterns उपयोग करता है। SQLite में search, LIKE के ASCII case-insensitive व्यवहार से भी बचता है। Advisory में वास्तविक हमलों में शोषण का कोई प्रमाण नहीं बताया गया है। प्रभावित पैकेज 3.1.1 में ठीक किए गए।
CVE-2026-71433 के लिए परिनियोजन-पहुँच मैट्रिक्स
| परिनियोजन और namespace का स्वरूप | दस्तावेज़ित व्यवहार | जाँच की कार्रवाई |
|---|---|---|
| PostgresStore / AsyncPostgresStore या SqliteStore / AsyncSqliteStore का संस्करण 3.1.1 से पुराना हो और tenant अलगाव namespace पर निर्भर हो। | सीमित search या list_namespaces अनुरोध पड़ोसी namespace तक पहुँच सकता है, यदि लेबल का पाठ्य prefix समान हो (foo / foobar, 1 / 12) या उसमें % / _ हों। SQLite खोज ASCII अक्षरों के केवल बड़े-छोटे रूप के अंतर को भी समान मानती थी। | संबंधित checkpoint पैकेज को 3.1.1 या बाद के संस्करण में अपडेट करें। उत्पादन backend पर पड़ोसी prefix, wildcard, suffix और केवल case के अंतर की जाँच करें। |
| 3.1.1 से पुराना SQLite Store, जिसमें namespace लेबल केवल ASCII case में अलग हों। | कमज़ोर descendant खोज case-insensitive LIKE का उपयोग करती थी, जबकि exact operations case को अलग मानती थीं। | अपडेट करें और यदि लेबल case में अलग हो सकते हैं तो case-sensitivity regression test जोड़ें। |
% और _ के बिना निश्चित-लंबाई वाले UUID लेबल। | Advisory के अनुसार यह स्वरूप प्रभावित नहीं है: समान लंबाई वाले लेबल एक-दूसरे के prefix नहीं हो सकते। | पुष्टि करें कि हर namespace segment इस शर्त को पूरा करता है। यदि लंबाई बदल सकती है या wildcard आ सकते हैं, तो परिनियोजन को प्रभावित मानें। |
| InMemoryStore। | प्रभावित नहीं: यह namespace तत्वों की अलग-अलग तुलना करता है। | इस CVE के लिए अपडेट आवश्यक नहीं; फिर भी application boundary पर tenant ownership जाँचें। |
| LangSmith hosted परिनियोजन। | डिफ़ॉल्ट LANGGRAPH_STORE_BACKEND=python AsyncPostgresStore का उपयोग करता है और प्रभावित पैकेज होने पर दायरे में आता है। अलग grpc backend को समकक्ष सुधार मिला। | कॉन्फ़िगर backend और deployed version जाँचें; केवल उत्पाद के नाम से अनुमान लगाने के बजाय hosted rollout या package version की पुष्टि करें। |
हमले का चरण-दर-चरण प्रवाह
Store backend और labels जाँचें
Deployment में 3.1.1 से पहले का langgraph-checkpoint-postgres या langgraph-checkpoint-sqlite होना चाहिए और user या tenant अलग करने के लिए namespace पर निर्भर होना चाहिए। मिलते-जुलते prefixes या % और _ वाले labels सीमा को प्रभावित करते हैं।
सामान्य scoped read होता है
Authenticated application request foo जैसे namespace को खोजती है। विशेष payload की जरूरत नहीं; सामान्य namespace ही दोषपूर्ण matcher का input है।
Backend labels जोड़कर pattern मिलाता है
Store labels को dot से जोड़ता है और अंत में % वाले LIKE prefix का उपयोग करता है। Separator अनिवार्य न होने से foo, foobar से मेल खा सकता है; label के pattern characters भी परिणाम बढ़ा सकते हैं।
पड़ोसी namespace के आइटम लौट सकते हैं
यदि एप्लिकेशन namespace को tenant सीमा मानता है, तो search या listing किसी अन्य user के संग्रहीत आइटम लौटा सकती है। यह read-side confidentiality समस्या है, SQL injection या write access नहीं।
अपडेट करके isolation फिर जाँचें
लागू दोनों पैकेज को 3.1.1 या नए संस्करण में अपडेट करें। अलग-अलग test tenants से पड़ोसी prefixes, literal % और _ labels, suffix matching और SQLite case behavior जाँचें।
सोर्स कोड: कमज़ोर बनाम सुरक्षित कार्यान्वयन
कमज़ोर condition जुड़े हुए namespace से शुरू होने वाली हर string को descendant मानती है। सुधार exact-equality branch जोड़ता है और descendant segments से पहले literal dot अनिवार्य करता है; LIKE pattern में backslash, % और _ भी escape होते हैं। Upstream commit list_namespaces के prefix/suffix patterns को segment-aware matching से बदलता है और SQLite search भी समायोजित करता है। यह source excerpt है, पूरा module नहीं।
सोर्स अंश: libs/checkpoint-postgres/langgraph/store/postgres/base.py
def _prepare_batch_search_queries(op):
ns_condition = "TRUE"
ns_param = None
if op.namespace_prefix:
ns_condition = "store.prefix LIKE %s"
ns_param = (f"{_namespace_to_text(op.namespace_prefix)}%",)
return ns_condition, ns_param
def _escape_like_literal(text: str) -> str:
return text.replace("\\", "\\\\").replace("%", "\\%").replace("_", "\\_")
def _namespace_prefix_condition(namespace_prefix: tuple[str, ...]) -> tuple[str, tuple]:
path = _namespace_to_text(namespace_prefix)
condition = r"(store.prefix = %s OR store.prefix LIKE %s ESCAPE '\\')"
return condition, (path, f"{_escape_like_literal(path)}.%")
if op.namespace_prefix:
ns_condition, ns_param = _namespace_prefix_condition(op.namespace_prefix)
इंजीनियरिंग और सिस्टम सुरक्षा चेकलिस्ट
- ✓सभी installations में
langgraph-checkpoint-postgresऔरlanggraph-checkpoint-sqliteको 3.1.1 या नए संस्करण पर अपडेट करें। - ✓ऐसे regression cases जोड़ें जहाँ एक tenant label दूसरे का prefix हो, जैसे
fooऔरfoobar; हर search में केवल माँगा गया namespace और उसके descendants लौटने चाहिए। - ✓Production में प्रयुक्त ठीक उसी database backend पर
%,_, backslash और केवल case में अलग labels जाँचें। - ✓
list_namespacesके prefix, suffix, wildcard और empty-path व्यवहार जाँचें; दस्तावेज़ के अनुसार*को ठीक एक segment से मेल खाना चाहिए। - ✓Authorization checks application boundary पर रखें; opaque या fixed-format namespace IDs tenant ownership verification का विकल्प नहीं हैं।