Zurück zu den Updates
New releaseSep 12, 2026

sandbox-runtime v0.0.76

Ein leichtgewichtiges Sandboxing-Tool zur Durchsetzung von Dateisystem- und Netzwerkbeschränkungen für beliebige Prozesse auf Betriebssystemebene, ohne dass ein Container erforderlich ist.

Teilen

Anthropic Sandbox Runtime (srt)

Ein leichtgewichtiges Sandboxing-Tool zur Durchsetzung von Dateisystem- und Netzwerkeinschränkungen für beliebige Prozesse auf Betriebssystemebene, ohne dass ein Container erforderlich ist.

srt verwendet native Sandboxing-Primitive des Betriebssystems (sandbox-exec unter macOS, bubblewrap unter Linux) und proxy-basierte Netzwerkfilterung. Es kann verwendet werden, um das Verhalten von Agents, lokalen MCP-Servern, Bash-Befehlen und beliebigen Prozessen in einer Sandbox zu isolieren.

Beta Research Preview

Die Sandbox Runtime ist eine Research Preview, die für Claude Code entwickelt wurde, um sicherere KI-Agents zu ermöglichen. Sie wird als frühe Open-Source-Vorschau verfügbar gemacht, um dem breiteren Ökosystem zu helfen, sicherere agentische Systeme zu entwickeln. Da es sich um eine frühe Research Preview handelt, können sich APIs und Konfigurationsformate weiterentwickeln. Wir freuen uns über Feedback und Beiträge, um KI-Agents standardmäßig sicherer zu machen!

Installation```bash

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

Überblick

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 explizit nur die Lücken, die Sie benötigen.

Wichtige Funktionen:

  • Netzwerkeinschränkungen: Steuern Sie, auf welche Hosts/Domains über HTTP/HTTPS und andere Protokolle zugegriffen werden kann
  • Dateisystemeinschränkungen: Steuern Sie, welche Dateien/Verzeichnisse gelesen/geschrieben werden können
  • Unix-Socket-Einschränkungen: Steuern Sie den Zugriff auf lokale IPC-Sockets
  • Verletzungsüberwachung: Nutzen Sie unter macOS den Sandbox-Verletzungsprotokollspeicher des Systems für Echtzeitwarnungen

Beispielanwendungsfall: Sandboxing von MCP-Servern

Ein wichtiger Anwendungsfall ist das Sandboxing von Model Context Protocol (MCP)-Servern, um deren Fähigkeiten einzuschränken. Um beispielsweise 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 konfigurieren Sie Einschränkungen in ~/.srt-settings.json:```json { "filesystem": { "denyRead": [], "allowWrite": ["."], "denyWrite": ["~/sensitive-folder"] }, "network": { "allowedDomains": [], "deniedDomains": [] } }

Nun 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'

Funktionsweise

Die Sandbox verwendet Betriebssystem-Primitive, um Einschränkungen durchzusetzen, die für den gesamten Prozessbaum gelten:

  • macOS: Verwendet sandbox-exec mit dynamisch generierten Seatbelt-Profilen
  • Linux: Verwendet bubblewrap zur Containerisierung mit Netzwerk-Namespace-Isolierung
  • Windows: Führt den sandboxed Prozess unter einem dedizierten lokalen Benutzerkonto srt-sandbox aus, mit einem Windows Filtering Platform-Egress-Zaun, der auf die SID dieses Kontos abgestimmt ist, sowie expliziten ACEs pro Sitzung auf dem Arbeitsverzeichnis

0d1c612947c798aef48e6ab4beb7e8544da9d41a-4096x2305

Duales Isolationsmodell

Sowohl Dateisystem- als auch Netzwerkisolierung sind für effektives Sandboxing erforderlich. Ohne Dateiisolierung könnte ein kompromittierter Prozess SSH-Schlüssel oder andere sensible Dateien exfiltrieren. Ohne Netzwerkisolierung könnte ein Prozess aus der Sandbox entkommen und uneingeschränkten Netzwerkzugriff erlangen.

Dateisystemisolierung erzwingt Lese- und Schreibbeschränkungen:

  • Lesen (Deny-then-Allow-Muster): Standardmäßig ist Lesezugriff überall erlaubt. Sie können breite Bereiche verweigern (z. B. /Users) und dann bestimmte Pfade darin wieder erlauben (z. B. .). allowRead hat Vorrang vor denyRead — das Gegenteil von Schreiben, wo denyWrite Vorrang vor allowWrite hat. Ein denyRead-Eintrag, der spezifischer ist als der allowRead-Bereich, in den er fällt (z. B. denyRead: ["**/.env"] oder ["./secrets"] mit allowRead: ["."]), bleibt dennoch verweigert.
  • Schreiben (Allow-only-Muster): Standardmäßig ist Schreibzugriff überall verweigert. Sie müssen Pfade explizit erlauben (z. B. ., /tmp). Eine leere Allow-Liste bedeutet keinen Schreibzugriff.

Netzwerkisolierung (Allow-only-Muster): Standardmäßig ist jeglicher Netzwerkzugriff verweigert. Sie müssen Domains explizit erlauben. Eine leere allowedDomains-Liste bedeutet keinen Netzwerkzugriff. Netzwerkverkehr wird über Proxy-Server geleitet, die auf dem Host laufen:

  • Linux: Anfragen werden über das Dateisystem über einen Unix-Domain-Socket geleitet. Der Netzwerk-Namespace des sandboxed Prozesses wird vollständig entfernt, sodass der gesamte Netzwerkverkehr über die Proxies laufen muss, die auf dem Host laufen (lauschen auf Unix-Sockets, die in die Sandbox bind-mounted sind)

  • macOS: Das Seatbelt-Profil erlaubt Kommunikation nur zu einem bestimmten localhost-Port. Die Proxies lauschen auf diesem Port und schaffen so einen kontrollierten Kanal für jeglichen Netzwerkzugriff

  • Windows: Ein maschinenweiter WFP-Filtersatz blockiert alle ausgehenden Verbindungen, die vom srt-sandbox-Konto ausgehen, außer Loopback zum Proxy-Portbereich. Die Proxies lauschen innerhalb dieses Bereichs und schaffen so einen kontrollierten Kanal für jeglichen Netzwerkzugriff

Sowohl HTTP/HTTPS (über HTTP-Proxy) als auch anderer TCP-Verkehr (über SOCKS5-Proxy) werden durch diese Proxies vermittelt, die Ihre Domain-Allowlists und -Denylists durchsetzen.

Weitere Details zum Sandboxing in Claude Code finden Sie unter:

