एक AGI बनाएंएडवांस्डपाठ 667 मिनट का पाठ

एग्ज़ीक्यूटर को एक असली sandbox बनाना

ट्यूटोरियल का एग्ज़ीक्यूटर आपकी मशीन पर आपके क्रेडेंशियल्स के साथ हमलावर द्वारा प्रभावित किया जा सकने वाला कोड चलाता है। इससे पहले कि यह आपकी किसी ज़रूरी चीज़ को छुए, यहाँ बताया गया है कि क्या बदलना होगा।

पाठ वीडियो में

60 सेकंड में

एग्ज़ीक्यूटर को एक असली sandbox बनाना

ट्यूटोरियल का एग्ज़ीक्यूटर आपकी मशीन पर आपके क्रेडेंशियल्स के साथ हमलावर द्वारा प्रभावित किया जा सकने वाला कोड चलाता है। इससे पहले कि यह आपकी किसी ज़रूरी चीज़ को छुए, यहाँ बताया…

1/6
आसान शब्दों में
रोबोट को अपनी रसोई में खाना पकाने देना ठीक है। लेकिन खिड़की से किसी अजनबी द्वारा रेसिपी चिल्लाए जाने पर उसे अपनी रसोई में पकाने देना ठीक नहीं है।
Module 64 का run_python_code एक काम की चीज़ करता है — यह क्रैश होने पर पैरेंट को बंद होने से रोकता है। लेकिन यह वह काम नहीं करता जिसका इसका नाम वादा करता है। इसे एक असली sandbox की ज़रूरतों के सामने रखकर देखें:
प्रॉपर्टीsubprocessअगर मौजूद न हो तो इसका क्या मतलब है
क्रैश होने पर भी पैरेंट बचा रहता है✓—
समय सीमा✓ (timeout=10)एक अनियंत्रित लूप एजेंट को अटका (hang) देता है
फ़ाइलसिस्टम आइसोलेशन✗यह ~/.ssh, ~/.aws, आपका सोर्स कोड पढ़ सकता है
नेटवर्क आइसोलेशन✗यह आपकी फ़ाइलों को कहीं भी POST कर सकता है
क्रेडेंशियल आइसोलेशन✗यह आपके सभी एनवायरनमेंट वेरिएबल्स को इनहेरिट कर लेता है
मेमोरी / CPU सीमाएँ✗कोड की एक लाइन पूरी मशीन को थका (exhaust) सकती है
कोई पर्सिस्टेंस नहीं✗यह पीछे एक cron एंट्री छोड़ सकता है
ख़तरा
इन सात में से चार चीज़ें गायब हैं, और जो चार गायब हैं, वही सबसे ज़्यादा मायने रखती हैं। अगर लक्ष्य (goal) किसी यूज़र, वेब पेज, टिकट, या आपके अपने कीबोर्ड के अलावा कहीं और से आया है, तो आप किसी अजनबी से प्रभावित टेक्स्ट को, अपने क्रेडेंशियल्स के साथ, अपनी मशीन पर चला रहे हैं। यह वही घातक तिकड़ी (lethal trifecta - Module 11) है जिसे एक फ़ीचर के रूप में लागू कर दिया गया है।

न्यूनतम व्यावहारिक (minimum viable) असली sandbox

executor.py — container isolationpython
import subprocess
import tempfile
import os

IMAGE = "python:3.12-slim"

def run_python_code(code_string, timeout=10):
    """Run untrusted code in a disposable container with no network."""
    with tempfile.TemporaryDirectory() as workdir:
        path = os.path.join(workdir, "main.py")
        with open(path, "w") as f:
            f.write(code_string)

        try:
            result = subprocess.run(
                [
                    "docker", "run",
                    "--rm",                      # destroyed when it exits
                    "--network", "none",         # no exfiltration path at all
                    "--memory", "256m",
                    "--cpus", "0.5",
                    "--pids-limit", "64",        # blocks fork bombs
                    "--read-only",               # immutable root filesystem
                    "--tmpfs", "/tmp:size=16m",
                    "--cap-drop", "ALL",
                    "--security-opt", "no-new-privileges",
                    "--user", "65534:65534",     # nobody
                    "-v", f"{workdir}:/work:ro", # only this file, read-only
                    "-w", "/work",
                    IMAGE,
                    "timeout", str(timeout), "python", "main.py",
                ],
                capture_output=True,
                text=True,
                timeout=timeout + 5,
                env={"PATH": os.environ["PATH"]},   # NOT os.environ
            )
        except subprocess.TimeoutExpired:
            return "EXECUTION ERROR:\nTimed out"

        if result.returncode != 0:
            return f"EXECUTION ERROR:\n{result.stderr[:4000]}"
        return f"SUCCESS OUTPUT:\n{result.stdout[:4000]}"

