Hoppa till innehåll

Sandlådebackends

Backend Värde Plattform Tillgänglighet
Avskild VM microvm macOS, Linux, Windows (microVM-hypervisor) Sondstyrd på microVM-körtiden; gäller interaktiva terminaler — skalet körs inuti en station, inte på värden
Inbyggd native macOS (Seatbelt), Linux och WSL2 (bubblewrap) Sonderas vid start; Linux vägrar en körning som kräver skrivnekanden för filnamnsglober, vilket bubblewrap inte kan framtvinga
Ingen none Alla Standard för parsern, terminalens standard och reservvägen när ingen backend finns eller --sandbox off är satt

SandboxBackend.fromName returnerar none för ett nullvärde eller ett okänt sparat värde. Ett sparat "docker" mappas till native.

microvm är den enda backenden med en kärngräns — arbetslasten körs verkligen inte på värden. Den är aldrig en tyst reservväg i någon riktning: att uttryckligen begära den på en värd som inte kan starta en VM misslyckas högt (”jag bad om en VM och fick min laptop” är den enda försämring avskiljningen inte har råd med), och bara en ospecificerad standard trappas ner till native, med en loggrada som säger det. Sessionens faktiska backend rapporteras tillbaka till klienten och märks upp, så en terminal kan aldrig påstå sig vara avskild medan den körs på värden. Livscykel, avbilder och utgående trafik för själva VM:en täcks av stationsreferensen.

Windows har ingen inbyggd sandlåda. NativeSandboxAdapter.probe returnerar available: false på varje värd som inte är macOS eller Linux/WSL2. Agentdispatch på Windows använder därför none. Backenden microvm är separat: den är sondstyrd på microVM-körtiden och gäller interaktiva terminaler och stationer, inte inlindning av bash på värden.

Det är sonderingen som avgör om tvånget tillämpas. Den körs en gång, vid serverns start.

Värd available Not / ledtråd
macOS true sandbox-exec (Seatbelt) — namnrymdsisolering, ingen kärngräns
Linux eller WSL2 med bwrap och socat true bubblewrap — namnrymdsisolering, ingen kärngräns
Linux eller WSL2 som saknar något av verktygen false requiresInstall: true, med en installationsledtråd som namnger de saknade paketen
Annan plattform false Inbyggd sandlåda erbjuds inte på den här plattformen

Servern loggar resultatet på en enda startrad: agent sandbox ON plus noten, no OS-native agent sandbox on this host plus ledtråden, eller agent sandbox DISABLED by --sandbox off. GET /healthz innehåller inget sandlådefält.

--sandbox / CC_SERVER_SANDBOX accepterar on (standard) eller off. Det är en opt-out, inte en aktivering: on betyder ”linda in när värden erbjuder en backend”, aldrig ”kräv en”.

Använder Apples sandlådemekanism Seatbelt (samma system som macOS App Sandbox använder).

Den genererade profilen är tillåtande som standard ((allow default)) och skär ut nekanden, eftersom en helt neka-som-standard-profil gör ett interaktivt skal obrukbart — det finns för många dyld-, XPC- och Mach-anrop att räkna upp. Den praktiska konsekvensen är att en agent fortfarande kan läsa det mesta av värden; dina registrerade utcheckningar skyddas av uttryckliga skriv- och namnändringsnekanden, inte av osynlighet.

  • Filsystemsläsningar: nekade för de hemliga sökvägarna (~/.ssh, ~/.aws, ~/.gnupg, ~/.config/gh, ~/Library/Keychains och resten av läsmängden som nekas)
  • Filsystemsskrivningar: återställs till neka, därefter uttryckliga tillåtanden för undersökvägar, med de obligatoriska neka-sökvägarna (skalets rc-filer, .git/hooks, Claude-konfiguration, skyddade utcheckningar) blockerade även inuti en skrivbar rot. file-write-unlink nekas på varje nekad sökväg och dess förfäder, så en namnändring kan inte kringgå ett skrivnekande
  • Process: process-exec-nekanden för de alltid farliga binärerna, plus ett block mot att köra något från en skrivbar katalog
  • Nätverk: begränsat till proxyportarna i processen plus DNS — loopback är inte generellt tillåtet och Unix-socketar är inte tillåtna. Proxyservrarna framtvingar sessionens domän-allowlist (se Utgående nätverkstrafik)
  • Konfiguration: profiler genereras per start utifrån SandboxSpec

Krav:

  • sandbox-exec (/usr/bin/sandbox-exec), en del av varje macOS-installation — inga ytterligare verktyg krävs

