Tovább a tartalomhoz

Homokozó-háttérrendszerek

Háttérrendszer Érték Platform Elérhetőség
Elszigetelt VM microvm macOS, Linux, Windows (microVM hypervisor) A microVM futásidejének észlelése kapuzza; interaktív terminálokra vonatkozik — a shell egy állomás belsejében fut, nem a gazdagépen
Natív native macOS (Seatbelt), Linux és WSL2 (bubblewrap) Indításkor észleljük; a Linux elutasítja azt a futtatást, amely fájlnév-glob írási tiltásokat igényel, mert a bubblewrap ezt nem tudja érvényesíteni
Nincs none Mind Az értelmezés alapértelmezése, a terminál alapértelmezése, és a visszaesés, amikor nincs elérhető háttérrendszer, vagy be van állítva a --sandbox off

A SandboxBackend.fromName none értéket ad vissza null vagy fel nem ismert tárolt érték esetén. A tárolt "docker" a native értékre képeződik.

A microvm az egyetlen kernelhatárral rendelkező háttérrendszer — a munkaterhelés valóban nem a gazdagépen fut. Egyik irányban sem csendes visszaesés: ha egy VM indítására képtelen gazdagépen kifejezetten kérjük, hangosan meghiúsul („VM-et kértem, és a laptopomat kaptam” az az egyetlen visszaesés, amelyet az elszigetelés nem engedhet meg magának), és csak egy meghatározatlan alapértelmezés lép le a native értékre, ezt egy naplósor is jelzi. A munkamenet tényleges háttérrendszere visszajelzésre kerül a kliensnek és jelvényt kap, így egy terminál soha nem állíthatja, hogy elszigetelt, miközben a gazdagépen fut. Magának a VM-nek az életciklusát, lemezképeit és kimenő forgalmát az állomások referenciája tárgyalja.

A Windowsnak nincs natív homokozója. A NativeSandboxAdapter.probe minden olyan gazdagépen available: false értéket ad vissza, amely nem macOS vagy Linux/WSL2. A Windowson folyó ügynökindítás ezért a none háttérrendszert használja. A microvm háttérrendszer ettől független: a microVM futásidejének észlelése kapuzza, és az interaktív terminálokra és az állomásokra vonatkozik, nem pedig a bash gazdagépen való becsomagolására.

Az észlelés kapuzza a kikényszerítést. Egyszer fut le, a szerver indításakor.

Gazdagép available Megjegyzés / tipp
macOS true sandbox-exec (Seatbelt) — névtér-elszigetelés, kernelhatár nélkül
Linux vagy WSL2 bwrap és socat meglétével true bubblewrap — névtér-elszigetelés, kernelhatár nélkül
Linux vagy WSL2, amelyből valamelyik eszköz hiányzik false requiresInstall: true, a hiányzó csomagokat megnevező telepítési tippel
Bármely más platform false A natív homokozó ezen a platformon nem érhető el

A szerver az eredményt egyetlen indítási sorban naplózza: agent sandbox ON és a megjegyzés, no OS-native agent sandbox on this host és a tipp, vagy agent sandbox DISABLED by --sandbox off. A GET /healthz nem tartalmaz homokozómezőt.

A --sandbox / CC_SERVER_SANDBOX az on (alapértelmezett) vagy az off értéket fogadja el. Ez kikapcsolási lehetőség, nem engedélyezés: az on azt jelenti, hogy „csomagolj, ha a gazdagép kínál háttérrendszert”, és soha nem azt, hogy „követelj meg egyet”.

Az Apple Seatbelt homokozómechanizmusát használja (ugyanazt a rendszert, amelyet a macOS App Sandbox használ).