हर फ़्लैग क्यों मौजूद है

  1. 1

    --network none

    फ़ाइल की सबसे मूल्यवान एकल लाइन। बिना नेटवर्क इंटरफ़ेस के, जेनरेट किया गया कोड कुछ भी बाहर नहीं भेज (exfiltrate) सकता, चाहे उसे कुछ भी करने को कहा गया हो। Module 12 के हमलों का पूरा परिवार यहीं खत्म हो जाता है।
  2. 2

    --rm और साथ में एक टेम्प डायरेक्टरी

    अल्पकालिक (Ephemeral)। कोड जो कुछ भी लिखता है, इंस्टॉल करता है या शेड्यूल करता है, वह रन के बाद नहीं बचता, इसलिए कोई हमला अगले यूज़र के सेशन में नहीं टिक सकता (Module 18)।
  3. 3

    --read-only और --cap-drop ALL

    यह इमेज में बदलाव नहीं कर सकता और न ही प्रिविलेज हासिल कर सकता है। nobody के रूप में चलाने के साथ मिलकर, कंटेनर से बाहर निकलने (escape) के लिए कॉन्फ़िगरेशन की गलती नहीं बल्कि कर्नेल बग की ज़रूरत होगी।
  4. 4

    env={"PATH": ...}

    शांत पर असरदार। subprocess.run डिफ़ॉल्ट रूप से आपके पूरे एनवायरनमेंट को इनहेरिट कर लेता है — आपके द्वारा एक्सपोर्ट की गई हर API key को। एक स्पष्ट न्यूनतम env पास करना एक लाइन का बदलाव है जो लीक की पूरी श्रेणी को खत्म कर देता है।
  5. 5

    आउटपुट ट्रंकेशन (छंटाई)

    एक मॉडल जो गीगाबाइट में प्रिंट करता है, वह आपकी कॉन्टेक्स्ट विंडो और आपके बिल दोनों को भर देता है। इस पर कैप (सीमा) लगाएँ।

जब कंटेनर भी काफ़ी न हों

Docker होस्ट के साथ कर्नेल शेयर करता है। वास्तव में खतरनाक इनपुट के लिए — एक ऐसा पब्लिक प्रोडक्ट जहाँ कोई भी लक्ष्य सबमिट कर सकता है — आगे बढ़ें:
  • gVisor या Kata Containers — वर्कलोड और होस्ट कर्नेल के बीच एक syscall सीमा।
  • Firecracker microVMs — असली वर्चुअलाइज़ेशन, ~125ms में बूट होता है। होस्टेड कोड-एग्ज़ीक्यूशन सेवाएँ इसी का उपयोग करती हैं।
  • WebAssembly (Pyodide, Wasmtime) — बनावट से ही क्षमता-आधारित (capability-based): जब तक आप न दें, कोई फ़ाइलसिस्टम या नेटवर्क नहीं मिलता। बेहतरीन तब है जब कोड को सिर्फ़ गणना (compute) करनी हो।
  • एक मैनेज्ड sandbox सर्विस — किसी और की समस्या, जो अक्सर सही इंजीनियरिंग समाधान होता है।
यह करें
निर्णय का नियम, और यह बहुत छोटा है: यदि लक्ष्य ऑपरेटर के अलावा किसी और से प्रभावित हो सकता है, तो कंटेनर न्यूनतम सीमा (floor) हैं, अधिकतम (ceiling) नहीं। यदि लक्ष्य हमेशा सिर्फ़ आपसे, आपके लैपटॉप पर ही आता है, तो ट्यूटोरियल वाला वर्ज़न ठीक है — बस कभी भी इस धारणा को चुपचाप बदलने न दें।

बाकी सुरक्षा उपाय

  • इटरेशन, क्लॉक-टाइम और मॉडल के खर्च पर एक सख्त सीमा, जो लूप के बाहर लागू हो।
  • रन करने से पहले हर जेनरेट किए गए कोड ब्लॉक का लॉग होना — यह आपका एकमात्र फोरेंसिक रिकॉर्ड है।
  • एजेंट द्वारा sandbox के बाहर किसी भी चीज़ को छूने से पहले इंसानी मंज़ूरी।
  • इन्फ़्रास्ट्रक्चर लेयर पर एक किल स्विच, न कि कोई ऐसा फ़्लैग जिसे एजेंट देख सके (Module 33)।

