This guide details the method that actually works: structural restriction to SELECT, closed whitelist of functions, mandatory row cap, and locking of the queried schema. Each step relies on the validator actually implemented in Aurabase's NL2SQL engine, a capability of its native AI built into thebackend, not a third-party service thrown together after the fact. If the subject is new to you, our overview of NL2SQL lays the foundations, and the step-by-step tutorial shows how to build the complete endpoint.
अनिवार्य है
- प्रॉम्प्ट इंजीनियरिंग ("केवल चयन उत्पन्न करता है") सुरक्षा जांच नहीं है: एक मॉडल मतिभ्रम कर सकता है, एक अस्पष्ट प्रश्न द्वारा निर्देशित हो सकता है, या बस निर्देशों को अनदेखा कर सकता है।
- जो सत्यापन होता है वह संरचनात्मक होता है: एक पार्सर अनुरोध के सिंटैक्टिक ट्री (एएसटी) का निर्माण करता है और डिफ़ॉल्ट रूप से किसी भी चीज़ को अस्वीकार कर देता है जो स्पष्ट रूप से अधिकृत नहीं है।
- चार ठोस परतें जोखिम को सीमित करती हैं: सख्त चयन (न तो सबक्वेरी, न ही सीटीई, न ही यूनियन), दस कार्यों की बंद श्वेतसूची,
LIMITअनिवार्य और कैप्ड, सिस्टम कैटलॉग और गैर-किरायेदार स्कीमा तक अवरुद्ध पहुंच। - क्वेरी की गई स्कीमा सर्वर से आनी चाहिए, क्लाइंट अनुरोध में किसी फ़ील्ड से नहीं: अन्यथा कोई भी कॉल करने वाले को सत्यापन को बायपास करने के लिए अपनी स्वयं की स्कीमा प्रदान करने से नहीं रोकता है।
- ऑराबेस में, इस सत्यापनकर्ता (रस्ट क्रेट
sqlparser) का परीक्षण कोड में दर्ज प्रतिकूल मामलों के साथ किया जाता है:FILTERमें, इंट्रा-एग्रीगेटORDER BYमें, याOFFSETमें छिपे हुए निषिद्ध कार्य।
सिस्टम प्रॉम्प्ट में कोई निर्देश किसी चीज़ को ब्लॉक क्यों नहीं करता?
एक सिस्टम प्रॉम्प्ट जो कहता है कि "केवल चयनित क्वेरी उत्पन्न करता है" एक प्राथमिकता है, बाधा नहीं। मॉडल अधिकांश समय इसका सम्मान करता है क्योंकि उसे निर्देशों का पालन करने के लिए प्रशिक्षित किया गया है, इसलिए नहीं कि कोई तकनीकी बाधा उसे शारीरिक रूप से कुछ और लिखने से रोकती है। विफलता के दो वर्ग इस आत्मविश्वास को उत्पादन में अपर्याप्त बनाते हैं।
पहला सवाल से ही आता है. एक उपयोगकर्ता, गलत इरादे से या बस अपने फॉर्मूलेशन में रचनात्मक, प्रश्न को इस तरह से निर्देशित कर सकता है कि मॉडल को एसक्यूएल की ओर धकेल दिया जाए जो उन्हें नहीं लिखना चाहिए था: एक संवेदनशील तालिका में शामिल होना, एक फिल्टर जो अपेक्षित तर्क को दरकिनार करता है, एक सिस्टम फ़ंक्शन कॉल। मॉडल एक वैध प्रश्न और उसमें हेरफेर करने के लिए डिज़ाइन किए गए प्रश्न के बीच अंतर नहीं करता है।
दूसरे के लिए किसी द्वेष की आवश्यकता नहीं है। एक मॉडल एक तालिका के नाम को मतिभ्रम कर सकता है, संकेत के लिए पूछे गए LIMIT को भूल सकता है, या एक बड़ी तालिका पर बिना किसी प्रतिबंध के SELECT * उत्पन्न कर सकता है। परिणाम दोनों मामलों में समान है: संभावित रूप से महंगा या दखल देने वाला एसक्यूएल, जो प्रॉम्प्ट फ़िल्टर को पार कर चुका है और वास्तविक डेटाबेस के विरुद्ध निष्पादित होने वाला है।
सिस्टम प्रॉम्प्ट उपयोगी रहता है, यह अधिकांश समय मॉडल को सही परिणाम की ओर निर्देशित करता है। लेकिन "नो एक्सेस" का संकेत किसी ऐसे व्यक्ति को नहीं रोकता है जो पढ़ना नहीं जानता है, या जो इसे अनदेखा करने का निर्णय लेता है। आपको पीछे एक बंद दरवाज़ा चाहिए, न कि केवल सामने एक पैनल।
जेनरेट किए गए SQL को सिंटैक्स ट्री में पार्स करें, कभी भी रॉ स्ट्रिंग में नहीं
रक्षा की पहली पंक्ति लक्ष्य बोली के लिए वास्तविक पार्सर के साथ मॉडल द्वारा उत्पादित एसक्यूएल को पार्स करना है, फिर परिणामी संरचना को मान्य करना है, न कि कच्चे पाठ को। वर्ण स्ट्रिंग ("ड्रॉप", "डिलीट", ";") में निषिद्ध शब्दों की खोज को तुच्छ रूप से नजरअंदाज कर दिया गया है: अलग-अलग मामले, कीवर्ड के बीच में डाली गई टिप्पणी, टाइप किए गए उद्धरण चिह्न। एक सिंटैक्स ट्री स्पष्ट रूप से वर्णन करता है कि क्वेरी वास्तव में क्या करती है।
ऑराबेस इस चरण को रस्ट क्रेट sqlparser और इसकी बोली PostgreSqlDialectके साथ लागू करता है। पार्सिंग से पहले भी, पहला लेक्सिकल फ़िल्टर दो निर्माणों को अस्वीकार कर देता है जिन्हें पेड़ में एक बार सही ढंग से तर्क करना मुश्किल होता है: डॉलर-उद्धरण ($$...$$), जो एक स्ट्रिंग में मनमानी सामग्री छुपा सकता है, और बहु-पंक्ति टिप्पणियां (/* */), जो एक निर्देश के वास्तविक अंत को छुपा सकता है।
मल्टी-स्टेटमेंट की यह अस्वीकृति अकेले SQL इंजेक्शन के सबसे प्रसिद्ध रूप को स्टैकिंग द्वारा ब्लॉक कर देती है: SELECT * FROM users; DROP TABLE users;--। पार्सर केवल एक कार्रवाई योग्य निर्देश लौटाता है, दूसरे तक कभी नहीं पहुंचा जाता है, चाहे वह मूल प्रश्न में कैसे भी लिखा गया हो।
संरचनात्मक रूप से एक साधारण चयन तक सीमित रखें
एक बार पेड़ प्राप्त हो जाने के बाद, व्यापक सत्यापन केवल एक प्रकार के रूट नोड, एक क्वेरी (Statement::Query) को स्वीकार करना है, और बाकी सभी को अस्वीकार करना है: INSERT, UPDATE, DELETE, DROP, CREATE, ALTER। यह अब एक त्वरित निर्देश नहीं है, यह पार्स की गई वस्तु के प्रकार पर एक शर्त है, जिसे प्रश्न का कोई भी कुशल सूत्रीकरण टाल नहीं सकता है।
चयन के भीतर भी, कई निर्माण खतरनाक बने हुए हैं और अपनी स्पष्ट अस्वीकृति के पात्र हैं:
| निर्माण अस्वीकृत | यह खतरनाक क्यों है? |
|---|---|
| सीटीई / साथ | अंतिम चयन से पहले अतिरिक्त अनपेक्षित तर्क को श्रृंखलाबद्ध कर सकते हैं। |
| उपश्रेणी, संघ/प्रतिच्छेद/छोड़कर | एक प्रश्न एक ही प्रश्न में क्या कर सकता है इसके सतह क्षेत्र का विस्तार करता है। |
| चयन करें...इसमें | एक तालिका बनाता है: पढ़ने के रूप में लिखना। |
| अद्यतन हेतु/साझा करने हेतु | ताले लगाना, उत्पादन यातायात के साथ विवाद का जोखिम। |
| तालिका फ़ंक्शन (जेनरेट_सीरीज़, pg_read_file...) | मांग पर उत्पन्न लाइनों के माध्यम से सिस्टम तक पहुंच या सेवा से इनकार। |
रिपॉजिटरी से लिया गया एक परीक्षण मामला अंतिम बिंदु को ठोस रूप से दर्शाता है: SELECT * INTO backup FROM users को अस्वीकार कर दिया गया है, भले ही इसमें न तो दृश्यमान लेखन कीवर्ड और न ही संदिग्ध फ़ंक्शन शामिल है। अनुरोध का फ़ॉर्म उसे अयोग्य घोषित करने के लिए पर्याप्त है.
फ़ंक्शन श्वेतसूची, कालीसूची नहीं
निषिद्ध कार्यों की एक ब्लैकलिस्ट (pg_sleep, pg_read_file, dblink...) के लिए प्रत्येक खतरनाक फ़ंक्शन का एक-एक करके अनुमान लगाने की आवश्यकता होती है, जबकि पोस्टग्रेज़ उनमें से कई सौ को उजागर करता है। श्वेतसूची प्रमाण के बोझ को उलट देती है: केवल दस कार्य अधिकृत हैं, count, sum, avg, min, max, lower, upper, coalesce, date_trunc, now। बाकी सब कुछ डिफ़ॉल्ट रूप से अस्वीकृत है, जिसमें एक वैध सुविधा भी शामिल है जिसे अभी तक किसी ने जोड़ने के बारे में नहीं सोचा है।
एक एकल सत्यापन पास हमेशा पर्याप्त नहीं होता है. पेड़ का एक संरचनात्मक ट्रैवर्सल इसके प्रवेश बिंदुओं को एक-एक करके सूचीबद्ध करता है (प्रक्षेपण, कहां, शामिल हों, समूह द्वारा...), और एक को भूलना आसान है: एक निषिद्ध फ़ंक्शन को FILTER (WHERE pg_sleep(10) IS NOT NULL)क्लॉज में, इंट्रा-एग्रीगेट ORDER BY (sum(id ORDER BY pg_sleep(10))) में, WITHIN GROUP, DISTINCT ON, या OFFSETमें छुपाया जा सकता है।
इसलिए ऑराबेस सत्यापनकर्ता एक दूसरा संपूर्ण पास जोड़ता है, जो संरचनात्मक पथ से स्वतंत्र रूप से पेड़ में सभी अभिव्यक्तियों से होकर गुजरता है, चाहे वे कहीं भी हों। यह गहराई से एक कल्पित बचाव है: यदि पहला पास कोई मामला चूक जाता है, तो दूसरा पकड़ लेता है।
लौटाई गई पंक्तियों को बांधें: LIMIT अनिवार्य और सीमित
SELECT * अधिकृत रहता है, यह डेटा माइनिंग के लिए उपयोगी है। जोखिम स्टार नहीं है, यह एक मॉडल द्वारा लिखी गई क्वेरी पर छत की अनुपस्थिति है: एक खराब तरीके से तैयार किया गया प्रश्न मेमोरी लागत और प्रतिक्रिया समय के साथ एक पूरी तालिका को वापस ला सकता है।
ऑराबेस एक सरल और पारदर्शी नियम लागू करता है। यदि जेनरेट किए गए SQL में LIMITनहीं है, तो सर्वर एक जोड़ता है (डिफ़ॉल्ट रूप से 100 लाइनें, सिस्टम प्रॉम्प्ट में मॉडल के लिए घोषित मूल्य)। यदि SQL हार्ड कैप (डिफ़ॉल्ट रूप से 1000 पंक्तियाँ) से परे LIMIT का अनुरोध करता है, तो क्वेरी को चुपचाप कम करने के बजाय स्पष्ट रूप से अस्वीकार कर दिया जाता है। दोनों मान सर्वर साइड (AI_NL2SQL_DEFAULT_LIMIT, AI_NL2SQL_MAX_LIMIT) पर कॉन्फ़िगर करने योग्य हैं, और यदि गलती सीमा से अधिक हो जाती है तो सर्वर प्रारंभ करने से भी इनकार कर देता है।
चुपचाप पीछे हटने के बजाय इनकार करने का सीधा हित है: बिना कहे लागू की गई अधिकतम सीमा कॉल करने वाले को यह भ्रम देगी कि उसके अनुरोध का सम्मान किया गया है, जबकि परिणाम उसे जाने बिना ही काट दिया जाएगा। limit_injected हमेशा कहता है कि मान मॉडल या सर्वर से आता है।
स्कीमा तक पहुंच लॉक करें: सिस्टम कैटलॉग और क्रॉस-स्कीमा
दो अलग-अलग लीक से वास्तविक डेटाबेस से जुड़े एनएल2एसक्यूएल इंजन को खतरा है: पोस्टग्रेज सिस्टम कैटलॉग तक पहुंच, और एक स्कीमा तक पहुंच जो कॉलर से संबंधित नहीं है। दोनों ही सत्यापन पर रोक लगाते हैं, चाहे किसी भी आरएलएस नीति को डाउनस्ट्रीम में रखा गया हो।
pg_catalog हमेशा search_pathका हिस्सा होता है, जिसका अर्थ है कि pg_authid या pg_stat_activity जैसा अयोग्य नाम बिना किसी उपसर्ग के सीधे इस तक पहुंच बनाता है। ऑराबेस सत्यापनकर्ता pg_से शुरू होने वाले किसी भी नाम, साथ ही information_schema और आंतरिक स्कीमा aura_consoleको ब्लॉक कर देता है, चाहे वह योग्य हो या नहीं।
दो-घटक नाम (schema.table) पर, केवल कॉलिंग प्रोजेक्ट की स्कीमा की अनुमति है, कोई अन्य मान अस्वीकार कर दिया गया है। तीन या अधिक घटकों वाला नाम स्वचालित रूप से अस्वीकार कर दिया जाता है। उत्पन्न क्वेरी स्तर पर यह सीमाबहु-किरायेदार अलगावपर हमारे लेख में विस्तृत डेटाबेस स्तर अलगाव के अतिरिक्त है: एक जेनरेट किए गए SQL को किसी अन्य स्कीमा को लक्षित करने से रोकता है, दूसरा कनेक्शन को दूसरे डेटाबेस तक पहुंचने से रोकता है। कोई भी दूसरे का स्थान नहीं लेता।
क्लाइंट को कभी भी पूछे गए स्कीमा को फिर से परिभाषित न करने दें
किसी भी NL2SQL API के इंतजार में एक अलग जाल बिछा रहता है जो क्लाइंट की क्वेरी में अनुमत स्कीमा या तालिकाओं का वर्णन करने वाले पैरामीटर को स्वीकार करता है। यदि इसी पैरामीटर का उपयोग प्रॉम्प्ट बनाने और आउटपुट एसक्यूएल को मान्य करने के लिए किया जाता है, तो एक कॉलर इस बारे में झूठ बोल सकता है कि क्या अनुमति है, और सत्यापन तब डेटाबेस की वास्तविकता के बजाय इस झूठ के खिलाफ मान्य होता है।
ऑराबेस प्रत्येक कॉल पर वास्तविक प्रोजेक्ट बेस स्कीमा का आत्मनिरीक्षण करता है, प्रदर्शन के लिए एक छोटे से तीस-सेकंड कैश के साथ, और अनुरोध निकाय में भेजे गए किसी भी schema, allowed_schema, या schema_context फ़ील्ड को स्वीकार करने और फिर इसे चुपचाप ओवरराइट करने के बजाय स्पष्ट रूप से अस्वीकार (400 त्रुटि) करता है। अंतर मायने रखता है: एक क्षेत्र जिसे स्वीकार किया जाता है फिर अनदेखा कर दिया जाता है वह नियंत्रण का भ्रम देता है जो अस्तित्व में नहीं है; एक अस्वीकृत क्षेत्र इसे तुरंत कहता है।
उत्पादन से पहले अपनी स्वयं की NL2SQL पाइपलाइन का ऑडिट करें
चाहे आप ऑराबेस का उपयोग करें या जेनेरिक एलएलएम के शीर्ष पर अपनी खुद की पाइपलाइन बनाएं, निम्नलिखित बिंदु वह कवर करते हैं जो अक्सर छूट जाता है।
यदि आप सत्यापनकर्ता स्वयं लिखते हैं
- अपनी सटीक बोली के लिए वास्तविक पार्सर के साथ एसक्यूएल को पार्स करें, कभी भी स्ट्रिंग में पैटर्न मिलान के साथ नहीं।
- एक डिफ़ॉल्ट अस्वीकृति को अपनाएं: किसी भी प्रकार के नोड, स्पष्ट रूप से अधिकृत नहीं किए गए किसी भी फ़ंक्शन को अस्वीकार कर दिया जाना चाहिए, न कि केवल पहले से पहचाने गए खतरनाक मामलों को।
- प्रति क्वेरी केवल एक कथन स्वीकार करें, स्टैकिंग क्वेरी के विरुद्ध यह सबसे सरल अस्वीकृति है।
- केवल स्पष्ट मामलों के साथ ही नहीं, वास्तविक प्रतिकूल मामलों (फ़िल्टर में, इंट्रा-एग्रीगेट ऑर्डर बाय में, OFFSET में निषिद्ध फ़ंक्शन) के साथ सत्यापनकर्ता का परीक्षण करें।
- सब कुछ के बावजूद, अपेक्षित स्कीमा पर कम विशेषाधिकारों के साथ पोस्टग्रेज भूमिका के साथ मान्य एसक्यूएल को निष्पादित करें: सत्यापनकर्ता क्वेरी के रूप को सीमित करता है, भूमिका यह सीमित करती है कि यदि कोई मामला आपसे बच गया है तो वह भौतिक रूप से क्या हासिल कर सकता है।
यदि आप किसी तृतीय-पक्ष NL2SQL ढांचे का मूल्यांकन कर रहे हैं
- स्पष्ट रूप से पूछें कि क्या सत्यापन संरचनात्मक (एएसटी) है या केवल एक त्वरित निर्देश है: उत्तर सब कुछ बदल देता है।
- जांचें कि लाइन कैप डिफ़ॉल्ट रूप से लागू की गई है, न कि इसे केवल आपके खर्च पर सर्वोत्तम अभ्यास के रूप में प्रलेखित किया गया है।
- जांचें कि क्या सत्यापन के लिए उपयोग की जाने वाली स्कीमा एपीआई क्लाइंट द्वारा प्रदान की जा सकती है, जो ऊपर वर्णित दोष को फिर से खोल देगी।
- चुनने से पहले इस विशिष्ट मानदंड पर कई टूल की तुलना करें: NL2SQL टूल की हमारी तुलना विवरण देती है कि 2026 में उपलब्ध दृष्टिकोणों में क्या अंतर है।
सत्यापनकर्ता जोखिम कम करता है, यह आरएलएस को प्रतिस्थापित नहीं करता है
एक ठोस एएसटी सत्यापनकर्ता स्रोत पर जोखिम को कम करता है: आपके डेटाबेस तक पहुंचने वाले SQL का पहले से ही एक ज्ञात और परिबद्ध रूप होता है। हालाँकि, यह आपकी संवेदनशील तालिकाओं पर आरएलएस नीतियों को प्रतिस्थापित नहीं करता है, जो यह तय करती हैं कि किसी दिए गए उपयोगकर्ता को कौन सी पंक्तियाँ देखने का अधिकार है। दो परतें अलग-अलग प्रश्नों का उत्तर देती हैं: सत्यापनकर्ता उत्पन्न क्वेरी के रूप को सीमित करता है, आरएलएस उस डेटा को सीमित करता है जिसे वह किसी विशिष्ट उपयोगकर्ता के लिए वापस कर सकता है। दोनों को सक्रिय रखें, भले ही एक दूसरे के साथ अनावश्यक लगे।
NL2SQL covers structured questions about your tables. For questions about unstructured content, documents, notes, tickets, Aurabase's native RAG follows a comparable security logic, detailed in our RAG pipeline tutorial on pgvector.