Använder bubblewrap (bwrap) för att skapa monterings- och PID-namnrymder.

  • Filsystem: skapar en monteringsnamnrymd där bara de inbundna sökvägarna syns
  • Nätverk: körs i en osharead nätverksnamnrymd; trafiken når värdens proxyservrar via socat-bryggor över Unix-socketar
  • Process: PID-namnrymdsisolering

Krav:

  • bubblewrap och socat installerade (sudo apt-get install bubblewrap socat på Debian/Ubuntu)
  • Stöd för namnrymder i kärnan (standard på modern Linux)

Bubblewrap kan skugga en befintlig sökväg men kan inte förbjuda en ny .env-, *.key- eller *.pem-fil inuti en skrivbar bind-montering. Standardpolicyn för dispatch kräver dessa filnamnsglobnekanden, så inbyggd agentdispatch faller för närvarande stängt på Linux/WSL2 även när sonderingen hittar bubblewrap. Den kör inte med en tyst svagare policy. En backend med filnamnsregler vid skapandet krävs för att återställa inbyggd dispatch på Linux. Att stänga av sandlådan är en uttrycklig opt-out utan begränsningar, inte en likvärdig kringgång.

Ingen sandlåda. Processen körs direkt på värden med värdens filsystem, nätverk och processåtkomst. ACP och harnessens bash-verktyg får fortfarande sanerad miljö och kommandopolicyen; Claude Code via NoSandboxAdapter ärver värdmiljön. Det här är vad agentdispatchen faller tillbaka på när värden saknar tillgänglig backend eller när --sandbox off är satt, och det är terminalens standard när en klient inte anger någon.

Terminalen sandlådas på sina egna villkor, inte av dispatchsonderingen. TerminalSessionService:s defaultBackend är none och cc_server åsidosätter den inte, så en terminalsession kör värdskalet om inte klienten uttryckligen begär native — skrivbordets terminalpanel gör det inte.

När native begärs lindas skalet in via SandboxManager under en fast terminalprofil: $HOME och sessionens arbetskatalog är skrivbara, nätverket är öppet och ~/.ssh, ~/.aws, ~/.gnupg, ~/.config/gh och ~/Library/Keychains är läsnekade. Kodvärdstoken som bara kan läsa och pushgatewayen gäller inte — de hör till dispatch. Om inlindningen inte stöds misslyckas sessionen i stället för att visa en inbyggd märkning på en PTY med värdskalet.

När en sandlåda startas framtvingas utgående nätverksåtkomst av proxyservrar i processen, inte av brandväggsregler i kärnan. På en värd utan tillgänglig backend gäller inget av detta, och en startad process når nätverket precis som serveranvändaren skulle göra.

  • Sandlådans körtid kör en HTTP/HTTPS-proxy och en SOCKS5-proxy på 127.0.0.1 inuti cc_server-processen, ett par per begränsad session (http_proxy.dart, socks_proxy.dart). Samtidiga körningar delar inte ett par.
  • Sandlådade processer får proxyvariabler i miljön (HTTP_PROXY/HTTPS_PROXY → HTTP-proxyn, ALL_PROXY → SOCKS-proxyn; GIT_SSH_COMMAND dirigerar git-over-SSH genom SOCKS-proxyn). På Linux är nätverksnamnrymden osharead, så proxyservrarna är enda vägen ut; på macOS delar sandlådan värdens loopback och talar med dem direkt.
  • Varje anslutnings målvärd matchas mot sessionens domän-allowlist; allt annat nekas. Två jokerteckenformer, var och en med exakt en *: ett inledande *.example.com matchar vilken underdomän som helst (inklusive a.b.example.com) men inte toppdomänen själv; ett jokertecken i mitten, bedrock.*.amazonaws.com, matchar exakt en etikett (bedrock.us-east-1.amazonaws.com, inte bedrock.evil.attacker.amazonaws.com).
  • Allowlisten löses per session utifrån den kurerade baslinjen (kBaselineAllowedDomains: LLM-leverantörer, Git-hostning, paketregister), plus GitHub-domänerna (kGithubDomains), plus SandboxSpec.egressAllowlist. Dispatchvägen skickar aldrig med extra poster i egressAllowlist, så i praktiken får varje körning baslinjen plus GitHub.
  • En fast nekalista (kBaselineDeniedDomains: molnmetadatanslutningar, telemetrimottagare) har företräde framför alla tillåtanden.
  • networkEnabled: false startar fortfarande sessionsproxyservrarna, men allowlisten är tom så varje utgående anslutning nekas. Dispatch sätter värdet när körningen startar utifrån regeln Använd nätverket: neka stänger av nätverket, tillåt och fråga först lämnar det på.