A generált profil alapértelmezés szerint megengedő ((allow default)), és tiltásokat vés ki, mert egy teljesen tiltásra épülő profil használhatatlanná teszi az interaktív shellt — túl sok a felsorolandó dyld-, XPC- és Mach-hívás. Ennek gyakorlati következménye, hogy az ügynök továbbra is olvashatja a gazdagép nagy részét; a regisztrált checkoutokat nem a láthatatlanság védi, hanem explicit írási és átnevezési tiltások.

  • Fájlrendszer-olvasás: tiltott a titkos útvonalakra (~/.ssh, ~/.aws, ~/.gnupg, ~/.config/gh, ~/Library/Keychains és az olvasásmegtagadási halmaz többi tagja)
  • Fájlrendszer-írás: visszaállítva tiltásra, majd explicit alútvonal-engedélyek, a kötelezően tiltott útvonalak (shell rc-fájlok, .git/hooks, Claude-konfiguráció, védett checkoutok) egy írható gyökér belsejében is blokkolva. A file-write-unlink minden tiltott útvonalon és annak ősein tiltott, így egy átnevezés nem kerülheti meg az írási tiltást
  • Folyamat: process-exec tiltások a mindig veszélyes binárisokra, valamint blokk bárminek az írható könyvtárból való végrehajtására
  • Hálózat: a folyamaton belüli proxyportokra és a DNS-re korlátozva — a loopback nincs általánosan engedélyezve, és a Unix-socketek sem engedélyezettek. A proxyk érvényesítik a munkamenetenkénti domain-engedélylistát (lásd Hálózati kimenő forgalom)
  • Konfiguráció: a profilok indításonként, a SandboxSpec alapján generálódnak

Követelmények:

  • sandbox-exec (/usr/bin/sandbox-exec), minden macOS-telepítés része — nincs szükség további eszközre

A bubblewrap (bwrap) segítségével mount- és PID-névtereket hoz létre.

  • Fájlrendszer: olyan mountnévtért hoz létre, amelyben csak a becsatolt útvonalak láthatók
  • Hálózat: nem megosztott hálózati névtérben fut; a forgalom socat Unix-socket hidakon keresztül éri el a gazdagép proxyit
  • Folyamat: PID-névtér-elszigetelés

Követelmények:

  • bubblewrap és socat telepítve (sudo apt-get install bubblewrap socat Debian/Ubuntun)
  • Kernel névtértámogatás (modern Linuxon alapértelmezett)

A bubblewrap el tud fedni egy meglévő útvonalat, de nem tud megtiltani egy új .env, *.key vagy *.pem fájlt egy írható bindon belül. A standard indítási szabályzat megköveteli ezeket a fájlnév-glob tiltásokat, ezért a natív ügynökindítás jelenleg Linuxon/WSL2-n fail-closed módon meghiúsul még akkor is, ha az észlelés megtalálja a bubblewrapet. Nem fut csendben gyengébb szabályzattal. A Linux natív indításának helyreállításához olyan háttérrendszer kell, amely létrehozás idejű fájlnévszabályokat támogat. A homokozó kikapcsolása explicit, korlátok nélküli kikapcsolás, nem egyenértékű megoldás.

Nincs homokozó. A folyamat közvetlenül a gazdagépen fut, a gazdagép fájlrendszer-, hálózat- és folyamathozzáférésével. Az ACP és a harness bash eszköze továbbra is kap környezettisztítást és a parancsszabályzatot; a Claude Code a NoSandboxAdapter-en keresztül a gazdagép környezetét örökli. Erre esik vissza az ügynökindítás olyan gazdagépen, ahol nincs elérhető háttérrendszer, vagy ahol --sandbox off van beállítva, és ez a terminál alapértelmezése is, amikor a kliens egyet sem nevez meg.

A terminál a saját szabályai szerint kerül homokozóba, nem az indítási észlelés szerint. A TerminalSessionService defaultBackend értéke none, és a cc_server nem írja felül, így egy terminálmunkamenet a gazdagép shelljét futtatja, hacsak a kliens kifejezetten nem kéri a native értéket — az asztali alkalmazás terminálpanelje nem kéri.

Amikor a native értéket kérik, a shellt a SandboxManager csomagolja be egy rögzített terminálprofil alá: a $HOME és a munkamenet munkakönyvtára írható, a hálózat nyitott, a ~/.ssh, ~/.aws, ~/.gnupg, ~/.config/gh és ~/Library/Keychains pedig olvasásra tiltott. A csak olvasásra jogosult kódhosting-token és a push-átjáró nem érvényesül — az az indítás dolga. Ha a becsomagolás nem támogatott, a munkamenet meghiúsul, ahelyett hogy natív jelvényt mutatna egy gazdagépshell-PTY-n.

