Gå til innholdet

Sandkasse-backender

Backend Verdi Plattform Tilgjengelighet
Innelukket VM microvm macOS, Linux, Windows (microVM-hypervisor) Sonderingstyrt på microVM-kjøretiden; gjelder interaktive terminaler — skallet kjører inne i en stasjon, ikke på verten
Native native macOS (Seatbelt), Linux og WSL2 (bubblewrap) Sonderes ved oppstart; Linux nekter en kjøring som krever skrivenekter på filnavnmønstre, noe bubblewrap ikke kan håndheve
Ingen none Alle Standardverdien ved parsing, terminalens standard og reserveløsningen når ingen backend er tilgjengelig eller --sandbox off er satt

SandboxBackend.fromName returnerer none for en lagret verdi som er null eller ukjent. En lagret "docker" tilordnes native.

microvm er den eneste backenden med en kjernegrense — arbeidslasten kjører faktisk ikke på verten. Den er aldri en stille reserveløsning i noen av retningene: å be om den eksplisitt på en vert som ikke kan starte en VM, feiler høylytt («jeg ba om en VM og fikk laptopen min» er den ene forringelsen innelukkingen ikke har råd til), og bare en uspesifisert standard faller ned til native, med en logglinje som sier det. Kjøringens faktiske backend rapporteres tilbake til klienten og merkes, så en terminal kan aldri påstå å være innelukket mens den kjører på verten. Livssyklus, bilder og utgående trafikk for selve VM-en dekkes av stasjonsreferansen.

Windows har ingen native sandkasse. NativeSandboxAdapter.probe returnerer available: false på alle verter som ikke er macOS eller Linux/WSL2. Agentutsending på Windows bruker derfor none. microvm-backenden er separat: den er sonderingstyrt på microVM-kjøretiden og gjelder interaktive terminaler og stasjoner, ikke innpakking av bash på verten.

Det er sonderingen som avgjør om håndheving skjer. Den kjøres én gang, ved serveroppstart.

Vert available Merknad / hint
macOS true sandbox-exec (Seatbelt) — navneromsisolasjon, ingen kjernegrense
Linux eller WSL2 med bwrap og socat true bubblewrap — navneromsisolasjon, ingen kjernegrense
Linux eller WSL2 som mangler ett av verktøyene false requiresInstall: true, med et installasjonstips som navngir de manglende pakkene
Enhver annen plattform false Native sandkasse tilbys ikke på denne plattformen

Serveren logger resultatet på én oppstartslinje: agent sandbox ON pluss merknaden, no OS-native agent sandbox on this host pluss hintet, eller agent sandbox DISABLED by --sandbox off. GET /healthz inneholder ikke noe sandkassefelt.

--sandbox / CC_SERVER_SANDBOX godtar on (standard) eller off. Det er en opt-out, ikke en aktivering: on betyr «pakk inn når verten tilbyr en backend», aldri «krev én».

Bruker Apples sandkassemekanisme Seatbelt (det samme systemet som macOS App Sandbox bruker).

Den genererte profilen er tillatende som standard ((allow default)) og skjærer ut nekter, fordi en profil som nekter alt som standard, gjør et interaktivt skall ubrukelig — det er for mange dyld-, XPC- og Mach-kall til å liste opp. Den praktiske konsekvensen er at en agent fortsatt kan lese mesteparten av verten; de registrerte utsjekkingene dine beskyttes av eksplisitte skrive- og omdøpingsnekter, ikke av usynlighet.

  • Filsystemlesing: nektet for de hemmelige stiene (~/.ssh, ~/.aws, ~/.gnupg, ~/.config/gh, ~/Library/Keychains og resten av lesenekt-settet)
  • Filsystemskriving: nullstilt til nekt, deretter eksplisitte tillatelser for understier, med de obligatoriske nekt-stiene (shell-rc-filer, .git/hooks, Claude-konfigurasjon, beskyttede utsjekkinger) blokkert selv inne i en skrivbar rot. file-write-unlink nektes på hver nektet sti og dens overordnede, så en omdøping ikke kan omgå en skrivenekt
  • Prosess: process-exec-nekter for de alltid-farlige binærene, pluss en blokkering av å kjøre noe fra en skrivbar katalog
  • Nettverk: begrenset til proxyportene i samme prosess pluss DNS — loopback er ikke tillatt i sin helhet, og Unix-sokler er ikke tillatt. Proxyene håndhever domenetillatelseslisten per økt (se Utgående nettverkstrafikk)
  • Konfigurasjon: profiler genereres ved hver oppstart fra SandboxSpec

Krav:

  • sandbox-exec (/usr/bin/sandbox-exec), en del av enhver macOS-installasjon — ingen ekstra verktøy kreves

