Sandboxed-Codeausführung
Der Crate adk-sandbox bietet isolierte Codeausführung für ADK-Agenten mit zwei Isolationsstufen:
- Prozessisolierung — Kindprozesse mit Umgebungsisolierung und Timeout-Durchsetzung
- Sandbox-Profile auf Betriebssystemebene — Einschränkungen auf Kernel-Ebene für Dateisystem, Netzwerk und das Starten von Prozessen
Backends
| Backend | Isolationsstufe | Sprachen | Feature-Flag |
|---|---|---|---|
ProcessBackend | Umgebung + Zeitlimit | Rust, Python, JS, TS, Befehl | process (Standard) |
ProcessBackend + Sandbox | Auf Kernel-Ebene | Wie oben | process + sandbox-native |
WasmBackend | Vollständig (Speicher, Dateisystem, Netzwerk) | nur WASM | wasm |
Welche Isolation erhalten Sie?
ProcessBackend::isolation() meldet dies, daher ist dies nichts, was sich aus dem Crate-Namen ableiten lässt:
| Ergebnis | Bedeutung |
|---|---|
IsolationClass::SubprocessOnly | Ein Kindprozess mit bereinigter Umgebung, einem Zeitlimit und einer eigenen Prozessgruppe. Das Betriebssystem wendet keine weiteren Einschränkungen an: Der Code kann das Host-Dateisystem lesen und auf das Netzwerk zugreifen. Das erhalten Sie mit ProcessBackend::default(). |
IsolationClass::OsEnforced | Ein Enforcer und eine Richtlinie sind angehängt, sodass das Betriebssystem den Kindprozess einschränkt. |
Zwei Dinge über das Prozess-Backend sind wissenswert:
- Programme werden aufgelöst, bevor die Umgebung geleert wird. Ein einfaches
python3,nodeoderrustcwird in derPATHdes Aufrufers gesucht und dem Kindprozess als absoluter Pfad übergeben. Das bedeutet, dass der Kindprozess zum Starten keine eigenePATHbenötigt – zuvor musste ein AufruferPATHinExecRequest::envsetzen, wodurch der ausgeführte Code außerdem beliebige andere Programme darüber starten konnte. - Die Kompilierung läuft durch dieselbe Grenze wie die Ausführung. Rust-Quellcode wurde
bisher von einem außerhalb des gemeinsamen Pfads erstellten Befehl kompiliert, sodass für
die Kompilierung kein Enforcer-Wrapper, kein Timeout und keine Prozessgruppe vorhanden war.
Das ist relevant, weil die Kompilierung nicht passiv ist:
include_str!liest Dateien, und prozedurale Makros führen beliebigen Code aus, bevor die erzeugte Binärdatei existiert. Die Kompilierungsphase erhält eine plattformspezifische Zulassungsliste für Toolchains; unter Windows umfasst diese die MSVC- und Windows-SDK-Pfade, die aus der installierten Toolchain ermittelt werden, wenn sich der Aufrufer nicht bereits in einer Entwicklershell befindet. Die Kompilierung verwendet denrust-lld-Linker der Rust-Toolchain, sodass ein davon unabhängigeslink.exe, das weiter vorne inPATHsteht, nicht ausgewählt werden kann. Ein Enforcer des Betriebssystems begrenzt diese Phase.
Vorrang der Umgebung
SandboxPolicy::env stellt für jede Ausführung Standardwerte bereit, und ExecRequest::env
überschreibt sie pro Aufruf. Die Variablen der Richtlinie wurden zuvor vollständig ignoriert.
Sandbox-Profile des Betriebssystems
Die Sandbox-Durchsetzung auf Betriebssystemebene beschränkt Kindprozesse auf Kernel-Ebene. Dies geht über die Isolierung der Umgebung hinaus – das Betriebssystem selbst blockiert nicht autorisierten Dateisystemzugriff, Netzwerkverbindungen und das Starten von Prozessen.
Plattformunterstützung
| Plattform | Durchsetzer | Funktionsweise |
|---|---|---|
| macOS | Seatbelt (sandbox-exec) | Regeln auf Systemaufrufebene: „standardmäßig erlauben, Gefährliches verweigern“ — verweigert Schreibzugriffe, Netzwerkzugriff und Forks; Lesezugriffe sind nicht eingeschränkt |
| Linux | bubblewrap (bwrap) | Isolierung des Dateisystem-Namensraums (Whitelist-Einhängungen) |
| Windows | AppContainer | Nicht implementiert – der Enforcer meldet sich als nicht verfügbar |
Schnellstart
use adk_sandbox::{
ProcessBackend, ProcessConfig, SandboxBackend,
SandboxPolicyBuilder, get_enforcer,
};
// 1. Define what the sandboxed process can do
let policy = SandboxPolicyBuilder::new()
.allow_read("/usr") // Read system libraries
.allow_read_write("/tmp/work") // Write to work directory
.allow_process_spawn() // Python needs to exec
// Network is denied by default
.env("PATH", "/usr/bin:/usr/local/bin")
.build();
// 2. Get the platform-appropriate enforcer
let enforcer = get_enforcer()?;
// 3. Create a sandboxed backend
let backend = ProcessBackend::with_sandbox(
ProcessConfig::default(),
enforcer,
policy,
);
// 4. Execute code — network is blocked, writes restricted
let result = backend.execute(request).await?;
Feature-Flags
[dependencies]
# Auto-detect platform enforcer
adk-sandbox = { version = "2.1.0", features = ["process", "sandbox-native"] }
# Or pick a specific platform
adk-sandbox = { version = "2.1.0", features = ["process", "sandbox-macos"] }
adk-sandbox = { version = "2.1.0", features = ["process", "sandbox-linux"] }
SandboxPolicy
Die Richtlinie legt fest, was ein isolierter Prozess tun darf:
| Feld | Standard | Beschreibung |
|---|---|---|
allowed_paths | [] (alles verweigern) | Dateisystempfade mit schreibgeschütztem oder Lese-/Schreibzugriff |
allow_network | false | Gibt an, ob der Netzwerkzugriff zulässig ist |
allow_process_spawn | false | Ob das Erzeugen von Kindprozessen erlaubt ist |
env | {} | Umgebungsvariablen für den isolierten Prozess |
Plattformunterschiede
macOS (Seatbelt): Verwendet „standardmäßig erlauben, Gefährliches verweigern“ – startet mit vollständigem Zugriff und blockiert anschließend Netzwerkzugriff, Dateischreibvorgänge und das Starten von Prozessen. Ein reiner Whitelist-Ansatz funktioniert nicht, da Python beim Start Dutzende macOS-spezifische Syscall-Kategorien benötigt.
Linux (bubblewrap): Verwendet eine namespace-basierte Whitelist – standardmäßig ist nichts vorhanden, und Sie binden nur das ein, was benötigt wird. Installieren Sie mit apt install bubblewrap oder dnf install bubblewrap.
Windows (AppContainer): Nicht implementiert. Das Design basiert auf tokenbasierten ACLs – einer eingeschränkten SID, die standardmäßig keinen Zugriff hat, wobei anschließend ACLs für bestimmte Pfade gewährt werden. Da jedoch die Containererstellung, ACLs, Capabilities und die Bereinigung von Job-Objekten fehlen, gibt probe() EnforcerUnavailable zurück. Führen Sie Windows ohne Enforcer aus oder verwenden Sie macOS oder Linux, wo die Durchsetzung tatsächlich funktioniert.
Beispiel
Siehe examples/sandbox_agent/ für ein vollständiges von LLM gesteuertes Beispiel, das Python-Code in einer Sandbox-Umgebung ausführt, wobei der Netzwerkzugriff durch den Betriebssystemkernel blockiert wird.