
Ein leichtgewichtiges Sandboxing-Tool zur Durchsetzung von Dateisystem- und Netzwerkbeschränkungen für beliebige Prozesse auf Betriebssystemebene, ohne dass ein Container erforderlich ist.
Ein leichtgewichtiges Sandboxing-Tool zur Durchsetzung von Dateisystem- und Netzwerkbeschränkungen für beliebige Prozesse auf Betriebssystemebene, ohne dass ein Container erforderlich ist.
srt nutzt native OS-Sandboxing-Primitive (sandbox-exec auf macOS, bubblewrap auf Linux) sowie proxybasiertes Netzwerk-Filtering. Es kann verwendet werden, um das Verhalten von Agenten, lokalen MCP-Servern, Bash-Befehlen und beliebigen Prozessen zu sandboxen.
Beta-Forschungspreview
Die Sandbox Runtime ist eine Forschungspreview, die für Claude Code entwickelt wurde, um sicherere KI-Agenten zu ermöglichen. Sie wird als frühe Open-Source-Preview bereitgestellt, um dem breiteren Ökosystem beim Aufbau sichererer agentischer Systeme zu helfen. Da es sich um eine frühe Forschungspreview handelt, können sich APIs und Konfigurationsformate weiterentwickeln. Wir freuen uns über Feedback und Beiträge, um KI-Agenten standardmäßig sicherer zu machen!
npm install -g @anthropic-ai/sandbox-runtime
## Grundlegende Verwendung```bash
# Network restrictions
$ srt "curl anthropic.com"
Running: curl anthropic.com
<html>...</html> # Request succeeds
$ srt "curl example.com"
Running: curl example.com
Connection blocked by network allowlist # Request blocked
# Filesystem restrictions
$ srt "cat README.md"
Running: cat README.md
# Anthropic Sandb... # Current directory access allowed
$ srt "cat ~/.ssh/id_rsa"
Running: cat ~/.ssh/id_rsa
cat: /Users/ollie/.ssh/id_rsa: Operation not permitted # Specific file blocked
Dieses Paket bietet eine eigenständige Sandbox-Implementierung, die sowohl als CLI-Tool als auch als Bibliothek verwendet werden kann. Es ist mit einer Secure-by-Default-Philosophie konzipiert, die auf gängige Entwickler-Anwendungsfälle zugeschnitten ist: Prozesse starten mit minimalem Zugriff, und Sie öffnen gezielt nur die Löcher, die Sie benötigen.
Wichtigste Funktionen:
Ein wichtiger Anwendungsfall ist das Sandboxing von Model Context Protocol (MCP)-Servern, um deren Fähigkeiten einzuschränken. Zum Beispiel, um den Dateisystem-MCP-Server zu sandboxen:
Ohne Sandboxing (.mcp.json):```json
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem"]
}
}
}
**Mit Sandboxing** (`.mcp.json`):```json
{
"mcpServers": {
"filesystem": {
"command": "srt",
"args": ["npx", "-y", "@modelcontextprotocol/server-filesystem"]
}
}
}
Dann konfiguriere die Einschränkungen in ~/.srt-settings.json:```json
{
"filesystem": {
"denyRead": [],
"allowWrite": ["."],
"denyWrite": ["~/sensitive-folder"]
},
"network": {
"allowedDomains": [],
"deniedDomains": []
}
}
Jetzt wird der MCP-Server daran gehindert, in den verweigerten Pfad zu schreiben:```
> Write a file to ~/sensitive-folder
✗ Error: EPERM: operation not permitted, open '/Users/ollie/sensitive-folder/test.txt'
Die Sandbox nutzt OS-Primitive, um Einschränkungen durchzusetzen, die für den gesamten Prozessbaum gelten:
sandbox-exec mit dynamisch generierten Seatbelt-Profilensrt-sandbox aus, mit einem Windows Filtering Platform-Egress-Fence, der auf die SID dieses Kontos sowie explizite ACEs pro Sitzung im Arbeitsbaum abgestimmt ist0d1c612947c798aef48e6ab4beb7e8544da9d41a-4096x2305
Sowohl Dateisystem- als auch Netzwerkisolation sind für eine effektive Sandboxing erforderlich. Ohne Dateiisolation könnte ein kompromittierter Prozess SSH-Schlüssel oder andere sensible Dateien exfiltrieren. Ohne Netzwerkisolation könnte ein Prozess die Sandbox verlassen und uneingeschränkten Netzwerkzugriff erlangen.
Dateisystem-Isolation erzwingt Lese- und Schreibbeschränkungen:
/Users) und dann bestimmte Pfade darin wieder erlauben (z. B. .). allowRead hat Vorrang vor denyRead – im Gegensatz zum Schreiben, wo denyWrite Vorrang vor allowWrite hat. Ein denyRead-Eintrag, der spezifischer ist als der allowRead-Bereich, in dem er liegt (z. B. denyRead: ["**/.env"] oder ["./secrets"] mit allowRead: ["."]), bleibt weiterhin verweigert.., /tmp). Eine leere Erlaubnisliste bedeutet keinen Schreibzugriff.Netzwerk-Isolation (Nur-Erlauben-Muster): Standardmäßig ist der gesamte Netzwerkzugriff verweigert. Sie müssen Domains explizit erlauben. Eine leere allowedDomains-Liste bedeutet keinen Netzwerkzugriff. Netzwerkverkehr wird über Proxyserver geleitet, die auf dem Host laufen:
Linux: Anfragen werden über das Dateisystem über einen Unix-Domain-Socket geleitet. Der Netzwerk-Namespace des sandboxierten Prozesses wird vollständig entfernt, sodass der gesamte Netzwerkverkehr über die auf dem Host laufenden Proxys laufen muss (die auf Unix-Sockets lauschen, die in die Sandbox eingebunden sind)
macOS: Das Seatbelt-Profil erlaubt nur die Kommunikation mit einem bestimmten Localhost-Port. Die Proxys lauschen auf diesem Port und schaffen so einen kontrollierten Kanal für den gesamten Netzwerkzugriff
Windows: Ein maschinenweiter WFP-Filtersatz blockiert alle ausgehenden Verbindungen, die vom Konto srt-sandbox stammen, mit Ausnahme von Loopback zum Proxy-Portbereich. Die Proxys lauschen innerhalb dieses Bereichs und schaffen so einen kontrollierten Kanal für den gesamten Netzwerkzugriff
Sowohl HTTP/HTTPS (über HTTP-Proxy) als auch anderer TCP-Verkehr (über SOCKS5-Proxy) werden von diesen Proxys vermittelt, die Ihre Domain-Allowlists und Denylists durchsetzen.
Weitere Details zum Sandboxing in Claude Code finden Sie unter:
src/ ├── index.ts # Library exports ├── cli.ts # CLI entrypoint (srt command) ├── utils/ # Shared utilities │ ├── debug.ts # Debug logging │ ├── settings.ts # Settings reader (permissions + sandbox config) │ ├── platform.ts # Platform detection │ └── exec.ts # Command execution utilities └── sandbox/ # Sandbox implementation ├── sandbox-manager.ts # Main sandbox manager ├── sandbox-schemas.ts # Zod schemas for validation ├── sandbox-violation-store.ts # Violation tracking ├── sandbox-utils.ts # Shared sandbox utilities ├── http-proxy.ts # HTTP/HTTPS proxy for network filtering ├── socks-proxy.ts # SOCKS5 proxy for network filtering ├── linux-sandbox-utils.ts # Linux bubblewrap sandboxing ├── macos-sandbox-utils.ts # macOS sandbox-exec sandboxing └── windows-sandbox-utils.ts # Windows srt-win sandboxing
## Verwendung
### Als CLI-Werkzeug
Der Befehl `srt` (Anthropic Sandbox Runtime) umschließt jeden Befehl mit Sicherheitsgrenzen:```bash
# Run a command in the sandbox
srt echo "hello world"
# With debug logging
srt --debug curl https://example.com
# Specify custom settings file
srt --settings /path/to/srt-settings.json npm install
import { SandboxManager, type SandboxRuntimeConfig, } from '@anthropic-ai/sandbox-runtime' import { spawn } from 'child_process'
// Define your sandbox configuration const config: SandboxRuntimeConfig = { network: { allowedDomains: ['example.com', 'api.github.com'], deniedDomains: [], }, filesystem: { denyRead: ['~/.ssh'], allowWrite: ['.', '/tmp'], denyWrite: ['.env'], }, }
// Initialize the sandbox (starts proxy servers, etc.) await SandboxManager.initialize(config)
// Wrap a command with sandbox restrictions const sandboxedCommand = await SandboxManager.wrapWithSandbox( 'curl https://example.com', )
// Execute the sandboxed command const child = spawn(sandboxedCommand, { shell: true, stdio: 'inherit' })
// Handle exit and cleanup after child process completes
child.on('exit', async code => {
console.log(Command exited with code ${code})
// Cleanup when done (optional, happens automatically on process exit)
await SandboxManager.reset()
})
**Verletzungszuordnung (`commandId` / `commandText`).** Verstöße, die während der Ausführung eines umschlossenen Befehls beobachtet werden (Seatbelt-Protokollzeilen, Seccomp-Ereignisse, Proxy-Ablehnungen), werden unter einem Zuordnungsschlüssel gespeichert, und `annotateStderrWithSandboxFailures(key, stderr)` / `getViolationsForCommand(key)` suchen sie über denselben Schlüssel nach. Standardmäßig ist der Schlüssel die umschlossene Zeichenkette selbst. Übergeben Sie eine undurchsichtige, pro Aufruf vergebene `commandId` (z. B. eine Tool-Use-ID), um stattdessen danach zu schlüsseln — empfohlen: Schlüssel vergleichen ihre ersten 100 Zeichen, sodass lange Befehle mit gemeinsamem Präfix sonst falsch zugeordnet würden, und eine erneute Ausführung desselben Texts die Ereignisse des früheren Laufs erben würde. Wenn die Zeichenkette, die Sie *ausführen*, nicht der Befehl ist, den der Aufruf *repräsentiert* (z. B. wenn Sie ein zusammengesetztes `source <snapshot> && eval '<cmd>'` umschließen), übergeben Sie ebenfalls `commandText: '<cmd>'`: Es ist das, wogegen die `ignoreViolations`-Befehlsmuster abgleichen und was jeder Verstoß als seinen `command` meldet.```typescript
const wrapped = await SandboxManager.wrapWithSandbox(
assembledCommand, // what actually runs
undefined,
undefined,
undefined,
{ commandId: invocationId, commandText: rawCommand },
)
// ... run it ...
const annotated = SandboxManager.annotateStderrWithSandboxFailures(invocationId, stderr)
// Main sandbox manager export { SandboxManager } from '@anthropic-ai/sandbox-runtime'
// Violation tracking export { SandboxViolationStore } from '@anthropic-ai/sandbox-runtime'
// TypeScript types export type { SandboxRuntimeConfig, NetworkConfig, FilesystemConfig, IgnoreViolationsConfig, SandboxAskCallback, FsReadRestrictionConfig, FsWriteRestrictionConfig, NetworkRestrictionConfig, } from '@anthropic-ai/sandbox-runtime'
## Konfiguration
### Speicherort der Einstellungsdatei
Standardmäßig sucht die Sandbox-Laufzeitumgebung nach der Konfiguration unter `~/.srt-settings.json`. Sie können einen benutzerdefinierten Pfad mithilfe des Flags `--settings` angeben:```bash
srt --settings /path/to/srt-settings.json <command>
{ "network": { "allowedDomains": [ "github.com", ".github.com", "lfs.github.com", "api.github.com", "npmjs.org", ".npmjs.org" ], "deniedDomains": ["malicious.com"], "allowUnixSockets": ["/var/run/docker.sock"], "allowLocalBinding": false }, "filesystem": { "denyRead": ["~/.ssh"], "allowRead": [], "allowWrite": [".", "src/", "test/", "/tmp"], "denyWrite": [".env", "config/production.json"] }, "ignoreViolations": { "*": ["/usr/bin", "/System"], "git push": ["/usr/bin/nc"], "npm": ["/private/tmp"] }, "enableWeakerNestedSandbox": false, "enableWeakerNetworkIsolation": false, "allowAppleEvents": false }
### Konfigurationsoptionen
#### Netzwerkkonfiguration
Verwendet ein **Nur-Erlauben-Muster** – der gesamte Netzwerkzugriff ist standardmäßig verweigert.
- `network.allowedDomains` – Array der erlaubten Domains (unterstützt Platzhalter wie `*.example.com`). Leeres Array = kein Netzwerkzugriff. Ein optionales `:port`-Suffix (`api.example.com:443`, `*.example.com:8443`) beschränkt einen Eintrag auf diesen Zielport; Einträge ohne Port entsprechen jedem Port.
- IPv6-Literale müssen in eckigen Klammern gesetzt werden, RFC-3986-Stil: `[::1]`, `[2001:db8::1]:443`. Ein Eintrag mit mehreren Doppelpunkten ohne Klammern wird als mehrdeutig abgelehnt (`2001:db8::1:443` ist selbst eine gültige Adresse).
- `network.deniedDomains` – Array der verweigerten Domains (wird zuerst geprüft, hat Vorrang vor `allowedDomains`). Gleiches `:port`-Suffix, und ein nacktes `*` (oder `*:22`) wird für Verweigern-alles akzeptiert.
- `network.deniedDomainReasons` – Optionale Zuordnung von einem `deniedDomains`-Eintrag (per exakter Zeichenkette abgeglichen) zu einem modellbezogenen Grund, der in der `<sandbox_violations>`-Zeile erscheint, wenn dieser Eintrag eine Verbindung verweigert – geben Sie an, was blockiert ist, und die genehmigte Alternative (z. B. `{"github.com:22": "SSH-Pushes an GitHub sind blockiert; verwenden Sie ein https://-Remote"}`). Einträge ohne Grund melden einen allgemeinen Grund. Für SSH-Ziele (Port 22) wird der Grund auch in-band übermittelt: Ein SSH-Client, der durch einen SOCKS-ProxyCommand ohne Authentifizierung getunnelt wird (z. B. BSD `nc -X 5`), erhält eine SSH-Trennung vor dem Schlüsselaustausch, deren Beschreibung der Grund ist, den OpenSSH wörtlich ausgibt – halten Sie solche Gründe unter ~400 ASCII-Zeichen, imperativ zuerst, da OpenSSH nicht-ASCII kürzt und maskiert.
- `network.allowLocalBinding` – Binden an lokale Ports erlauben (boolesch, Standard: false)
**TLS-Terminierung** (`network.tlsTerminate`, experimentell): Wenn gesetzt, werden HTTPS-CONNECTs prozessintern terminiert, sodass SRT die entschlüsselten Anfragen sehen (und über `network.filterRequest` filtern) kann. Der sandboxierte Prozess wird auf einen Vertrauensspeicher verwiesen, der die MITM-CA (`caCertPath`/`caKeyPath` oder eine flüchtige CA, falls weggelassen) sowie die regulären Roots des Hosts enthält, sodass sowohl vom Proxy ausgestellte Zertifikate als auch echte Upstream-Zertifikate verifiziert werden.
- `network.tlsTerminate.excludeDomains` – Domain-Muster (gleiche Syntax wie `allowedDomains`), die **nicht** terminiert werden. Passende CONNECTs werden stattdessen opak getunnelt: Sie unterliegen weiterhin der Domain-Allowlist, aber der Client innerhalb der Sandbox führt seinen eigenen TLS-Handshake mit dem echten Upstream durch, und `filterRequest`/Credential-Injektion gelten nicht für deren HTTPS-Verkehr. Verwenden Sie dies für die beiden Fälle, die TLS-Terminierung grundlegend bricht:
- **mTLS-Upstreams** – nur der Client in der Sandbox hält das Client-Zertifikat, sodass der Proxy die Verbindung nicht in seinem Namen neu aufbauen kann.
- **Zertifikat-Pinning-Clients** – Clients, die die Identität des Upstreams selbst verifizieren (benutzerdefinierte CAs, SAN-Pinning) und das MITM-Zertifikat ablehnen.
- `network.tlsTerminate.extraCaCertPaths` – Pfade zu PEM-CA-Zertifikatsdateien, die diesem Vertrauensspeicher angehängt werden, nach der MITM-CA und den regulären Roots des Hosts. Ausgeschlossene (nicht terminierte) Hosts werden vom Client in der Sandbox verifiziert, und die Vertrauens-Umgebungsvariablen, die SRT setzt (`SSL_CERT_FILE`, `GIT_SSL_CAINFO`, ...), _ersetzen_ die eigene Vertrauenskonfiguration jedes Tools, sodass eine standortlokale Root (z. B. eine interne mTLS-CA) im Speicher enthalten sein muss, sonst können diese Hosts nie verifiziert werden. Nur die `CERTIFICATE`-Blöcke jeder Datei werden in den Speicher kopiert (alles andere, z. B. ein privater Schlüssel in einem kombinierten PEM, wird der Sandbox nie ausgesetzt); Dateien, die fehlen, nicht lesbar sind oder keinen PEM-`CERTIFICATE`-Block enthalten, werden übersprungen, sodass es sicher ist, Pfade aufzulisten, die nur auf einigen Hosts existieren.```json
{
"network": {
"allowedDomains": ["*.example.com", "internal-mtls.example.net"],
"deniedDomains": [],
"tlsTerminate": {
"excludeDomains": ["internal-mtls.example.net"],
"extraCaCertPaths": ["/etc/internal-mtls-roots.pem"]
}
}
}
Unix-Socket-Einstellungen (plattformspezifisches Verhalten):
| Einstellung | macOS | Linux |
|---|---|---|
allowUnixSockets: string[] | Zulassungsliste von Socket-Pfaden | Ignoriert (seccomp kann nicht nach Pfad filtern) |
allowAllUnixSockets: boolean | Alle Sockets zulassen | seccomp-Blockierung deaktivieren |
Unix-Sockets sind auf beiden Plattformen standardmäßig blockiert.
allowUnixSockets, um bestimmte Pfade zuzulassen (z. B. ["/var/run/docker.sock"]), oder allowAllUnixSockets: true, um alle zuzulassen.allowAllUnixSockets: true, um die Blockierung explizit zu deaktivieren.Verwendet zwei verschiedene Muster:
Lesebeschränkungen (Verweigern-dann-Zulassen-Muster) – alle Lesezugriffe sind standardmäßig erlaubt:
filesystem.denyRead – Array von Pfaden, für die der Lesezugriff verweigert wird. Leeres Array = voller Lesezugriff.filesystem.allowRead – Array von Pfaden, für die der Lesezugriff innerhalb verweigerter Bereiche wieder erlaubt wird (hat Vorrang vor denyRead). Hinweis: Dies ist das Gegenteil von Schreiben, wo denyWrite Vorrang vor allowWrite hat.Schreibbeschränkungen (Nur-Zulassen-Muster) – alle Schreibzugriffe sind standardmäßig verweigert:
filesystem.allowWrite – Array von Pfaden, für die der Schreibzugriff erlaubt wird. Leeres Array = kein Schreibzugriff.filesystem.denyWrite – Array von Pfaden, für die der Schreibzugriff innerhalb erlaubter Pfade verweigert wird (hat Vorrang vor allowWrite)Pfadsyntax (macOS):
Pfade unterstützen auf macOS Git-ähnliche Glob-Muster, ähnlich der .gitignore-Syntax:
* – Entspricht beliebigen Zeichen außer / (z. B. entspricht *.ts foo.ts, aber nicht foo/bar.ts)** – Entspricht beliebigen Zeichen einschließlich / (z. B. entspricht src/**/*.ts allen .ts-Dateien in src/)? – Entspricht einem einzelnen Zeichen außer / (z. B. entspricht file?.txt file1.txt)[abc] – Entspricht einem beliebigen Zeichen aus der Menge (z. B. entspricht file[0-9].txt file3.txt)Beispiele:
"allowWrite": ["src/"] – Schreiben in das gesamte src/-Verzeichnis erlauben"allowWrite": ["src/**/*.ts"] – Schreiben in alle .ts-Dateien in src/ und Unterverzeichnissen erlauben"denyRead": ["~/.ssh"] – Lesezugriff auf das SSH-Verzeichnis verweigern"denyRead": ["/Users"], "allowRead": ["."] – Lesezugriff auf ganz /Users verweigern, aber das aktuelle Verzeichnis wieder erlauben"denyWrite": [".env"] – Schreibzugriff auf die .env-Datei verweigern (auch wenn das aktuelle Verzeichnis erlaubt ist)Pfadsyntax (Linux):
Linux unterstützt derzeit kein Glob-Matching. Verwenden Sie nur literale Pfade:
"allowWrite": ["src/"] – Schreiben in das src/-Verzeichnis erlauben"denyRead": ["/home/user/.ssh"] – Lesezugriff auf das SSH-Verzeichnis verweigern"denyRead": ["/home"], "allowRead": ["."] – Lesezugriff auf ganz /home verweigern, aber das aktuelle Verzeichnis wieder erlaubenAlle Plattformen:
/home/user/.ssh) oder relativ zum aktuellen Arbeitsverzeichnis sein (z. B. ./src)~ wird zum Home-Verzeichnis des Benutzers erweitertignoreViolations – Objekt, das Befehlsmuster auf Arrays von Pfaden abbildet, in denen Verstöße ignoriert werden sollenenableWeakerNestedSandbox – Schwächeren Sandbox-Modus für Docker-Umgebungen aktivieren (boolesch, Standard: false)enableWeakerNetworkIsolation – Zugriff auf com.apple.trustd.agent in der macOS-Sandbox erlauben (boolesch, Standard: false). Dies wird für Go-Programme (gh, gcloud, terraform, kubectl usw.) benötigt, um TLS-Zertifikate zu verifizieren, wenn httpProxyPort mit einem MITM-Proxy und einer benutzerdefinierten CA verwendet wird. Sicherheitswarnung: Das Aktivieren dieser Option öffnet einen potenziellen Vektor für Datenexfiltration über den trustd-Dienst.allowAppleEvents – Senden von Apple Events und Launch-Services-Öffnungsanfragen aus der macOS-Sandbox erlauben (boolesch, Standard: false). Ohne dies schlagen Befehle wie open, osascript und alles, was URLs öffnet oder andere Apps über AppleScript skriptet, mit dem AppleScript-Fehler -600 („Application isn't running") oder LaunchServices-Fehlern (-10822, -54) fehl. Sicherheitswarnung: Das Aktivieren dieser Option bedeutet, dass die Sandbox keine Codeausführungs-Isolation mehr bietet. Ein sandboxierter Befehl kann andere Anwendungen über open ohne Benutzeraufforderung starten, und alles, was er startet, läuft außerhalb der Dateisystem- und Netzwerkbeschränkungen der Sandbox; das Skripten bereits laufender Apps über Apple Events wird zusätzlich durch die TCC-Automatisierungszustimmung des Benutzers pro App eingeschränkt. Einbettende Anwendungen sollten diese Option nur aus vertrauenswürdiger Benutzerebene-Konfiguration beziehen – niemals aus projektlokalen Dateien in einem ausgecheckten Repository, da ein von Angreifern erstelltes Projekt sonst seine eigenen Sandbox-Berechtigungen erhöhen könnte.GitHub-Zugriff erlauben (alle erforderlichen Endpunkte):```json { "network": { "allowedDomains": [ "github.com", "*.github.com", "lfs.github.com", "api.github.com" ], "deniedDomains": [] }, "filesystem": { "denyRead": [], "allowWrite": ["."], "denyWrite": [] } }
**Auf bestimmte Verzeichnisse beschränken:**```json
{
"network": {
"allowedDomains": [],
"deniedDomains": []
},
"filesystem": {
"denyRead": ["~/.ssh"],
"allowWrite": [".", "src/", "test/"],
"denyWrite": [".env", "secrets/"]
}
}
Nur-Workspace-Dateisystemzugriff (Lesezugriffe außerhalb des Workspace verweigern):```json { "network": { "allowedDomains": [], "deniedDomains": [] }, "filesystem": { "denyRead": ["/Users"], "allowRead": ["."], "allowWrite": ["."], "denyWrite": [] } }
Dies verweigert das Lesen von allem unter `/Users` (oder `/home` unter Linux) und erlaubt dann wieder das aktuelle Arbeitsverzeichnis. Systempfade (`/usr`, `/lib` usw.) bleiben lesbar.
### Häufige Probleme und Tipps
**Jest ausführen:** Verwenden Sie das Flag `--no-watchman`, um Sandbox-Verstöße zu vermeiden:```bash
srt "jest --no-watchman"
Watchman greift auf Dateien außerhalb der Sandbox-Grenzen zu, was Berechtigungsfehler auslöst. Wenn Sie es deaktivieren, kann Jest stattdessen mit dem integrierten Datei-Watcher ausgeführt werden.
sandbox-exec mit benutzerdefinierten Profilen (keine zusätzlichen Abhängigkeiten)bubblewrap (bwrap) für die Containerisierungsrt-win.exe-Hilfsdatei (keine zusätzlichen Abhängigkeiten). Siehe Windows (Alpha) unten für Einrichtung, Sicherheitsmodell und bekannte EinschränkungenLinux erfordert:
bubblewrap - Container-Laufzeit
apt-get install bubblewrapdnf install bubblewrappacman -S bubblewrapsocat - Socket-Relay für die Proxy-Brücke
apt-get install socatdnf install socatpacman -S socatripgrep - Schnelles Suchtool zur Erkennung von verweigerten Pfaden
apt-get install ripgrepdnf install ripgreppacman -S ripgrepHinweis für Ubuntu 24.04+: Diese Versionen aktivieren kernel.apparmor_restrict_unprivileged_userns standardmäßig, was unshare(CLONE_NEWUSER) erlaubt, aber dem resultierenden Namespace die Capabilities entzieht. Sowohl bubblewrap als auch die seccomp-Isolationsschicht benötigen Namespaces mit Capabilities. Deaktivieren Sie die Einschränkung mit:```bash
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
oder ein AppArmor-Profil hinzufügen, das `userns` für die relevanten Binärdateien gewährt.
**Optionale Linux-Abhängigkeiten (für den Seccomp-Fallback):**
Das Paket enthält vorab generierte Seccomp-BPF-Filter für die Architekturen x86-64 und arm. Diese Abhängigkeiten werden nur benötigt, wenn Sie sich auf einer anderen Architektur befinden, für die keine vorab generierten Filter verfügbar sind:
- `gcc` oder `clang` - C-Compiler
- `libseccomp-dev` - Entwicklungsdateien der Seccomp-Bibliothek
- Ubuntu/Debian: `apt-get install gcc libseccomp-dev`
- Fedora: `dnf install gcc libseccomp-devel`
- Arch: `pacman -S gcc libseccomp`
**macOS erfordert:**
- `ripgrep` - Schnelles Suchwerkzeug zur Erkennung von Deny-Pfaden
- Installation über Homebrew: `brew install ripgrep`
- Oder herunterladen von: https://github.com/BurntSushi/ripgrep/releases
**Windows erfordert:**
- Keine zusätzlichen Abhängigkeiten. Der `srt-win.exe`-Helfer (x64 und arm64) ist im npm-Paket enthalten. Ein einmaliger Schritt `windows-install` mit erhöhten Rechten ist erforderlich – siehe unten.
## Windows (Alpha)
Die Windows-Unterstützung ist **Alpha**. Der sandboxierte Prozess läuft unter einem dedizierten lokalen Benutzerkonto `srt-sandbox`, das durch native Windows-Sicherheitsprimitive vom aufrufenden Benutzer isoliert ist – ein Windows Filtering Platform (WFP)-Egress-Fence, der auf die SID des Sandbox-Kontos abgestimmt ist, sowie explizite ACEs pro Sitzung, die dieser SID Zugriff auf konfigurierte Dateisystempfade gewähren oder verweigern.
### Einrichtung
Einmal pro Maschine ausführen (selbst-erhöhend; eine UAC-Eingabeaufforderung):```powershell
npx @anthropic-ai/sandbox-runtime windows-install
Dies stellt das lokale Benutzerkonto srt-sandbox bereit (mit einem zufälligen Passwort, das DPAPI-verschlüsselt in HKLM\SOFTWARE\sandbox-runtime gespeichert ist — maschinenweit, sodass Fleet-Installationen, die als SYSTEM laufen, funktionieren und die Rotation eines Benutzers die Kopie aktualisiert, die die anderen lesen), die lokale Gruppe sandbox-runtime-users und installiert einen maschinenweiten WFP-Filtersatz, der auf die SID von srt-sandbox ausgerichtet ist. Es ist idempotent — eine erneute Ausführung rotiert das Passwort des Sandbox-Kontos und gleicht den Filtersatz ab.
Kein Abmelden erforderlich. Die WFP-Filter sind auf die SID des dedizierten Sandbox-Kontos ausgerichtet, sodass Ihr eigenes Netzwerk, Dienste und alle anderen Prinzipale auf dem Rechner unberührt bleiben.
Nach der Installation funktionieren SandboxManager.initialize() und die srt-CLI wie auf anderen Plattformen. initialize() überprüft, ob das Sandbox-Konto und der WFP-Zaun aktiv sind, und schlägt andernfalls mit einer umsetzbaren Fehlermeldung fehl.
Programmatische Installation/Deinstallation werden als installWindowsSandbox() / uninstallWindowsSandbox() exportiert.
Der sandboxierte Befehl läuft als das Konto srt-sandbox, nicht als der aufrufende Benutzer. Der gebündelte Helfer srt-win.exe führt einen Zwei-Sprung-Start durch: Der Broker ruft CreateProcessWithLogonW auf, um einen Runner als srt-sandbox zu starten, und der Runner startet das Ziel unter einem eingeschränkten Token innerhalb eines Job-Objekts. Das Kind erbt das isolierte Profil des Sandbox-Kontos (%USERPROFILE%, %TEMP%, HKCU) und eine frische Umgebung, die nur mit dem PATH des Brokers und den generierten Proxy-Variablen überlagert ist.
Das Ausführen unter einer separaten Benutzer-SID schließt strukturell die Klasse der Surrogat-Spawn-Escapes (Task Scheduler, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS auf einen Broker-eigenen Prozess, BITS, Out-of-Process-COM mit RunAs="Interactive User"): Jeder Prozess, den das Kind außerhalb der Reihe starten kann, trägt weiterhin die SID von srt-sandbox, bleibt also dem WFP-Egress-Zaun unterworfen und hat keine Rechte auf die Dateien des aufrufenden Benutzers.
Netzwerkisolation ist ein Zwei-Filter-WFP-Satz auf FWPM_LAYER_ALE_AUTH_CONNECT_V4/V6: ein PERMIT für Loopback-Ziele innerhalb des konfigurierten Proxy-Portbereichs (Standard 60080–60089) und ein BLOCK für jede Verbindung, deren Token die SID von srt-sandbox trägt. Der sandboxierte Prozess erreicht das Internet nur über die JS-HTTP/SOCKS5-Proxys, die in diesem Bereich lauschen; ein Prozess, der seine Proxy-Umgebung entfernt und sich direkt verbindet, wird im Kernel blockiert.
Dateisystemisolation wird durch diskretionäre NTFS-ACLs durchgesetzt. Das Konto srt-sandbox hat keine inhärenten Rechte auf die Dateien des aufrufenden Benutzers, daher schreibt die Sandbox bei initialize() additive, vererbende explizite ACEs nur für die SID von srt-sandbox — sie überschreibt oder ersetzt niemals den vorhandenen Sicherheitsdeskriptor eines Pfads:
filesystem.allowWrite → ein vererbender MODIFY-ALLOW-ACE (READ|WRITE|EXECUTE|DELETE, wobei FILE_DELETE_CHILD vorenthalten wird). Der sandboxierte Prozess kann Dateien innerhalb des Arbeitsbaums erstellen, ändern und löschen; das Vorenthalten von FILE_DELETE_CHILD aus der Gewährung ist Defense-in-Depth für die unten stehenden Deny-Stempel, kein Schutz für die Baumwurzel.filesystem.allowRead → ein vererbender READ|EXECUTE-ALLOW-ACEfilesystem.denyRead / filesystem.denyWrite → ein vererbender DENY-ACE auf dem Ziel, plus ein vererbender FILE_DELETE_CHILD-DENY auf dessen Eltern — zusammen mit dem vorenthaltenen FILE_DELETE_CHILD auf der Arbeitsbaum-Gewährung verhindert dies, dass der sandboxierte Prozess einen verweigerten Pfad über sein übergeordnetes Verzeichnis umbenennt oder löschtreset() entfernt jeden ACE, den diese Sitzung hinzugefügt hat (referenzgezählt über die benutzerspezifische Sitzungsdatenbank für gleichzeitige Hosts dieses Benutzers; ein Crash-Recovery-Durchlauf beim nächsten initialize() räumt nach einem unsauberen Beenden auf). Verzeichnisziele werden unterstützt (die ACEs vererben sich auf den gesamten Unterbaum). Glob-Muster werden zum Zeitpunkt von initialize() zu konkreten Pfaden expandiert — ein passender Pfad, der später erscheint, ist nicht abgedeckt.
network.tlsTerminate erfordert, dass die MITM-CA im Zertifikatspeicher des Sandbox-Benutzers CurrentUser\Root vorhanden ist (schannel — das TLS-Backend, das von System32\curl.exe, PowerShell Invoke-WebRequest, .NET und git mit Standard-Backend verwendet wird — vertraut nur dem OS-Speicher, nicht Umgebungsvariablen). Dies ist ein Schritt zur Installationszeit, getrennt von windows-install:```typescript
import { windowsTrustCa } from '@anthropic-ai/sandbox-runtime'
windowsTrustCa('/path/to/mitm-ca.crt') // or: srt-win user trust-ca
`initialize()` vergleicht den Fingerabdruck der Sitzungs-CA mit der installierten und schlägt bei einer Abweichung mit einer verständlichen Meldung fehl, sodass eine veraltete Installations-CA TLS innerhalb der Sandbox nicht stillschweigend unterbrechen kann.
OpenSSL-basierte Clients (msys2 `curl`, `git -c http.sslBackend=openssl`, Node, Python, cargo) werden von der Vertrauensschicht über Umgebungsvariablen abgedeckt: Dasselbe Vertrauensbündel, das unter macOS/Linux verwendet wird, wird über `NODE_EXTRA_CA_CERTS`, `SSL_CERT_FILE`, `CURL_CA_BUNDLE`, `GIT_SSL_CAINFO`, `CARGO_HTTP_CAINFO` usw. in die Sandbox übergeben, und der Pfad zum Bündel wird der `allowRead`-Berechtigung der Sitzung hinzugefügt, damit das Sandbox-Konto es öffnen kann.
### Windows-spezifische Konfiguration
Die plattformübergreifenden Blöcke `filesystem` und `network` gelten wie oben beschrieben. Windows-spezifische Einstellungen befinden sich unter `windows`:
- `windows.proxyPortRange` — `[low, high]` inklusiver Portbereich, an den die JS-Proxys gebunden werden. **Muss** mit dem Bereich übereinstimmen, der an `windows-install --proxy-port-range` übergeben wird (Standard `[60080, 60089]`) — die WFP-Loopback-PERMIT-Regel deckt nur diesen Bereich ab.
- `windows.sublayerGuid` — WFP-Sublayer-GUID, unter der die Filter installiert wurden. Weglassen, um den Kompilierzeit-Standard zu verwenden; nur setzen, wenn Unternehmenswerkzeuge die Filter unter einem benutzerdefinierten Sublayer installiert haben.
- `windows.srtWin.path` — Pfad zur `srt-win`-Binärdatei. Weglassen, um die gebündelte `vendor/srt-win/<arch>/srt-win.exe` aufzulösen. Setzen, wenn die CLI von `srt-win` in eine Multical-Binärdatei eingebettet wird; Spawns übergeben dann `--srt-win` als `argv[1]`, damit der Dispatcher des Einbettenden an `srt_win::run_from_args` weiterleiten kann.
### Bekannte Einschränkungen
- **Zertifikatswiderruf unter schannel.** Der CRL/OCSP-Abruf von CryptoAPI erfolgt über WinHTTP unter dem Token des Aufrufers und ignoriert die Proxy-Umgebung, sodass er durch den WFP-Egress-Filter blockiert wird. Tools, die schannel mit standardmäßig aktivierter Widerrufsprüfung verwenden, schlagen mit `CRYPT_E_REVOCATION_OFFLINE` (`0x80092013`) fehl, sofern der Widerruf nicht pro Tool deaktiviert wird: `curl --ssl-no-revoke`, `git -c http.schannelCheckRevoke=false`, `CARGO_HTTP_CHECK_REVOKE=false`. `Invoke-WebRequest`, .NET `HttpClient` und `gh` prüfen den Widerruf standardmäßig nicht und sind nicht betroffen. Ein CRL-Ausstellungsort, der über den Loopback-Proxy bereitgestellt wird, ist geplant, um diese Problemumgehung zu entfernen.
- **Pro-benutzer-Installationen von Tools sind nicht erreichbar.** Der sandboxierte Prozess läuft als `srt-sandbox`, nicht als Sie, sodass Tools, die unter Ihrem Profil installiert sind (nvm/fnm-verwaltetes Node, Pro-benutzer-`winget`/Scoop-Pakete, `pip install --user`, `%LOCALAPPDATA%\Programs\…`), auf dem geerbten `PATH` aufgelöst, aber vom Sandbox-Konto nicht geöffnet werden können. Bevorzugen Sie maschinenweite Installationen (`Program Files`, `choco`/`winget --scope machine`) oder fügen Sie die spezifischen Profilpfade zu `filesystem.allowRead` hinzu.
- **Pro-Ausführung-Überschreibungen von `filesystem.allowRead` / `filesystem.allowWrite` werden nicht unterstützt.** Sitzungsweite `allowRead`/`allowWrite` (in der an `initialize()` übergebenen Konfiguration) funktionieren wie oben beschrieben; die Übergabe pro Befehl in `customConfig` von `wrapWithSandbox` wirft einen Fehler — Berechtigungen werden sitzungsweit über `srt-win acl grant` bei `initialize()` angewendet, und `srt-win exec` setzt nur Pro-Ausführung-Verweigerungen um.
- **`proxyAuthToken` ist in der Befehlszeile des Runners sichtbar.** Die Proxy-Umgebung (einschließlich `HTTP_PROXY=http://srt:<token>@127.0.0.1:…`) wird dem Zwei-Hop-Runner als `--env`-Argumente auf der argv von `srt-win exec` übergeben, sodass das Token von jedem lokalen Prinzipal gelesen werden kann, der den Runner-Prozess für `PROCESS_QUERY_LIMITED_INFORMATION` öffnen kann. Das Token existiert, damit der sandboxierte Prozess sich beim Loopback-Proxy authentifizieren kann, ist also kein Geheimnis gegenüber der Sandbox selbst; auf einem Einzelbenutzer-Entwicklungsrechner ist dies im Allgemeinen akzeptabel, aber auf einem gemeinsam genutzten Host behandeln Sie die Proxy-Allowlist als für andere Prinzipale derselben Sitzung erreichbar.
- **DNS-Auflösung über den System-Resolver ist nicht eingezäunt.** `getaddrinfo()` wird vom `Dnscache`-Dienst bedient, der als `NETWORK SERVICE` läuft, sodass die Namensauflösung gelingt, obwohl der anschließende `connect()` vom sandboxierten Prozess blockiert wird. Tools, die ihr eigenes UDP/53 verwenden (`nslookup`, `dig`), sind eingezäunt. Dies spiegelt das macOS-Verhalten wider.
### Deinstallation```powershell
npx @anthropic-ai/sandbox-runtime windows-uninstall
Entfernt den WFP-Filtersatz, das Konto srt-sandbox und dessen Profil, die Gruppe sandbox-runtime-users und entfernt den Schlüssel HKLM\SOFTWARE\sandbox-runtime (Anmeldedaten, Marker, CA-Eintrag) — eine UAC-Eingabeaufforderung. %ProgramData%\sandbox-runtime (das CA-Schlüsselmaterial) bleibt erhalten; löschen Sie es (und %LOCALAPPDATA%\sandbox-runtime pro Benutzer) manuell für eine vollständige Bereinigung.
npm install
npm run build
npm test
npm run typecheck
npm run lint
npm run format
### Seccomp-Binaries erstellen
Der BPF-Filter und der `apply-seccomp`-Lader werden aus C-Quellcode in `vendor/seccomp-src/` über `npm run build:seccomp` kompiliert (nur Linux; benötigt `gcc` und `libseccomp-dev`). CI führt dies vor den Tests auf jeder Linux-Architektur aus, und der Release-Workflow erstellt beide Architekturen und bündelt sie im veröffentlichten Paket.
## Implementierungsdetails
### Architektur der Netzwerk-Isolation
Die Sandbox führt HTTP- und SOCKS5-Proxy-Server auf dem Host-Rechner aus, die alle Netzwerkanfragen basierend auf den Berechtigungsregeln filtern:
1. **HTTP/HTTPS-Datenverkehr**: Ein HTTP-Proxy-Server fängt Anfragen ab und validiert sie gegen erlaubte/gesperrte Domains
2. **Anderer Netzwerkverkehr**: Ein SOCKS5-Proxy behandelt alle anderen TCP-Verbindungen (SSH, Datenbankverbindungen usw.)
3. **Durchsetzung von Berechtigungen**: Die Proxys setzen die `permissions`-Regeln aus Ihrer Konfiguration durch
**Plattformspezifische Proxy-Kommunikation:**
- **Linux**: Anfragen werden über das Dateisystem über Unix-Domain-Sockets weitergeleitet (unter Verwendung von `socat` zur Überbrückung). Der Netzwerk-Namespace wird aus dem Bubblewrap-Container entfernt, sodass der gesamte Netzwerkverkehr über die Proxys laufen muss.
- **macOS**: Das Seatbelt-Profil erlaubt nur die Kommunikation mit bestimmten Localhost-Ports, an denen die Proxys lauschen. Der gesamte andere Netzwerkzugriff ist blockiert.
- **Windows**: Ein WFP-`ALE_AUTH_CONNECT`-Filter blockiert jeden ausgehenden Connect vom `srt-sandbox`-Konto, außer Loopback zum konfigurierten Proxy-Portbereich. Die Proxys binden innerhalb dieses Bereichs. Umgebungsvariablen (`HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, …) zeigen Tools auf die Proxys, aber der WFP-Filter ist die Grenze – ein Prozess, der sie ignoriert oder entfernt, ist dennoch eingezäunt.
### Dateisystem-Isolation
Dateisystemeinschränkungen werden auf Betriebssystemebene durchgesetzt:
- **macOS**: Verwendet `sandbox-exec` mit dynamisch generierten Seatbelt-Profilen, die erlaubte Lese-/Schreibpfade festlegen
- **Linux**: Verwendet `bubblewrap` mit Bind-Mounts, die Verzeichnisse basierend auf der Konfiguration als schreibgeschützt oder lesbar/schreibbar markieren
- **Windows**: Schreibt additive `(OI)(CI)`-explizite ACEs für die `srt-sandbox`-SID auf die konfigurierten Pfade (ALLOW auf `allowRead`/`allowWrite`, DENY auf `denyRead`/`denyWrite`) und entfernt sie dann bei `reset()`
**Standard-Dateisystemberechtigungen:**
- **Lesen** (Deny-dann-Allow): Standardmäßig überall erlaubt. Sie können große Bereiche sperren und dann bestimmte Pfade darin wieder erlauben. `allowRead` hat Vorrang vor `denyRead`.
- Beispiel: `denyRead: ["~/.ssh"]`, um den Zugriff auf SSH-Schlüssel zu blockieren
- Beispiel: `denyRead: ["/Users"], allowRead: ["."]`, um ganz `/Users` zu blockieren, außer dem Arbeitsbereich
- Leeres `denyRead: []` = voller Lesezugriff (nichts gesperrt)
- **Schreiben** (nur-Allow): Standardmäßig überall gesperrt. Sie müssen Pfade explizit erlauben.
- Beispiel: `allowWrite: [".", "/tmp"]`, um Schreibzugriff auf das aktuelle Verzeichnis und /tmp zu erlauben
- Leeres `allowWrite: []` = kein Schreibzugriff (nichts erlaubt)
- `denyWrite` erstellt Ausnahmen innerhalb erlaubter Pfade (Deny hat Vorrang)
**Die Rangfolge ist für Lesen vs. Schreiben bewusst umgekehrt:** `allowRead` überschreibt `denyRead`, während `denyWrite` `allowWrite` überschreibt. So können Sie lesbare Bereiche innerhalb gesperrter Bereiche aussparen und geschützte Bereiche innerhalb beschreibbarer Bereiche aussparen.
### Pflicht-Sperrpfade (automatisch geschützte Dateien)
Bestimmte sensible Dateien und Verzeichnisse sind **immer gegen Schreibzugriffe blockiert**, selbst wenn sie in einen erlaubten Schreibpfad fallen. Dies bietet Defense-in-Depth gegen Sandbox-Escapes und Konfigurationsmanipulation.
**Immer blockierte Dateien:**
- Shell-Konfigurationsdateien: `.bashrc`, `.bash_profile`, `.zshrc`, `.zprofile`, `.profile`
- Git-Konfigurationsdateien: `.gitconfig`, `.gitmodules`
- Andere sensible Dateien: `.ripgreprc`, `.mcp.json`
**Immer blockierte Verzeichnisse:**
- IDE-Verzeichnisse: `.vscode/`, `.idea/`
- Claude-Konfigurationsverzeichnisse: `.claude/commands/`, `.claude/agents/`
- Git-Hooks und -Konfiguration: `.git/hooks/`, `.git/config`
Diese Pfade werden automatisch blockiert – Sie müssen sie nicht zu `denyWrite` hinzufügen. Beispielsweise schlägt selbst mit `allowWrite: ["."]` das Schreiben auf `.bashrc` oder `.git/hooks/pre-commit` fehl:```bash
$ srt 'echo "malicious" >> .bashrc'
/bin/bash: .bashrc: Operation not permitted
$ srt 'echo "bad" > .git/hooks/pre-commit'
/bin/bash: .git/hooks/pre-commit: Operation not permitted
Hinweis (Linux): Unter Linux blockieren obligatorische Deny-Pfade nur Dateien, die bereits existieren. Nicht vorhandene Dateien in diesen Mustern können durch den Bind-Mount-Ansatz von bubblewrap nicht blockiert werden. macOS verwendet Glob-Muster, die sowohl vorhandene als auch neue Dateien blockieren.
Linux-Suchtiefe: Unter Linux verwendet die Sandbox ripgrep, um in Unterverzeichnissen innerhalb erlaubter Schreibpfade nach gefährlichen Dateien zu suchen. Standardmäßig durchsucht sie aus Leistungsgründen bis zu 3 Ebenen tief. Sie können dies mit mandatoryDenySearchDepth konfigurieren:```json
{
"mandatoryDenySearchDepth": 5,
"filesystem": {
"allowWrite": ["."]
}
}
- Standard: `3` (durchsucht bis zu 3 Ebenen tief)
- Bereich: `1` bis `10`
- Höhere Werte bieten mehr Schutz, aber langsamere Leistung
- Dateien im aktuellen Arbeitsverzeichnis (Tiefe 0) sind unabhängig von dieser Einstellung immer geschützt
### Unix-Socket-Einschränkungen (Linux)
Unter Linux verwendet die Sandbox **seccomp BPF (Berkeley Packet Filter)**, um die Erstellung von Unix-Domain-Sockets auf Syscall-Ebene zu blockieren. Dies bietet eine zusätzliche Sicherheitsebene, um zu verhindern, dass Prozesse neue Unix-Domain-Sockets für lokale IPC erstellen (sofern nicht ausdrücklich erlaubt).
**So funktioniert es:**
1. **Eingebauter BPF-Filter**: Das Paket enthält eine statische `apply-seccomp`-Binärdatei für x64 und arm64 mit dem darin kompilierten seccomp-BPF-Filter. Der Filter ist architekturspezifisch, aber libc-unabhängig, sodass die Binärdatei sowohl mit glibc als auch mit musl funktioniert.
2. **Laufzeiterkennung**: Die Sandbox erkennt automatisch die Architektur Ihres Systems und verwendet die passende `apply-seccomp`-Binärdatei.
3. **Syscall-Filterung**: Der BPF-Filter fängt den `socket()`-Syscall ab und blockiert die Erstellung von `AF_UNIX`-Sockets, indem er `EPERM` zurückgibt. Dies verhindert, dass sandboxierter Code neue Unix-Domain-Sockets erstellt.
4. **Zweistufige Anwendung mithilfe der apply-seccomp-Binärdatei**:
- Äußeres bwrap erstellt die Sandbox mit Dateisystem-, Netzwerk- und PID-Namespace-Einschränkungen
- Netzwerk-Bridge-Prozesse (socat) starten innerhalb der Sandbox (benötigen Unix-Sockets)
- apply-seccomp erstellt einen verschachtelten User+PID+Mount-Namespace und mountet `/proc` neu
- Innerhalb des verschachtelten Namespace fungiert apply-seccomp als PID 1 (nicht-dumpbarer Init/Reaper)
- apply-seccomp forkt, wendet den seccomp-Filter über `prctl()` an und führt den Benutzerbefehl aus
- Der Benutzerbefehl läuft mit allen Sandbox-Einschränkungen plus Blockierung der Unix-Socket-Erstellung
**PID-Namespace-Isolation**: Der verschachtelte PID-Namespace stellt sicher, dass der Benutzerbefehl keinen Prozess sehen oder adressieren kann, der ohne den seccomp-Filter läuft (bwrap-Init, der Shell-Wrapper oder die socat-Helfer). Dies hält die seccomp-Grenze unabhängig von `kernel.yama.ptrace_scope` intakt, da ungefilterte Helfer über `ptrace` oder `/proc/N/mem` nicht erreichbar sind. Das innere PID 1 setzt `PR_SET_DUMPABLE=0`, sodass es ebenfalls nicht ptracebar ist. Wenn die Erstellung des verschachtelten Namespace fehlschlägt, bricht apply-seccomp ab, anstatt ohne Isolation zu laufen.
**Sicherheitsbeschränkungen**: Der Filter blockiert `socket(AF_UNIX, ...)` sowie die Syscalls `io_uring_setup`/`io_uring_enter`/`io_uring_register` (die letzten drei, weil `IORING_OP_SOCKET` unter Linux 5.19+ andernfalls die `socket()`-Regel umgehen würde). Er verhindert keine Operationen an Unix-Socket-Dateideskriptoren, die von übergeordneten Prozessen geerbt oder über `SCM_RIGHTS` übergeben wurden. Für die meisten Sandbox-Szenarien reicht das Blockieren der Socket-Erstellung aus, um unbefugte IPC zu verhindern.
**Null Laufzeitabhängigkeiten**: Vorgefertigte statische apply-seccomp-Binärdateien und vorab generierte BPF-Filter sind für die Architekturen x64 und arm64 enthalten. Zur Laufzeit sind keine Kompilierungswerkzeuge oder externen Abhängigkeiten erforderlich.
**Architekturunterstützung**: x64 und arm64 werden mit vorgefertigten Binärdateien vollständig unterstützt. Andere Architekturen werden derzeit nicht unterstützt. Um Sandboxing ohne Unix-Socket-Blockierung auf nicht unterstützten Architekturen zu verwenden, setzen Sie `allowAllUnixSockets: true` in Ihrer Konfiguration.
### Erkennung und Überwachung von Verstößen
Wenn ein sandboxierter Prozess versucht, auf eine eingeschränkte Ressource zuzugreifen:
1. **Blockiert die Operation** auf Betriebssystemebene (gibt `EPERM`-Fehler zurück)
2. **Protokolliert den Verstoß** (plattformspezifische Mechanismen)
3. **Benachrichtigt den Benutzer** (in Claude Code wird dadurch eine Berechtigungsabfrage ausgelöst)
**macOS**: Die Sandbox-Laufzeit greift auf den System-Sandbox-Verstoßprotokollspeicher von macOS zu. Dies bietet Echtzeit-Benachrichtigungen mit detaillierten Informationen darüber, was versucht wurde und warum es blockiert wurde. Dies ist derselbe Mechanismus, den Claude Code zur Erkennung von Verstößen verwendet.```bash
# View sandbox violations in real-time
log stream --predicate 'process == "sandbox-exec"' --style syslog
Linux: Bubblewrap bietet keine integrierte Verstoßberichterstattung. Verwenden Sie strace, um Systemaufrufe zu verfolgen und blockierte Operationen zu identifizieren:```bash
strace -f srt 2>&1 | grep EPERM
strace -f -e trace=open,openat,stat,access srt 2>&1 | grep EPERM
strace -f -e trace=network srt 2>&1 | grep EPERM
### Erweitert: Eigener Proxy
Für anspruchsvollere Netzwerkfilterung können Sie die Sandbox so konfigurieren, dass sie Ihren eigenen Proxy anstelle der integrierten verwendet. Dies ermöglicht:
- **Datenverkehrsinspektion**: Verwenden Sie Tools wie [mitmproxy](https://mitmproxy.org/), um Datenverkehr zu inspizieren und zu modifizieren
- **Benutzerdefinierte Filterlogik**: Implementieren Sie komplexe Regeln, die über einfache Domain-Allowlists hinausgehen
- **Audit-Protokollierung**: Protokollieren Sie alle Netzwerkanfragen für Compliance oder Debugging
**Beispiel mit mitmproxy:**```bash
# Start mitmproxy with custom filtering script
mitmproxy -s custom_filter.py --listen-port 8888
Hinweis: Die benutzerdefinierte Proxy-Konfiguration wird im neuen Konfigurationsformat noch nicht unterstützt. Diese Funktion wird in einer zukünftigen Version hinzugefügt.
Wichtiger Sicherheitshinweis: Selbst mit Domain-Allowlists können Exfiltrationsvektoren existieren. Beispielsweise ermöglicht das Zulassen von github.com einem Prozess, in jedes Repository zu pushen. Mit einem benutzerdefinierten MITM-Proxy und entsprechender Zertifikatseinrichtung können Sie bestimmte API-Aufrufe überprüfen und filtern, um dies zu verhindern.
allowUnixSockets kann versehentlich Zugriff auf leistungsstarke Systemdienste gewähren, die zu Sandbox-Umgehungen führen können. Wenn sie beispielsweise verwendet wird, um Zugriff auf /var/run/docker.sock zu gewähren, würde dies effektiv Zugriff auf das Hostsystem durch Ausnutzung des Docker-Sockets ermöglichen. Benutzer werden ermutigt, sorgfältig zu überlegen, welche Unix-Sockets sie durch die Sandbox zulassen.$PATH, Systemkonfigurationsverzeichnisse oder Benutzer-Shell-Konfigurationsdateien (.bashrc, .zshrc) kann zur Codeausführung in unterschiedlichen Sicherheitskontexten führen, wenn andere Benutzer oder Systemprozesse auf diese Dateien zugreifen.enableWeakerNestedSandbox, der die Ausführung in Docker-Umgebungen ohne privilegierte Namespaces ermöglicht. Diese Option schwächt die Sicherheit erheblich und sollte nur in Fällen verwendet werden, in denen anderweitig zusätzliche Isolation durchgesetzt wird.enableWeakerNetworkIsolation aktiviert den Zugriff auf com.apple.trustd.agent wieder, der für Go-Programme erforderlich ist, um TLS-Zertifikate über das macOS-Security-Framework zu verifizieren. Dies eröffnet einen potenziellen Datenextfiltrationsvektor über den trustd-Dienst und sollte nur aktiviert werden, wenn eine Go-TLS-Verifizierung erforderlich ist (z. B. bei Verwendung von httpProxyPort mit einem MITM-Proxy und benutzerdefinierter CA).allowAppleEvents aktiviert das Senden von Apple Events und Launch-Services-Öffnungsanfragen wieder ((allow appleevent-send), (allow lsopen) sowie Mach-Lookups für com.apple.coreservices.appleevents, com.apple.CoreServices.coreservicesd und com.apple.coreservices.quarantine-resolver), die open, osascript und URL-öffnende Helfer benötigen. Mit diesen erlaubten Funktionen kann ein sandboxierter Befehl beliebige Anwendungen ohne Benutzeraufforderung starten, und gestartete Anwendungen laufen vollständig außerhalb der Sandbox – diese Option entfernt also die Codeausführungsisolation, nicht nur schwächt sie sie. Das Skripten bereits laufender Anwendungen über Apple Events wird zusätzlich durch die macOS-TCC-Automatisierungseinwilligung eingeschränkt, das Starten über open jedoch nicht. Aktivieren Sie dies nur, wenn Befehle innerhalb der Sandbox tatsächlich URLs oder Anwendungen öffnen müssen.Linux-Proxy-Umgehung: Verwendet derzeit Umgebungsvariablen (HTTP_PROXY, HTTPS_PROXY, ALL_PROXY), um Datenverkehr durch Proxys zu leiten. Dies funktioniert für die meisten Anwendungen, kann jedoch von Programmen ignoriert werden, die diese Variablen nicht berücksichtigen, was dazu führt, dass sie keine Verbindung zum Internet herstellen können.
Zukünftige Verbesserungen:
Proxychains-Unterstützung: Hinzufügen der Unterstützung für proxychains mit LD_PRELOAD unter Linux, um Netzwerkaufrufe auf einer niedrigeren Ebene abzufangen und die Umgehung zu erschweren
Linux-Verletzungsüberwachung: Implementierung einer automatischen strace-basierten Verletzungserkennung für Linux, integriert in den Verletzungsspeicher. Derzeit müssen Linux-Benutzer strace manuell ausführen, um Verletzungen zu sehen, im Gegensatz zu macOS, das eine automatische Verletzungsüberwachung über den Systemprotokollspeicher bietet.