Architektur```

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-Tool

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

Als Bibliothek```typescript

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`).** Verletzungen, die während der Ausführung eines umschlossenen Befehls beobachtet werden (Seatbelt-Logzeilen, Seccomp-Ereignisse, Proxy-Ablehnungen), werden unter einem Zuordnungsschlüssel gespeichert, und `annotateStderrWithSandboxFailures(key, stderr)` / `getViolationsForCommand(key)` schlagen sie unter demselben Schlüssel nach. Standardmäßig ist der Schlüssel die umschlossene Zeichenkette selbst. Übergeben Sie eine undurchsichtige `commandId` pro Aufruf (z. B. eine Tool-Use-ID), um stattdessen danach zu schlüsseln — empfohlen: Schlüssel werden anhand ihrer ersten 100 Zeichen verglichen, sodass lange Befehle, die ein Präfix teilen, andernfalls querverknüpft würden, und ein erneuter Lauf desselben Textes 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 zusätzlich `commandText: '<cmd>'`: Dies ist das, wogegen die Befehlsmuster von `ignoreViolations` abgeglichen werden und was jede Verletzung als ihren `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)

Verfügbare Exporte```typescript

// 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 mit dem Flag `--settings` angeben:```bash
srt --settings /path/to/srt-settings.json <command>

Vollständiges Konfigurationsbeispiel```json

{ "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 **Allow-only-Muster** – jeglicher Netzwerkzugriff ist standardmäßig verweigert.

- `network.allowedDomains` – Array erlaubter Domains (unterstützt Wildcards 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 stimmen mit jedem Port überein.
  - IPv6-Literale müssen in Klammern gesetzt werden, RFC 3986-konform: `[::1]`, `[2001:db8::1]:443`. Ein nicht geklammerter Eintrag mit mehreren Doppelpunkten wird als mehrdeutig abgelehnt (`2001:db8::1:443` ist selbst eine gültige Adresse).
- `network.deniedDomains` – Array verweigerter Domains (wird zuerst geprüft, hat Vorrang vor allowedDomains). Gleiches `:port`-Suffix, und ein bloßes `*` (oder `*:22`) wird für Deny-all akzeptiert.
- `network.deniedDomainReasons` – Optionale Zuordnung von einem `deniedDomains`-Eintrag (übereinstimmend per exakter Zeichenkette) zu einem modellseitigen Grund, der in der `<sandbox_violations>`-Zeile erscheint, wenn dieser Eintrag eine Verbindung verweigert – nennen Sie, was blockiert wird und die zulässige Alternative (z. B. `{"github.com:22": "SSH pushes to GitHub are blocked; use an https:// remote"}`). Einträge ohne Grund melden einen generischen. Für SSH-Ziele (Port 22) wird der Grund auch in-band übermittelt: Ein SSH-Client, der durch einen No-Auth-SOCKS-ProxyCommand (z. B. BSD `nc -X 5`) getunnelt wird, 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 abschneidet und Nicht-ASCII-Zeichen escapt.
- `network.allowLocalBinding` – Bindung an lokale Ports erlauben (Boolean, Standard: false)

**Prüfung der aufgelösten Adresse.** Die Allow/Deny-Listen stimmen per _Name_ überein, aber wer das DNS eines erlaubten Namens kontrolliert (oder eines beliebigen Labels unter einem erlaubten Wildcard), kontrolliert, worauf dieser auflöst. Bevor also ein erlaubter **Hostname** direkt angewählt wird, löst der Proxy ihn einmal auf, verwirft jede Adresse in einer verweigerten Menge und verbindet sich mit einer überlebenden Adresse (die Adresse, die die Prüfung bestanden hat, ist die angewählte – es gibt keinen zweiten Lookup). Wenn nichts überlebt, wird die Verbindung wie jede andere Richtlinienverweigerung abgelehnt: HTTP/CONNECT erhalten `403` (`X-Proxy-Error: blocked-by-sandbox-runtime`, der Grund im Body), SOCKS erhält "connection not allowed by ruleset", und eine Zeile `deny network-outbound host:port (resolved to a loopback address)` – die die Klasse der Adresse benennt (Loopback, Link-Local, die dieses Hosts, Cloud-Metadaten, deny-gelistet, gelistet, …), nicht die Adresse selbst, die nur das Debug-Log trägt – wird im Violation-Store aufgezeichnet.

Die verweigerte Menge ist: Loopback (`127.0.0.0/8`, `::1`), Unspecified (`0.0.0.0/8`, `::`), Link-Local (`169.254.0.0/16`, `fe80::/10`), Multicast (`224.0.0.0/4`, `ff00::/8`), Broadcast, die Cloud-Instanz-Metadaten-/Plattform-Endpunkte, die außerhalb von Link-Local liegen (`100.100.100.200`, `168.63.129.16`, `192.0.0.192`, `fd00:ec2::/32`, `fd20:ce::254`, `fd00:c1::a9fe:a9fe`, `fd00:42::42`), jede Adresse, die derzeit einer der eigenen Netzwerkschnittstellen dieses Hosts zugewiesen ist (ein Dienst, der an `0.0.0.0` gebunden ist, antwortet auf der LAN- oder globalen Adresse genauso wie auf Loopback), jedes in `deniedDomains` gelistete IP-Literal (unter Berücksichtigung seines `:port`, falls vorhanden) und alles in `deniedResolvedAddresses`. IPv4-Einträge stimmen auch mit den IPv6-Formen überein, die eine IPv4-Adresse tragen – IPv4-gemappte, IPv4-kompatible und IPv4-translatierte Adressen, das NAT64-Well-Known-Präfix (`64:ff9b::/96`) und 6to4 (`2002::/16`) werden anhand der eingebetteten IPv4-Adresse beurteilt. Das Local-Use-NAT64-Präfix `64:ff9b:1::/48` und netzwerkspezifische Präfixe werden nicht dekodiert – ihr Layout (RFC 6052 erlaubt die IPv4 an mehreren Positionen) kann nicht allein aus der Adresse erkannt werden; listen Sie in einem solchen Netzwerk die Übersetzungen der von Ihnen verweigerten Bereiche durch das Präfix auf (z. B. `<prefix>::a00:0/104` für `10.0.0.0/8`). Adressen, die diesen Host erreichen, ohne ihm zugewiesen zu sein – eine 1:1-NAT-Public-Adresse einer Cloud-Instanz, ein Router-Port-Forward, ein Container- oder VM-Host-Gateway-Alias – sind nicht automatisch abgedeckt; listen Sie sie in `deniedResolvedAddresses` auf.

Was die Prüfung unberührt lässt: Allowlist-Einträge, die **IP-Literale sind** (das Allow-Listen von `127.0.0.1:3000` ist eine explizite Entscheidung) – und ebenso kann ein Hostname auf eine ansonsten verweigerte Adresse auflösen, wenn dieses IP-Literal (auf diesem Port) selbst in `allowedDomains` steht, da das Erreichen per Name nichts gewährt, was der Literal-Eintrag nicht gewährt (ein IP-Literal in `deniedDomains` gewinnt weiterhin, genau wie bei einer Literal-Anfrage). Ein Dev-Setup, bei dem `myapp.test` über `/etc/hosts` auf einen lokalen Server zeigt, allow-listet also `["myapp.test", "127.0.0.1:3000"]`; es gibt keine separate Ausnahmeliste. `localhost` und Namen unter `.localhost` lösen auf Loopback (oder ein allow-gelistetes Literal) und nichts anderes auf. Die Prüfung wird nicht für Verbindungen ausgewertet, die über `parentProxy` (einschließlich eines aus `HTTP_PROXY` / `HTTPS_PROXY` in srt's eigener Umgebung übernommenen) oder `mitmProxy` geroutet werden – dieser Hop löst den Namen auf und besitzt seine eigene Adressrichtlinie – und sie regelt nur, was der Proxy anwählt: unter macOS lässt `allowLocalBinding` den sandboxed Prozess separat Loopback-Ports erreichen, ohne überhaupt durch den Proxy zu gehen.

- `network.deniedResolvedAddresses` – Zusätzliche IP-Adressen / CIDR-Bereiche (IPv4 oder IPv6, ungeklammert, beliebiger Port), auf die erlaubte Hostnamen nicht auflösen dürfen. Private-Use-Space wird standardmäßig nicht verweigert, weil das Allow-Listen eines Intranet-Hostnamens legitim ist; listen Sie es hier auf, wenn allow-gelistete Namen daraus herausgehalten werden müssen, z. B. `["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "100.64.0.0/10", "fc00::/7"]`. Listen Sie IPv4- und IPv6-Bereiche getrennt auf – ein IPv6-Bereich, der breit genug ist, um den IPv4-gemappten Block (`::ffff:0:0/96`) abzudecken, wie etwa `::/0`, stimmt in manchen Runtimes mit IPv4-Antworten überein, in anderen nicht, verlassen Sie sich also nicht darauf, um IPv4 zu verweigern.

**TLS-Terminierung** (`network.tlsTerminate`, experimentell): Wenn gesetzt, werden HTTPS-CONNECTs in-process terminiert, damit SRT die entschlüsselten Anfragen sehen (und über `network.filterRequest` filtern) kann. Der sandboxed Prozess wird auf ein Trust-Bundle verwiesen, das die MITM-CA (`caCertPath`/`caKeyPath`, oder eine ephemere CA, falls weggelassen) plus die regulären Roots des Hosts enthält, sodass sowohl proxy-generierte Zertifikate als auch echte Upstream-Zertifikate verifiziert werden.

- `network.tlsTerminate.excludeDomains` – Domain-Muster (gleiche Syntax wie `allowedDomains`), die **nicht** terminiert werden. Übereinstimmende 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-Injection gelten nicht für ihren HTTPS-Verkehr. Verwenden Sie dies für die beiden Fälle, die TLS-Terminierung grundsätzlich bricht:
  - **mTLS-Upstreams** – nur der In-Sandbox-Client hält das Client-Zertifikat, sodass der Proxy die Verbindung nicht in dessen 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 an dieses Trust-Bundle angehängt werden, nach der MITM-CA und den regulären Roots des Hosts. Ausgeschlossene (nicht terminierte) Hosts werden vom Client innerhalb der Sandbox verifiziert, und die von SRT gesetzten Trust-Umgebungsvariablen (`SSL_CERT_FILE`, `GIT_SSL_CAINFO`, ...) _ersetzen_ die eigene Trust-Konfiguration jedes Tools, sodass eine standortlokale Root (z. B. eine interne mTLS-CA) im Bundle enthalten sein muss, sonst können diese Hosts niemals verifiziert werden. Nur die `CERTIFICATE`-Blöcke jeder Datei werden in das Bundle kopiert (alles andere, z. B. ein privater Schlüssel in einem kombinierten PEM, wird niemals der Sandbox ausgesetzt); Dateien, die fehlen, unlesbar sind oder keinen PEM-`CERTIFICATE`-Block enthalten, werden übersprungen, sodass es sicher ist, Pfade aufzulisten, die nur auf manchen 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):