और देखें और पढ़ें

लैब

एक sandbox एस्केप जिसका आपने प्रयास किया और असफल रहे।

~25 min

समस्या

ट्यूटोरियल एग्ज़ीक्यूटर को Module 66 के सुरक्षित कंटेनर से बदलें। फिर उस पर हमला करें: एक होस्ट फ़ाइल पढ़ें, बाहर संपर्क करें (phone home), मेमोरी खत्म करें, fork-bomb करें, पर्सिस्ट करें। फिर एक-एक करके फ़्लैग हटाएँ और पुष्टि करें कि प्रत्येक हमला फिर से संभव हो जाता है।
शुरुआती कोडpython
ATTACKS = {
  "read host":  "print(open('/etc/passwd').read())",
  "network":    "import urllib.request; urllib.request.urlopen('http://example.com')",
  "memory":     "x = bytearray(10**9)",
  "fork bomb":  "import os\nwhile True: os.fork()",
  "persist":    "open('/work/persisted.txt','w').write('still here')",
}
Google Colab खोलें ↗इस कोड के लिए आपके अपने सेटअप की ज़रूरत है (एक मॉडल, एक GPU या अतिरिक्त पैकेज)। इसे Google Colab में चलाएं: File → Upload notebook।

आपका काम तब पूरा होगा जब

कठिन सवाल

उत्तर देखने से पहले ख़ुद जवाब देने की कोशिश करें। अगर आप इनके जवाब दे सकते हैं, तो आप पाठ समझ गए हैं।

Q1आप --network none को हटाते हैं लेकिन बाकी सब रखते हैं। अब एक हमलावर क्या कर सकता है, उसे सबसे बुरे से शुरू करते हुए रैंक करें।दिखाएं
एक: कंटेनर में मौजूद किसी भी चीज़ को बाहर भेजना (exfiltrate) — कोड, लक्ष्य, माउंट किया गया कोई भी डेटा — जो असीमित और अपरिवर्तनीय है। दो: दूसरे चरण का पेलोड लाना और चलाना, जिससे एक सीमित sandbox एक मनमाने sandbox में बदल जाता है। तीन: यदि होस्ट नेटवर्क रूट करने योग्य है तो इंटरनल सेवाओं और क्लाउड मेटाडेटा तक पहुँचना, जिससे क्रेडेंशियल मिल सकते हैं। इग्रेस (Egress) सबसे मूल्यवान एकल फ़्लैग है क्योंकि यह हर दूसरी सीमा को एक अस्थायी असुविधा में बदल देता है।

जारी रखने के लिए कृपया साइन इन करें।

अक्सर पूछे जाने वाले सवाल

क्या मेरे इंटरनल टूल के लिए Docker काफ़ी है?

एक इंटरनल टूल के लिए जहाँ लक्ष्य आपकी अपनी टीम से आते हैं, हाँ, ऊपर बताए अनुसार कॉन्फ़िगर किया गया हो। यहाँ ख़तरा दुर्घटना और गलती का है, कर्नेल का फ़ायदा उठाने वाले किसी इरादतन हमलावर का नहीं।

क्या मैं खतरनाक कोड को चलाने से पहले सिर्फ़ फ़िल्टर नहीं कर सकता?

आप कोशिश कर सकते हैं, और यह एक स्पीड ब्रेकर जैसा है (Module 20)। open("/etc/passwd") को लिखने के अनगिनत तरीके हैं। आइसोलेशन इसलिए काम करता है क्योंकि यह हमले को पहचानने पर निर्भर नहीं करता।

sandbox के अंदर pip install के बारे में क्या?

इसके लिए नेटवर्क की ज़रूरत होती है, जिसे आपने अभी-अभी हटाया है। पैकेज को अपनी इमेज में पहले से बेक (pre-bake) कर लें। यह एक फ़ीचर है: आपका एजेंट आज PyPI द्वारा दी जा रही किसी भी चीज़ के बजाय एक ज्ञात डिपेंडेंसी सेट पर चलता है।

यह लूप को कितना धीमा कर देता है?

कंटेनर शुरू होने में लगभग 200-500ms लगते हैं। कई सेकंड की मॉडल कॉल के मुकाबले, यह नगण्य है। अगर आपको कभी फ़र्क पड़े तो एक वॉर्म पूल तैयार रखें।

पाठ का टेस्ट

5 सवाल। पास होने और इस पाठ को पूरा करने के लिए 3 सही होने चाहिए (60%)।

टेस्ट देने और अपनी प्रोग्रेस सेव करने के लिए साइन इन करें