Specifikationen som skickas till SandboxPort.launch:

Fält Typ Beskrivning
sessionId String Stabil sessionsidentifierare (vanligtvis ytans id)
workspaceId String Id för den ägande arbetsytan
agentId String? Agent som för närvarande är bunden till sandlådan, om någon
bindMounts List<SandboxBindMount> Monteringar värd→gäst; sandlådan ser bara de värdsökvägar som listas här
networkEnabled bool (standard true) Sätts vid dispatch utifrån regeln för utgående nätverkstrafik (av bara när den löses upp till neka). När den är av startar sessionsproxyservrarna fortfarande, men allowlisten är tom så varje utgående anslutning nekas
egressAllowlist List<String> (standard []) Extra tillåtna utgående domäner; jokertecken stöds (*.example.com, plus en mittform med en etikett). Dispatch fyller aldrig i detta, så en inlindad körning får den kurerade baslinjen plus GitHub-domänerna
guestWorkdir String? Standardarbetskatalog inuti sandlådan; enskilda exec-anrop kan åsidosätta den
mode Mode (standard chat) Skär ut filsystemets skrivregler: chat håller bind-monteringar skrivbara; review, plan och orchestrate är skrivskyddade
protectedPaths List<String> (standard []) Värdsökvägar som aldrig får vara skrivbara inuti sandlådan, i något läge
runnerStateDirs List<String> (standard []) Värdkataloger där köraren håller sitt eget tillstånd, skrivbara i varje läge (en Control Center-hanterad CLAUDE_CONFIG_DIR är den nuvarande)
execGrantRoots List<String> (standard []) Operatörsgodkända katalogträd som öppnar exec-blocket för skrivbara kataloger igen på macOS. Linux ignorerar dem — bwrap har inget $HOME-exec-block att öppna igen

protectedPaths innehåller de ursprungliga registrerade repo-utcheckningarna, lösta per dispatch utifrån arbetsytans repos. Agenter arbetar uteslutande i copy-on-write-worktrees per samtal, så originalen får aldrig vara skrivbara inifrån sandlådan — på macOS skulle Seatbelts generella skrivtillåtelse för $HOME annars lämna dem skrivbara via bash. De ansluter till skrivförbudsuppsättningen för hemligheter i varje läge, även chat.

Varje läsmekad och skrivnekad sökväg skrivs ut i både sin bokstavliga och sin symlänksupplösta stavning. Kärnan matchar en nekanderegel mot den upplösta sökvägen, så en regel skriven mot en symlänkad sökväg utlöses aldrig — och på macOS är det det vanliga snarare än det exotiska fallet, eftersom /tmp löses upp till /private/tmp och /var/folders/… till /private/var/folders/…. Poster som innehåller * eller ? behandlas som glober och lämnas i fred; en sökväg som inte löses upp behålls som den är skriven.

Fält Typ Beskrivning
hostPath String Absolut sökväg på värden
guestPath String Sökväg inuti sandlådan (med den inbyggda sandlådan är den lika med hostPath; behålls för adapter-symmetri)
readOnly bool (standard false) Montera skrivskyddat när sant

Returneras av SandboxPort.launch:

Fält Typ Beskrivning
sessionId String Sessionsidentifierare
backend SandboxBackend Vilken backend som körs
state SandboxState Livscykeltillstånd
error Object? Sätts när state är error
details Map<String, Object?> Adapterprivat bokföring (arbetskatalog, PID, profilsökväg m.m.)
Tillstånd Beskrivning
created Specifikationen är skapad men VM:en har inte startat än
warm Kör och är redo att köra kommandon
active Kör för närvarande ett kommando
suspended Pausad / checkpointad till disk för att spara RAM
destroyed Nerriven; handtaget är inte längre giltigt
error Starten misslyckades — se SandboxHandle.error
Händelsetyp Beskrivning
stdout Standardutdata från sandlådan
stderr Standardfel från sandlådan
exit Sandlådeprocessen avslutades (bär exitCode)
starting Sandlådan startar
ready Sandlådan är redo att ta emot exec-anrop
killed Processen dödades av värden (OOM, timeout, manuellt stopp)
violation En sandlådepolicy överträddes (bär en SandboxViolation)
Fält Typ Beskrivning
action String Verbet som nekades (t.ex. file-read*, network-outbound)
target String Sökväg eller värd som var mål för den nekade åtgärden
raw String? Rå loggrada, användbar vid felsökning