Bruker bubblewrap (bwrap) til å opprette mount- og PID-navnerom.

  • Filsystem: oppretter et mount-navnerom der bare de bundne stiene er synlige
  • Nettverk: kjører i et ikke-delt nettverksnavnerom; trafikken når vertsproxyene gjennom socat-broer over Unix-sokler
  • Prosess: PID-navneromsisolasjon

Krav:

  • bubblewrap og socat installert (sudo apt-get install bubblewrap socat på Debian/Ubuntu)
  • Støtte for navnerom i kjernen (standard på moderne Linux)

Bubblewrap kan skyggelegge en eksisterende sti, men kan ikke forby en ny .env-, *.key- eller *.pem-fil inne i en skrivbar bind-montering. Den vanlige utsendingspolicyen krever disse filnavnmønster-nektene, så native agentutsending feiler lukket på Linux/WSL2 selv når sonderingen finner bubblewrap. Den kjører ikke med en stille svakere policy. En backend med filnavnregler på opprettelsestidspunktet kreves for å gjenopprette native utsending på Linux. Å slå av sandkassen er en eksplisitt opt-out uten begrensninger, ikke en likeverdig omvei.

Ingen sandkasse. Prosessen kjører direkte på verten med vertens filsystem-, nettverks- og prosesstilgang. ACP og harnessets bash-verktøy får fortsatt miljøsanering og kommandopolicyen; Claude Code gjennom NoSandboxAdapter arver vertens miljø. Dette er det agentutsending faller tilbake på når en vert ikke har noen tilgjengelig backend eller når --sandbox off er satt, og det er terminalens standard når en klient ikke angir noen.

Terminalen sandkasseinnpakkes på egne vilkår, ikke av utsendingssonderingen. defaultBackend til TerminalSessionService er none, og cc_server overstyrer den ikke, så en terminaløkt kjører vertens skall med mindre klienten eksplisitt ber om native — terminalpanelet i skrivebordsappen gjør ikke det.

Når native bes, pakkes skallet inn gjennom SandboxManager under en fast terminalprofil: $HOME og øktens arbeidskatalog er skrivbare, nettverket er åpent, og lesing av ~/.ssh, ~/.aws, ~/.gnupg, ~/.config/gh og ~/Library/Keychains er nektet. Kodeverttokenet som bare kan lese, og push-gatewayen gjelder ikke — de er utsendingssaker. Hvis innpakningen ikke støttes, feiler økten i stedet for å vise et native-merke på en PTY med vertens skall.

Når en sandkasse startes, håndheves utgående nettverkstilgang av proxyer i samme prosess, ikke av brannmurregler i kjernen. På en vert uten tilgjengelig backend gjelder ingenting av dette, og en startet prosess når nettverket nøyaktig slik serverbrukeren ville gjort.

  • Sandkassekjøretiden kjører en HTTP/HTTPS-proxy og en SOCKS5-proxy på 127.0.0.1 inne i cc_server-prosessen, ett par per begrenset økt (http_proxy.dart, socks_proxy.dart). Samtidige kjøringer deler ikke et par.
  • Sandkasseinnpakkede prosesser får proxy-miljøvariabler (HTTP_PROXY/HTTPS_PROXY → HTTP-proxyen, ALL_PROXY → SOCKS-proxyen; GIT_SSH_COMMAND ruter git-over-SSH gjennom SOCKS-proxyen). På Linux er nettverksnavnerommet ikke delt, så proxyene er den eneste veien ut; på macOS deler sandkassen vertens loopback og snakker direkte med dem.
  • Målverten for hver tilkobling matches mot øktens domenetillatelsesliste; alt annet nektes. To jokertegnformer, hver med nøyaktig én *: en ledende *.example.com matcher et hvilket som helst subdomene (inkludert a.b.example.com), men ikke toppdomenet selv; en midtstilt merkelapp som i bedrock.*.amazonaws.com matcher nøyaktig én merkelapp (bedrock.us-east-1.amazonaws.com, ikke bedrock.evil.attacker.amazonaws.com).
  • Tillatelseslisten løses opp per økt fra den kuraterte grunnlinjen (kBaselineAllowedDomains: LLM-leverandører, Git-hosting, pakkeregistre), pluss GitHub-domenene (kGithubDomains), pluss SandboxSpec.egressAllowlist. Utsendingsstien sender aldri ekstra egressAllowlist-oppføringer, så i praksis får hver kjøring grunnlinjen pluss GitHub.
  • En fast nekteliste (kBaselineDeniedDomains: endepunkter for skymetadata, telemetrimottak) har forrang foran alle tillatelser.
  • networkEnabled: false starter fortsatt proxyene per økt, men tillatelseslisten er tom, så hver utgående tilkobling avvises. Utsendingen setter verdien når kjøringen starter, ut fra regelen Bruk nettverket: nekt slår av nettverket, tillat og spør først lar det stå på.