Amikor egy homokozó elindul, a kimenő hálózati hozzáférést folyamaton belüli proxyk érvényesítik, nem kernel tűzfalszabályok. Olyan gazdagépen, ahol nincs elérhető háttérrendszer, mindez nem érvényesül, és egy elindított folyamat pontosan úgy éri el a hálózatot, ahogy a szerver felhasználója tenné.

  • A homokozó-futtatókörnyezet egy HTTP/HTTPS proxyt és egy SOCKS5 proxyt futtat a 127.0.0.1 címen, a cc_server folyamatán belül, korlátozott munkamenetenként egy párt (http_proxy.dart, socks_proxy.dart). Az egyidejű futtatások nem osztoznak egy páron.
  • A homokozóba zárt folyamatok proxy környezeti változókat kapnak (HTTP_PROXY/HTTPS_PROXY → a HTTP-proxy, ALL_PROXY → a SOCKS-proxy; a GIT_SSH_COMMAND a git-over-SSH forgalmat a SOCKS-proxyn keresztül vezeti). Linuxon a hálózati névtér nem megosztott, így a proxyk jelentik az egyetlen kivezető utat; macOS-en a homokozó a gazdagép loopbackjét használja, és közvetlenül beszél velük.
  • Minden kapcsolat célhosztját a munkamenet domain-engedélylistájával vetjük össze; minden más elutasításra kerül. Két helyettesítő karakteres forma létezik, mindegyikben pontosan egy *: a kezdő *.example.com bármely aldomainre illeszkedik (beleértve az a.b.example.com címet is), de magára a csúcstartományra nem; a középső címkés bedrock.*.amazonaws.com pontosan egy címkére illeszkedik (bedrock.us-east-1.amazonaws.com, de nem bedrock.evil.attacker.amazonaws.com).
  • Az engedélylista munkamenetenként a gondozott alaplistából oldódik fel (kBaselineAllowedDomains: LLM-szolgáltatók, Git-hoszting, csomagregiszterek), plusz a GitHub-domainekből (kGithubDomains), plusz a SandboxSpec.egressAllowlist elemeiből. Az indítási útvonal soha nem ad át további egressAllowlist bejegyzéseket, így a gyakorlatban minden futtatás az alaplistát és a GitHubot kapja.
  • Egy rögzített tiltólista (kBaselineDeniedDomains: felhő-metaadatvégpontok, telemetriai célpontok) elsőbbséget élvez minden engedéllyel szemben.
  • A networkEnabled: false esetén a munkamenetenkénti proxyk továbbra is elindulnak, de az engedélylista üres, így minden kimenő kapcsolat elutasításra kerül. Az indítás a futás kezdetén a Hálózati hozzáférés szabály alapján állítja be: a tiltás kikapcsolja a hálózatot, az engedélyezés és az előbb kérdezzen bekapcsolva hagyja.

A SandboxPort.launch számára átadott specifikáció:

Mező Típus Leírás
sessionId String Stabil munkamenet-azonosító (jellemzően a tér azonosítója)
workspaceId String A tulajdonos munkaterület azonosítója
agentId String? A homokozóhoz jelenleg kötött ügynök, ha van
bindMounts List<SandboxBindMount> Gazdagép→vendég csatolások; a homokozó csak az itt felsorolt gazdagép-útvonalakat látja
networkEnabled bool (default true) Az indítás állítja be a hálózati kimenő forgalom szabálya alapján (csak akkor kikapcsolt, ha tiltásra oldódik fel). Kikapcsolva a munkamenetenkénti proxyk továbbra is elindulnak, de az engedélylista üres, így minden kimenő kapcsolat elutasításra kerül
egressAllowlist List<String> (default []) További engedélyezett kimenő domainek; a helyettesítő karakterek támogatottak (*.example.com, valamint az egycímkés középső forma). Az indítás soha nem tölti ki, így egy becsomagolt futtatás a gondozott alaplistát és a GitHub-domaineket kapja
guestWorkdir String? Alapértelmezett munkakönyvtár a homokozón belül; az egyes exec hívások felülírhatják
mode Mode (default chat) Kivési a fájlrendszer-írási szabályokat: a chat írhatóan tartja a bind mountokat; a review, a plan és az orchestrate csak olvasható
protectedPaths List<String> (default []) Olyan gazdagép-útvonalak, amelyek soha nem lehetnek írhatók a homokozón belül, egyetlen módban sem
runnerStateDirs List<String> (default []) Gazdagép-könyvtárak, amelyekben a futtató a saját állapotát tartja, minden módban írhatók (jelenleg egy Control Center által kezelt CLAUDE_CONFIG_DIR az egyetlen)
execGrantRoots List<String> (default []) Operátor által jóváhagyott könyvtárfák, amelyek újra megnyitják az írható könyvtárból való végrehajtás blokkját macOS-en. A Linux figyelmen kívül hagyja őket — a bwrapnak nincs $HOME-execblokkja, amelyet újra meg lehetne nyitni

A protectedPaths az eredeti, regisztrált repó-checkoutokat tartalmazza, amelyeket indításonként a munkaterület repóiból oldunk fel. Az ügynökök kizárólag beszélgetésenkénti copy-on-write worktree-kben dolgoznak, így az eredeti példányok soha nem lehetnek írhatók a homokozón belülről — macOS-en a Seatbelt általános $HOME-írási engedélye egyébként írhatóvá tenné őket a bash számára. Minden módban csatlakoznak a titkos fájlok írásmegtagadási halmazához, a chat módban is.

Minden olvasásmegtagadási és írásmegtagadási útvonal kiadásra kerül mind a szó szerinti, mind a symlink-feloldott alakjában. A kernel a tiltási szabályt a feloldott útvonallal veti össze, így egy symlinkelt útvonalra írt szabály soha nem lép életbe — és macOS-en ez a gyakori eset, nem az egzotikus, mivel a /tmp a /private/tmp útvonalra, a /var/folders/… pedig a /private/var/folders/… útvonalra oldódik fel. A * vagy ? karaktert tartalmazó bejegyzéseket globként kezeljük, és nem bántjuk; egy fel nem oldható útvonal úgy marad, ahogy leírták.

Mező Típus Leírás
hostPath String Abszolút útvonal a gazdagépen
guestPath String Útvonal a homokozón belül (a natív homokozónál ez megegyezik a hostPath értékkel; az adapterek szimmetriája miatt maradt meg)
readOnly bool (default false) Igaz érték esetén csak olvashatóként csatol

A SandboxPort.launch adja vissza:

Mező Típus Leírás
sessionId String Munkamenet-azonosító
backend SandboxBackend Melyik háttérrendszer fut
state SandboxState Életciklus-állapot
error Object? Akkor van beállítva, amikor a state értéke error
details Map<String, Object?> Adapteren belüli nyilvántartás (munkakönyvtár, PID, a profil útvonala stb.)
Állapot Leírás
created A specifikáció elkészült, de a VM még nem indult el
warm Fut, és készen áll parancsok végrehajtására
active Éppen egy parancsot hajt végre
suspended Szüneteltetve / lemezre checkpointolva a RAM felszabadításához
destroyed Lebontva; a fogantyú már nem érvényes
error Az indítás meghiúsult — lásd a SandboxHandle.error mezőt
Eseménytípus Leírás
stdout A homokozó standard kimenete
stderr A homokozó standard hibakimenete
exit A homokozófolyamat kilépett (exitCode értéket hordoz)
starting A homokozó indulóban van
ready A homokozó készen áll az exec hívások fogadására
killed A folyamatot a gazdagép ölte meg (OOM, időtúllépés, kézi leállítás)
violation Egy homokozószabályzat megsértése történt (SandboxViolation értéket hordoz)
Mező Típus Leírás
action String A megtagadott művelet (pl. file-read*, network-outbound)
target String A megtagadott művelet célpontja, egy útvonal vagy hoszt
raw String? Nyers naplósor, hibakereséshez hasznos