EinstellungmacOSLinux
allowUnixSockets: string[]Allowlist von Socket-PfadenIgnoriert (seccomp kann nicht nach Pfad filtern)
allowAllUnixSockets: booleanAlle Sockets erlaubenseccomp-Blockierung deaktivieren

Unix-Sockets sind auf beiden Plattformen standardmäßig blockiert.

  • macOS: Verwende allowUnixSockets, um bestimmte Pfade zu erlauben (z. B. ["/var/run/docker.sock"]), oder allowAllUnixSockets: true, um alle zu erlauben.
  • Linux: Die Blockierung verwendet seccomp-Filter (nur x64/arm64). Wenn seccomp nicht verfügbar ist, sind Sockets uneingeschränkt und es wird eine Warnung angezeigt. Verwende allowAllUnixSockets: true, um die Blockierung explizit zu deaktivieren.

Dateisystem-Konfiguration

Verwendet zwei verschiedene Muster:

Lese-Beschränkungen (Deny-then-Allow-Muster) – alle Lesezugriffe standardmäßig erlaubt:

  • filesystem.denyRead – Array von Pfaden, für die Lesezugriff verweigert wird. Leeres Array = voller Lesezugriff.
  • filesystem.allowRead – Array von Pfaden, für die Lesezugriff innerhalb verweigerter Bereiche wieder erlaubt wird (hat Vorrang vor denyRead). Hinweis: Dies ist das Gegenteil von Schreiben, wo denyWrite Vorrang vor allowWrite hat.

Schreib-Beschränkungen (Allow-only-Muster) – alle Schreibzugriffe standardmäßig verweigert:

  • filesystem.allowWrite – Array von Pfaden, für die Schreibzugriff erlaubt wird. Leeres Array = kein Schreibzugriff.
  • filesystem.denyWrite – Array von Pfaden, für die Schreibzugriff innerhalb erlaubter Pfade verweigert wird (hat Vorrang vor allowWrite)

Pfad-Syntax (macOS):