Spesifikasjonen som sendes til SandboxPort.launch:

Felt Type Beskrivelse
sessionId String Stabil øktidentifikator (vanligvis område-ID-en)
workspaceId String ID-en til arbeidsområdet som eier den
agentId String? Agenten som for tiden er bundet til sandkassen, hvis noen
bindMounts List<SandboxBindMount> Vert→gjest-monteringer; sandkassen ser bare vertsstiene som er listet opp her
networkEnabled bool (standard true) Settes ved utsending ut fra regelen for utgående nettverkstrafikk (av bare når den løses opp til nekt). Når den er av, starter proxyene per økt fortsatt, men tillatelseslisten er tom, så hver utgående tilkobling avvises
egressAllowlist List<String> (standard []) Ekstra tillatte utgående domener; jokertegn støttes (*.example.com, pluss en midtform med én merkelapp). Utsending fyller aldri ut dette, så en innpakket kjøring får den kuraterte grunnlinjen pluss GitHub-domenene
guestWorkdir String? Standard arbeidskatalog inne i sandkassen; enkelte exec-kall kan overstyre den
mode Mode (standard chat) Skjærer ut skrivereglene for filsystemet: chat holder bind-monteringer skrivbare; review, plan og orchestrate er skrivebeskyttet
protectedPaths List<String> (standard []) Vertsstier som aldri må være skrivbare inne i sandkassen, i noen modus
runnerStateDirs List<String> (standard []) Vertskataloger der kjøreren holder sin egen tilstand, skrivbare i alle moduser (en CLAUDE_CONFIG_DIR administrert av Control Center er den gjeldende)
execGrantRoots List<String> (standard []) Katalogtrær godkjent av operatøren som åpner exec-blokkeringen for skrivbare kataloger på macOS igjen. Linux ignorerer dem — bwrap har ingen exec-blokkering for $HOME å åpne igjen

protectedPaths inneholder de opprinnelige registrerte repo-utsjekkingene, løst opp per utsending fra arbeidsområdets repoer. Agenter jobber utelukkende i copy-on-write-worktrees per samtale, så originalene må aldri være skrivbare fra innsiden av sandkassen — på macOS ville Seatbelts generelle skrivetillatelse for $HOME ellers ha gjort dem skrivbare via bash. De går inn i skrivenekt-settet for hemmeligheter i alle moduser, også chat.

Hver lesenekt- og skrivenekt-sti sendes ut i både sin litterale skrivemåte og sin symlenke-oppløste. Kjernen matcher en nektregel mot den oppløste stien, så en regel skrevet mot en symlenket sti utløses aldri — og på macOS er det det vanlige tilfellet snarere enn det eksotiske, siden /tmp løses opp til /private/tmp og /var/folders/… til /private/var/folders/…. Oppføringer som inneholder * eller ?, behandles som glob-mønstre og røres ikke; en sti som ikke løses opp, beholdes som skrevet.

Felt Type Beskrivelse
hostPath String Absolutt sti på verten
guestPath String Sti inne i sandkassen (med den native sandkassen er denne lik hostPath; beholdt for symmetri mellom adaptere)
readOnly bool (standard false) Monter skrivebeskyttet når den er sann

Returneres av SandboxPort.launch:

Felt Type Beskrivelse
sessionId String Øktidentifikator
backend SandboxBackend Hvilken backend som kjører
state SandboxState Livssyklustilstand
error Object? Settes når state er error
details Map<String, Object?> Adapterprivat bokføring (arbeidskatalog, PID, profilbanesti osv.)
Tilstand Beskrivelse
created Spesifikasjonen er opprettet, men VM-en har ikke startet ennå
warm Kjører og klar til å utføre kommandoer
active Kjører en kommando akkurat nå
suspended Satt på pause / lagret som sjekkpunkt på disk for å spare RAM
destroyed Revet ned; håndtaket er ikke lenger gyldig
error Oppstart mislyktes — se SandboxHandle.error
Hendelsestype Beskrivelse
stdout Standard utdata fra sandkassen
stderr Standard feilutdata fra sandkassen
exit Sandkasseprosessen avsluttet (har med exitCode)
starting Sandkassen starter opp
ready Sandkassen er klar til å ta imot exec-kall
killed Prosessen drept av verten (OOM, tidsavbrudd, manuell stopp)
violation En sandkassepolicy ble brutt (har med en SandboxViolation)
Felt Type Beskrivelse
action String Det nektede verbet (f.eks. file-read*, network-outbound)
target String Stien eller verten som var mål for den nektede operasjonen
raw String? Rå logglinje, nyttig for feilsøking