Pfade unterstützen auf macOS git-artige 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 beliebigen 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/"] – Schreibzugriff auf das gesamte src/-Verzeichnis erlauben
  • "allowWrite": ["src/**/*.ts"] – Schreibzugriff auf 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)

Pfad-Syntax (Linux):

Linux unterstützt derzeit kein Glob-Matching. Verwende nur wörtliche Pfade:

  • "allowWrite": ["src/"] – Schreibzugriff auf 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 erlauben

Alle Plattformen:

  • Pfade können absolut (z. B. /home/user/.ssh) oder relativ zum aktuellen Arbeitsverzeichnis (z. B. ./src) sein
  • ~ wird zum Home-Verzeichnis des Benutzers erweitert

Weitere Konfiguration

  • ignoreViolations – Objekt, das Befehlsmuster auf Arrays von Pfaden abbildet, in denen Verstöße ignoriert werden sollen
  • enableWeakerNestedSandbox – Aktiviert den schwächeren Sandbox-Modus für Docker-Umgebungen (Boolean, Standard: false)
  • javaAgentJarPath – macOS/Linux: absoluter Pfad zu srt-proxy-agent.jar, dem JVM-Agent, der über JAVA_TOOL_OPTIONS injiziert wird (siehe „JVM-Tools" unter Netzwerkisolierung). Wird nur von Konsumenten benötigt, die sandbox-runtime bündeln und das Jar separat ausliefern; eine normale npm-Installation findet es unter vendor/java-proxy-agent/.
  • enableWeakerNetworkIsolation – Erlaubt den Zugriff auf com.apple.trustd.agent in der macOS-Sandbox (Boolean, Standard: false). Dies ist erforderlich, damit Go-Programme (gh, gcloud, terraform, kubectl usw.) TLS-Zertifikate verifizieren können, wenn httpProxyPort mit einem MITM-Proxy und benutzerdefinierter CA verwendet wird. Sicherheitswarnung: Das Aktivieren öffnet einen potenziellen Datenexfiltrationsvektor über den trustd-Dienst.
  • allowAppleEvents – Erlaubt das Senden von Apple Events und Launch Services Open Requests aus der macOS-Sandbox (Boolean, Standard: false). Ohne dies schlagen Befehle wie open, osascript und alles, was URLs öffnet oder Skripte anderer Apps über AppleScript startet, mit dem AppleScript-Fehler -600 („Application isn't running") oder LaunchServices-Fehlern (-10822, -54) fehl. Sicherheitswarnung: Das Aktivieren bedeutet, dass die Sandbox keine Code-Ausführungsisolierung mehr bietet. Ein sandboxed 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 ist zusätzlich durch die TCC-Automatisierungszustimmung des Benutzers pro App eingeschränkt. Embedder sollten diese Option nur aus vertrauenswürdiger Benutzerkonfiguration beziehen – niemals aus projektlokalen Dateien in einem ausgecheckten Repository, da dies einem von einem Angreifer erstellten Projekt ermöglichen würde, seine eigenen Sandbox-Berechtigungen zu erweitern.

Häufige Konfigurationsrezepte

GitHub-Zugriff erlauben (alle notwendigen 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-Verletzungen zu vermeiden:```bash
srt "jest --no-watchman"

Watchman greift auf Dateien außerhalb der Sandbox-Grenzen zu, was zu Berechtigungsfehlern führt. Wenn es deaktiviert wird, kann Jest stattdessen mit dem integrierten Datei-Watcher ausgeführt werden.

Plattformunterstützung

  • macOS: Verwendet sandbox-exec mit benutzerdefinierten Profilen (keine zusätzlichen Abhängigkeiten)
  • Linux: Verwendet bubblewrap (bwrap) für die Containerisierung
  • Windows: Alpha — verwendet einen mitgelieferten srt-win.exe-Helfer (keine zusätzlichen Abhängigkeiten). Siehe Windows (Alpha) unten für Einrichtung, Sicherheitsmodell und bekannte Einschränkungen

Plattformspezifische Abhängigkeiten

Linux erfordert:

  • bubblewrap - Container-Laufzeit
    • Ubuntu/Debian: apt-get install bubblewrap
    • Fedora: dnf install bubblewrap
    • Arch: pacman -S bubblewrap
  • socat - Socket-Relay für Proxy-Bridging
    • Ubuntu/Debian: apt-get install socat
    • Fedora: dnf install socat
    • Arch: pacman -S socat
  • ripgrep - Schnelles Suchwerkzeug zur Erkennung von Deny-Pfaden
    • Ubuntu/Debian: apt-get install ripgrep
    • Fedora: dnf install ripgrep
    • Arch: pacman -S ripgrep

Hinweis zu Ubuntu 24.04+: Diese Versionen aktivieren standardmäßig kernel.apparmor_restrict_unprivileged_userns, was unshare(CLONE_NEWUSER) erlaubt, aber die Fähigkeiten aus dem resultierenden Namespace entfernt. Sowohl bubblewrap als auch die seccomp-Isolationsschicht benötigen fähigkeitstragende User-Namespaces. Deaktivieren Sie die Einschränkung mit:```bash sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0

oder ein AppArmor-Profil hinzufügen, das den relevanten Binärdateien `userns` gewährt.

**Optionale Linux-Abhängigkeiten (für seccomp-Fallback):**

Das Paket enthält vorgefertigte seccomp-BPF-Filter für x86-64- und arm-Architekturen. Diese Abhängigkeiten werden nur benötigt, wenn Sie sich auf einer anderen Architektur befinden, für die keine vorgefertigten 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 erhöhter `windows-install`-Schritt ist erforderlich — siehe unten.

## Windows (Alpha)

Die Windows-Unterstützung ist **Alpha**. Der sandboxed 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-Zaun, der auf die SID des Sandbox-Kontos abgestimmt ist, und sitzungsspezifische explizite ACEs, die dieser SID Zugriff auf konfigurierte Dateisystempfade gewähren oder verweigern.

### Einrichtung

Einmal pro Maschine ausführen (selbsterhöhend; eine UAC-Aufforderung):```powershell
npx @anthropic-ai/sandbox-runtime windows-install

Dies richtet das lokale Benutzerkonto srt-sandbox ein (mit einem zufälligen Passwort, das DPAPI-verschlüsselt in HKLM\SOFTWARE\sandbox-runtime gespeichert wird — maschinenweit, sodass Flotteninstallationen, 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 abgestimmt ist. Es ist idempotent — ein erneutes Ausführen rotiert das Passwort des Sandbox-Kontos und gleicht den Filtersatz ab.

Es ist keine Abmeldung erforderlich. Die WFP-Filter sind auf die SID des dedizierten Sandbox-Kontos abgestimmt, sodass Ihr eigenes Netzwerk, Ihre Dienste und jeder andere Prinzipal auf der Maschine nicht betroffen sind.

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 einem umsetzbaren Fehler fehl.

Die programmatische Installation/Deinstallation wird als installWindowsSandbox() / uninstallWindowsSandbox() exportiert.

Sicherheitsmodell

Der sandboxed Befehl läuft als das Konto srt-sandbox, nicht als der aufrufende Benutzer. Der mitgelieferte Helfer srt-win.exe führt einen Zwei-Hop-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 wird.

Das Ausführen unter einer eigenen Benutzer-SID schließt strukturell die Escape-Klasse des Surrogate-Spawn (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 des Bandes zu starten vermag, trägt weiterhin die SID srt-sandbox, unterliegt also weiterhin dem WFP-Egress-Zaun und hat keine Rechte an den 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 srt-sandbox trägt. Der sandboxed Prozess erreicht das Internet nur über die JS-HTTP/SOCKS5-Proxies, die in diesem Bereich lauschen; ein Prozess, der seine Proxy-Umgebung entfernt und direkt verbindet, wird im Kernel blockiert.

Dateisystemisolation wird durch NTFS-Discretionary-ACLs erzwungen. Das Konto srt-sandbox hat keine inhärenten Rechte an den Dateien des aufrufenden Benutzers, daher schreibt die Sandbox bei initialize() additive, vererbende explizite ACEs nur für die SID srt-sandbox — sie schreibt niemals den vorhandenen Sicherheitsdeskriptor eines Pfads um oder ersetzt ihn:

  • filesystem.allowWrite → ein vererbender MODIFY ALLOW ACE (READ|WRITE|EXECUTE|DELETE, wobei FILE_DELETE_CHILD zurückgehalten wird). Der sandboxed Prozess kann Dateien innerhalb des Arbeitsbaums erstellen, ändern und löschen; das Zurückhalten von FILE_DELETE_CHILD von der Gewährung dient der Defense-in-Depth für die untenstehenden Deny-Stempel, nicht als Schutz des Baumstamms.
  • filesystem.allowRead → ein vererbender READ|EXECUTE ALLOW ACE
  • filesystem.denyRead / filesystem.denyWrite → ein vererbender DENY ACE auf das Ziel, plus ein vererbender FILE_DELETE_CHILD DENY auf dessen übergeordnetes Verzeichnis — zusammen mit dem zurückgehaltenen FILE_DELETE_CHILD bei der Arbeitsbaum-Gewährung hindert dies den sandboxed Prozess daran, einen verweigerten Pfad über sein übergeordnetes Verzeichnis umzubenennen oder zu löschen

reset() entfernt jeden ACE, den diese Sitzung hinzugefügt hat (refcounted über die gleichzeitigen Hosts dieses Benutzers via der benutzerspezifischen Sitzungs-DB; 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 Teilbaum). Glob-Muster werden zur initialize()-Zeit in konkrete Pfade expandiert — ein passender Pfad, der später erscheint, ist nicht abgedeckt.

TLS-Terminierung unter Windows

network.tlsTerminate erfordert, dass die MITM-CA im CurrentUser\Root-Zertifikatsspeicher des Sandbox-Benutzers vorhanden ist (schannel — das TLS-Backend, das von System32\curl.exe, PowerShell Invoke-WebRequest, .NET und dem Standard-Backend von git verwendet wird — vertraut nur dem OS-Speicher, nicht Umgebungsvariablen). Dies ist ein Installationsschritt, 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 Session-CA mit der installierten und schlägt bei Abweichung mit einer aussagekräftigen Meldung fehl, sodass eine veraltete CA aus der Installationszeit TLS innerhalb der Sandbox nicht stillschweigend brechen kann.

OpenSSL-basierte Clients (msys2 `curl`, `git -c http.sslBackend=openssl`, Node, Python, cargo) werden durch die Env-Var-Vertrauensschicht abgedeckt: dasselbe Trust-Bundle, 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 des Bundles wird dem `allowRead`-Grant der Session 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, in dem die JS-Proxies binden. **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 dem die Filter installiert wurden. Weglassen, um den Compile-Time-Standard zu verwenden; nur setzen, wenn Enterprise-Tooling die Filter unter einem benutzerdefinierten Sublayer installiert hat.
- `windows.srtWin.path` — Pfad zur `srt-win`-Binärdatei. Weglassen, um die paketierte `vendor/srt-win/<arch>/srt-win.exe` aufzulösen. Setzen, wenn die CLI von `srt-win` in eine Multicall-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-Zaun blockiert wird. Tools, die schannel mit standardmäßig aktivierter Widerrufsprüfung verwenden, schlagen mit `CRYPT_E_REVOCATION_OFFLINE` (`0x80092013`) fehl, es sei denn, der Widerruf wird pro Tool deaktiviert: `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-Verteilungspunkt, der vom Loopback-Proxy bereitgestellt wird, ist geplant, um diesen Workaround zu beseitigen.
- **Pro-Benutzer-Tool-Installationen sind nicht erreichbar.** Der sandboxed Prozess läuft als `srt-sandbox`, nicht als Sie, sodass Tools, die unter Ihrem Profil installiert sind (nvm/fnm-verwaltetes Node, benutzerspezifische `winget`/Scoop-Pakete, `pip install --user`, `%LOCALAPPDATA%\Programs\…`), zwar im geerbten `PATH` aufgelöst werden, 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.
- **Per-Exec-Überschreibungen von `filesystem.allowRead` / `filesystem.allowWrite` werden nicht unterstützt.** Session-weite `allowRead`/`allowWrite` (in der an `initialize()` übergebenen Konfiguration) funktionieren wie oben beschrieben; sie pro Befehl in `wrapWithSandbox`s `customConfig` zu übergeben, wirft einen Fehler — Grants werden session-weit über `srt-win acl grant` bei `initialize()` angewendet, und `srt-win exec` bietet nur Per-Exec-Denies.
- **`proxyAuthToken` ist in der Kommandozeile des Runners sichtbar.** Die Proxy-Umgebung (einschließlich `HTTP_PROXY=http://srt:<token>@127.0.0.1:…`) wird an den Two-Hop-Runner als `--env`-Argumente in der argv von `srt-win exec` übergeben, sodass das Token für jeden lokalen Principal lesbar ist, der den Runner-Prozess für `PROCESS_QUERY_LIMITED_INFORMATION` öffnen kann. Das Token existiert, damit der sandboxed Prozess sich am Loopback-Proxy authentifizieren kann, ist also kein Geheimnis vor der Sandbox selbst; auf einer Single-User-Entwicklungsmaschine ist dies im Allgemeinen akzeptabel, aber auf einem gemeinsam genutzten Host sollten Sie die Proxy-Allowlist als für andere Principals derselben Session erreichbar behandeln.
- **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 erfolgreich ist, obwohl das anschließende `connect()` aus dem sandboxed Prozess blockiert wird. Tools, die ihr eigenes UDP/53 durchführen (`nslookup`, `dig`), sind eingezäunt. Dies entspricht dem Verhalten unter macOS.

### Deinstallation```powershell
npx @anthropic-ai/sandbox-runtime windows-uninstall

Entfernt das WFP-Filterset, das Konto srt-sandbox und dessen Profil, die Gruppe sandbox-runtime-users und entfernt den Schlüssel HKLM\SOFTWARE\sandbox-runtime (Anmeldeinformationen, Marker, CA-Eintrag) — eine UAC-Aufforderung. %ProgramData%\sandbox-runtime (das CA-Schlüsselmaterial) bleibt bestehen; lösche es (und %LOCALAPPDATA%\sandbox-runtime pro Benutzer) manuell für eine vollständige Bereinigung.

Entwicklung```bash

Install dependencies

npm install

Build the project

npm run build

Run tests

npm test

Type checking

npm run typecheck

Lint code

npm run lint

Format code

npm run format

### Seccomp-Binaries erstellen

Der BPF-Filter und der `apply-seccomp`-Loader 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 baut beide Architekturen und bündelt sie in das veröffentlichte Paket.

## Implementierungsdetails

### Netzwerkisolationsarchitektur

Die Sandbox betreibt HTTP- und SOCKS5-Proxy-Server auf dem Host-Rechner, die alle Netzwerkanfragen basierend auf Berechtigungsregeln filtern:

1. **HTTP/HTTPS-Verkehr**: Ein HTTP-Proxy-Server fängt Anfragen ab und validiert sie gegen erlaubte/verweigerte Domains
2. **Sonstiger Netzwerkverkehr**: Ein SOCKS5-Proxy verarbeitet alle anderen TCP-Verbindungen (SSH, Datenbankverbindungen usw.)
3. **Durchsetzung von Berechtigungen**: Die Proxies erzwingen die `permissions`-Regeln aus Ihrer Konfiguration

**Plattformspezifische Proxy-Kommunikation:**

- **Linux**: Anfragen werden über das Dateisystem über Unix-Domain-Sockets geleitet (unter Verwendung von `socat` als Brücke). Der Netzwerk-Namespace wird aus dem bubblewrap-Container entfernt, wodurch sichergestellt wird, dass der gesamte Netzwerkverkehr über die Proxies laufen muss.

- **macOS**: Das Seatbelt-Profil erlaubt die Kommunikation nur mit bestimmten localhost-Ports, an denen die Proxies lauschen. Jeglicher andere Netzwerkzugriff wird blockiert.

- **Windows**: Ein WFP-`ALE_AUTH_CONNECT`-Filter blockiert jede ausgehende Verbindung vom `srt-sandbox`-Konto außer Loopback zum konfigurierten Proxy-Portbereich. Die Proxies binden sich innerhalb dieses Bereichs. Umgebungsvariablen (`HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, …) verweisen Tools auf die Proxies, aber der WFP-Filter ist die Grenze — ein Prozess, der sie ignoriert oder zurücksetzt, ist dennoch eingezäunt.

**JVM-Tools (macOS/Linux):** Die JVM ignoriert `HTTPS_PROXY`/`NO_PROXY` und hat keine Umgebungsvariable für Proxy-Anmeldedaten — die Proxy-Auswahl erfolgt über die `https.proxyHost`-Systemeigenschaften, und die Anmeldedaten können nur über `java.net.Authenticator` bereitgestellt werden. Daher würden JVM-basierte Tools (Bazels gRPC-Remote-Cache, Gradle, Maven, …) andernfalls das Ziel direkt anwählen und fehlschlagen oder den Proxy ohne dessen Token erreichen und einen 407 erhalten. Um diese Lücke zu schließen, injiziert srt einen kleinen `-javaagent` über `JAVA_TOOL_OPTIONS` (die Umgebungsvariable enthält nur den Jar-Pfad, die Anmeldedaten bleiben in `HTTPS_PROXY`). Beim JVM-Start setzt der Agent `http[s].proxyHost`/`Port` und `http.nonProxyHosts` aus den Proxy-Umgebungsvariablen, aktiviert Basic Auth für CONNECT-Tunnel wieder und installiert einen Authenticator für den Proxy-Endpunkt. Explizite `-D`-Proxy-Eigenschaften auf der JVM-Kommandozeile gewinnen weiterhin, und alle geerbten `JAVA_TOOL_OPTIONS` bleiben erhalten (es sei denn, es handelt sich um eine verweigerte Anmeldedaten-Umgebungsvariable). Jede JVM gibt infolgedessen eine Zeile `Picked up JAVA_TOOL_OPTIONS: …` an stderr aus; eine jlink'd-Laufzeitumgebung, die ohne das `java.instrument`-Modul erstellt wurde, kann keine Agents laden und verweigert den Start unter der Sandbox — setzen Sie `JAVA_TOOL_OPTIONS` im Befehl für ein solches Tool zurück. Das Jar wird im npm-Paket als `vendor/java-proxy-agent/srt-proxy-agent.jar` ausgeliefert (Quelle: `vendor/java-proxy-agent-src/`; erstellt vom Release-Workflow oder lokal mit `npm run build:java-agent` — benötigt ein JDK ≥ 17). Wenn es nicht gefunden wird, bleibt `JAVA_TOOL_OPTIONS` unverändert und JVMs verhalten sich wie zuvor; Bundler können mit `javaAgentJarPath` auf ihre eigene Kopie verweisen.

### Dateisystemisolation

Dateisystembeschränkungen werden auf Betriebssystemebene durchgesetzt:

- **macOS**: Verwendet `sandbox-exec` mit dynamisch generierten Seatbelt-Profilen, die erlaubte Lese-/Schreibpfade angeben
- **Linux**: Verwendet `bubblewrap` mit Bind-Mounts, wobei Verzeichnisse basierend auf der Konfiguration als schreibgeschützt oder beschreibbar markiert werden
- **Windows**: Schreibt additive explizite `(OI)(CI)`-ACEs für die `srt-sandbox`-SID auf die konfigurierten Pfade (ALLOW bei `allowRead`/`allowWrite`, DENY bei `denyRead`/`denyWrite`) und entfernt sie dann bei `reset()`

**Standard-Dateisystemberechtigungen:**

- **Lesen** (deny-then-allow): Standardmäßig überall erlaubt. Sie können breite Bereiche verweigern 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` außer dem Arbeitsbereich zu blockieren
  - Leeres `denyRead: []` = voller Lesezugriff (nichts verweigert)

- **Schreiben** (allow-only): Standardmäßig überall verweigert. 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 absichtlich gegensätzlich für Lesen vs. Schreiben:** `allowRead` überschreibt `denyRead`, während `denyWrite` `allowWrite` überschreibt. Dadurch können Sie lesbare Bereiche innerhalb verweigerter Bereiche und geschützte Bereiche innerhalb beschreibbarer Bereiche herausarbeiten.

### Obligatorische Verweigerungspfade (automatisch geschützte Dateien)

Bestimmte sensible Dateien und Verzeichnisse sind **immer vom Schreiben ausgeschlossen**, selbst wenn sie innerhalb eines erlaubten Schreibpfads liegen. Dies bietet Defense-in-Depth gegen Sandbox-Escapes und Manipulation der Konfiguration.

**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 wird selbst mit `allowWrite: ["."]` das Schreiben in `.bashrc` oder `.git/hooks/pre-commit` fehlschlagen:```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 existierende Dateien in diesen Mustern können durch den Bind-Mount-Ansatz von bubblewrap nicht blockiert werden. macOS verwendet Glob-Muster, die sowohl existierende 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 sucht sie aus Performancegründen bis zu 3 Ebenen tief. Sie können dies mit mandatoryDenySearchDepth konfigurieren:```json { "mandatoryDenySearchDepth": 5, "filesystem": { "allowWrite": ["."] } }

- Standard: `3` (sucht bis zu 3 Ebenen tief)
- Bereich: `1` bis `10`
- Höhere Werte bieten mehr Schutz, aber langsamere Leistung
- Dateien im CWD (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 Sicherheitsschicht, um zu verhindern, dass Prozesse neue Unix-Domain-Sockets für lokale IPC erstellen (sofern nicht ausdrücklich erlaubt).

**Funktionsweise:**

1. **Eingebauter BPF-Filter**: Das Paket enthält eine statische `apply-seccomp`-Binärdatei für x64 und arm64 mit integriertem 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 durch Rückgabe von `EPERM`. Dies verhindert, dass sandboxed Code neue Unix-Domain-Sockets erstellen kann.

4. **Zweistufige Anwendung mithilfe der apply-seccomp-Binärdatei**:
   - Äußeres bwrap erstellt die Sandbox mit Dateisystem-, Netzwerk- und PID-Namespace-Einschränkungen
   - Netzwerkbrücken-Prozesse (socat) starten innerhalb der Sandbox (benötigen Unix-Sockets)
   - apply-seccomp erstellt einen verschachtelten Benutzer-+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-Isolierung**: Der verschachtelte PID-Namespace stellt sicher, dass der Benutzerbefehl keinen Prozess sehen oder adressieren kann, der ohne den seccomp-Filter läuft (bwrap's Init, der Shell-Wrapper oder die socat-Helfer). Dies hält die seccomp-Grenze intakt, unabhängig von `kernel.yama.ptrace_scope`, da ungefilterte Helfer nicht über `ptrace` oder `/proc/N/mem` erreichbar sind. Der innere PID 1 setzt `PR_SET_DUMPABLE=0`, sodass er ebenfalls nicht ptracebar ist. Wenn die Erstellung des verschachtelten Namespace fehlschlägt, bricht apply-seccomp ab, anstatt ohne Isolierung zu laufen.

**Sicherheitsbeschränkungen**: Der Filter blockiert `socket(AF_UNIX, ...)` und 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 auf Unix-Socket-Dateideskriptoren, die von übergeordneten Prozessen geerbt oder über `SCM_RIGHTS` übergeben wurden. Für die meisten Sandboxing-Szenarien reicht die Blockierung der Socket-Erstellung aus, um unbefugte IPC zu verhindern.

**Keine Laufzeitabhängigkeiten**: Vorgefertigte statische apply-seccomp-Binärdateien und vorab generierte BPF-Filter sind für x64- und arm64-Architekturen 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.

### Verstoßerkennung und Überwachung

Wenn ein sandboxed Prozess versucht, auf eine eingeschränkte Ressource zuzugreifen:

1. **Blockiert den Vorgang** auf Betriebssystemebene (gibt `EPERM`-Fehler zurück)
2. **Protokolliert den Verstoß** (plattformspezifische Mechanismen)
3. **Benachrichtigt den Benutzer** (in Claude Code löst dies eine Berechtigungsaufforderung aus)

**macOS**: Die Sandbox-Laufzeit greift auf den System-Sandbox-Verstoßprotokollspeicher von macOS zu. Dies bietet Echtzeitbenachrichtigungen mit detaillierten Informationen darüber, was versucht wurde und warum es blockiert wurde. Dies ist derselbe Mechanismus, den Claude Code zur Verstoßerkennung verwendet.```bash
# View sandbox violations in real-time
log stream --predicate 'process == "sandbox-exec"' --style syslog

Linux: Bubblewrap bietet keine integrierte Berichterstattung über Verstöße. Verwenden Sie strace, um Systemaufrufe zu verfolgen und blockierte Operationen zu identifizieren:```bash

Trace all denied operations

strace -f srt 2>&1 | grep EPERM

Trace specific file operations

strace -f -e trace=open,openat,stat,access srt 2>&1 | grep EPERM

Trace network operations

strace -f -e trace=network srt 2>&1 | grep EPERM

### Fortgeschritten: Eigenen Proxy verwenden

Für eine anspruchsvollere Netzwerkfilterung können Sie die Sandbox so konfigurieren, dass sie Ihren eigenen Proxy anstelle der integrierten verwendet. Dies ermöglicht:

- **Verkehrsinspektion**: Verwenden Sie Tools wie [mitmproxy](https://mitmproxy.org/), um den Datenverkehr zu inspizieren und zu verändern
- **Benutzerdefinierte Filterlogik**: Implementieren Sie komplexe Regeln, die über einfache Domain-Allowlists hinausgehen
- **Audit-Protokollierung**: Protokollieren Sie alle Netzwerkanfragen für Compliance- oder Debugging-Zwecke

**Beispiel mit mitmproxy:**```bash
# Start mitmproxy with custom filtering script
mitmproxy -s custom_filter.py --listen-port 8888

Hinweis: Eine benutzerdefinierte Proxy-Konfiguration wird im neuen Konfigurationsformat noch nicht unterstützt. Diese Funktion wird in einer zukünftigen Version hinzugefügt.

Wichtige Sicherheitsüberlegung: Selbst mit Domain-Allowlists können Exfiltrationsvektoren existieren. Wenn beispielsweise github.com erlaubt wird, kann ein Prozess in jedes beliebige Repository pushen. Mit einem benutzerdefinierten MITM-Proxy und ordnungsgemäßer Zertifikatseinrichtung können Sie bestimmte API-Aufrufe inspizieren und filtern, um dies zu verhindern.

Sicherheitseinschränkungen

  • Einschränkungen der Netzwerk-Sandboxing: Das Netzwerkfilterungssystem funktioniert, indem es die Domains einschränkt, mit denen Prozesse sich verbinden dürfen. Es inspiziert den durch den Proxy laufenden Datenverkehr ansonsten nicht, und die Benutzer sind dafür verantwortlich, sicherzustellen, dass sie in ihrer Richtlinie nur vertrauenswürdige Domains zulassen. Erlaubte Hostnamen werden zusätzlich vor einem direkten Verbindungsaufbau gegen eine verweigerte Menge aufgelöster Adressen geprüft (siehe Prüfung aufgelöster Adressen oben), sodass ein erlaubter Name nicht auf Loopback, Link-Local, die eigenen Adressen dieses Hosts oder eine IP, die Sie in deniedDomains aufgeführt haben, gerichtet werden kann; andere private Bereiche werden nur abgedeckt, wenn Sie sie in deniedResolvedAddresses auflisten (ein Wildcard-Eintrag für eine Domain, deren DNS Sie nicht kontrollieren, kann andernfalls auf Dienste in Ihrem LAN gerichtet werden), und Verbindungen, die über parentProxy/mitmProxy hinausgehen, verlassen sich für die entsprechende Prüfung auf diesen Hop.
Benutzer sollten sich der potenziellen Risiken bewusst sein, die sich aus der Zulassung breiter Domains wie `github.com` ergeben und die Datenexfiltration ermöglichen können. Außerdem kann es in manchen Fällen möglich sein, die Netzwerkfilterung durch [Domain Fronting](https://en.wikipedia.org/wiki/Domain_fronting) zu umgehen.
  • Privilegieneskalation über Unix-Sockets: Die Konfiguration allowUnixSockets kann unbeabsichtigt Zugriff auf mächtige Systemdienste gewähren, was zu Sandbox-Umgehungen führen könnte. Wenn sie beispielsweise verwendet wird, um Zugriff auf /var/run/docker.sock zu erlauben, würde dies effektiv Zugriff auf das Hostsystem gewähren, indem der Docker-Socket ausgenutzt wird. Benutzer werden angehalten, alle Unix-Sockets, die sie durch die Sandbox zulassen, sorgfältig zu prüfen.
  • Eskalation von Dateisystemberechtigungen: Übermäßig breite Schreibberechtigungen im Dateisystem können Privilegieneskalationsangriffe ermöglichen. Das Zulassen von Schreibzugriffen auf Verzeichnisse, die ausführbare Dateien in $PATH enthalten, auf Systemkonfigurationsverzeichnisse oder auf Benutzer-Shell-Konfigurationsdateien (.bashrc, .zshrc) kann zur Codeausführung in anderen Sicherheitskontexten führen, wenn andere Benutzer oder Systemprozesse auf diese Dateien zugreifen.
  • Stärke der Linux-Sandbox: Die Linux-Implementierung bietet starke Dateisystem- und Netzwerkisolation, enthält jedoch einen Modus enableWeakerNestedSandbox, der es ermöglicht, innerhalb von Docker-Umgebungen ohne privilegierte Namespaces zu arbeiten. Diese Option schwächt die Sicherheit erheblich und sollte nur in Fällen verwendet werden, in denen anderweitig zusätzliche Isolation erzwungen wird.
  • Schwächere Netzwerkisolation (macOS): Die Option enableWeakerNetworkIsolation reaktiviert den Zugriff auf com.apple.trustd.agent, der benötigt wird, damit Go-Programme TLS-Zertifikate über das macOS Security Framework verifizieren können. Dies öffnet einen potenziellen Datenexfiltrationsvektor über den trustd-Dienst und sollte nur aktiviert werden, wenn die Go-TLS-Verifikation erforderlich ist (z. B. bei Verwendung von httpProxyPort mit einem MITM-Proxy und benutzerdefinierter CA).
  • Apple Events (macOS): Die Option allowAppleEvents reaktiviert das Senden von Apple Events und Launch Services Open Requests ((allow appleevent-send), (allow lsopen) und mach-lookups für com.apple.coreservices.appleevents, com.apple.CoreServices.coreservicesd und com.apple.coreservices.quarantine-resolver), die open, osascript und URL-öffnende Hilfsprogramme benötigen. Wenn diese erlaubt sind, kann ein in der Sandbox ausgeführtes Kommando 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 ab. Das Skripten bereits laufender Anwendungen über Apple Events ist zusätzlich durch die macOS-TCC-Automatisierungseinwilligung beschränkt, aber das Starten über open ist es nicht. Aktivieren Sie dies nur, wenn Kommandos innerhalb der Sandbox wirklich URLs oder Anwendungen öffnen müssen.

Bekannte Einschränkungen und zukünftige Arbeiten

Linux-Proxy-Umgehung: Derzeit werden Umgebungsvariablen (HTTP_PROXY, HTTPS_PROXY, ALL_PROXY) verwendet, um Datenverkehr durch Proxys zu leiten. Dies funktioniert für die meisten Anwendungen, kann jedoch von Programmen ignoriert werden, die diese Variablen nicht respektieren, was dazu führt, dass sie keine Verbindung zum Internet herstellen können.

Zukünftige Verbesserungen:

  • Proxychains-Unterstützung: Unterstützung für proxychains mit LD_PRELOAD unter Linux hinzufügen, um Netzwerkaufrufe auf einer niedrigeren Ebene abzufangen und eine Umgehung schwieriger zu machen

  • Überwachung von Linux-Verstößen: Automatische strace-basierte Verstoßerkennung für Linux implementieren, integriert in den Verstoßspeicher. Derzeit müssen Linux-Benutzer strace manuell ausführen, um Verstöße zu sehen, anders als bei macOS, das über den Systemprotokollspeicher eine automatische Verstoßüberwachung bietet

Kategorien