Backendy sandboxa
Przegląd backendów
Dział zatytułowany „Przegląd backendów”| Backend | Wartość | Platforma | Dostępność |
|---|---|---|---|
| Zamknięta VM | microvm |
macOS, Linux, Windows (hypervisor microVM) | Bramkowane sondą runtime’u microVM; dotyczy interaktywnych terminali — powłoka działa wewnątrz riga, a nie na hoście |
| Natywny sandbox | native |
macOS (Seatbelt), Linux i WSL2 (bubblewrap) | Sonduje się przy starcie; Linux odmawia uruchomienia wymagającego zakazów zapisu dla wzorców nazw plików, których bubblewrap nie potrafi wyegzekwować |
| Bez izolacji | none |
Wszystkie | Domyślna wartość parsowania, domyślna wartość terminala oraz rozwiązanie zapasowe, gdy żaden backend nie jest dostępny albo ustawiono --sandbox off |
SandboxBackend.fromName zwraca none dla pustej (null) lub nierozpoznanej zapisanej wartości. Zapisana wartość "docker" jest mapowana na native.
microvm to jedyny backend z granicą jądra — obciążenie naprawdę
nie działa na hoście. Nigdy nie jest cichym rozwiązaniem zapasowym w żadnym
kierunku: jawne zażądanie go na hoście, który nie potrafi uruchomić VM, kończy
się głośnym błędem („poprosiłem o VM, a dostałem swój laptop” to jedyna
degradacja, na którą ta izolacja nie może sobie pozwolić), a tylko nieokreślona
wartość domyślna schodzi do native, z linią w logu, która to komunikuje.
Rzeczywisty backend sesji jest raportowany z powrotem do klienta i oznaczany
plakietką, więc terminal nigdy nie może twierdzić, że jest zamknięty, gdy działa
na hoście. Cykl życia, obrazy i ruch wychodzący samej VM opisuje
dokumentacja referencyjna rigów.
Windows nie ma natywnego sandboxa. NativeSandboxAdapter.probe zwraca available: false na każdym hoście, który nie jest macOS ani Linux/WSL2. Wysyłanie agentów w Windows używa więc none. Backend microvm jest odrębny: jest bramkowany sondą runtime’u microVM i dotyczy interaktywnych terminali oraz rigów, a nie opakowywania bash na hoście.
Wyniki sondy
Dział zatytułowany „Wyniki sondy”To sonda bramkuje egzekwowanie. Działa raz, przy starcie serwera.
| Host | available |
Uwaga / wskazówka |
|---|---|---|
| macOS | true |
sandbox-exec (Seatbelt) — izolacja przestrzeni nazw, bez granicy jądra |
Linux lub WSL2 z bwrap i socat |
true |
bubblewrap — izolacja przestrzeni nazw, bez granicy jądra |
| Linux lub WSL2 bez któregokolwiek z narzędzi | false |
requiresInstall: true, ze wskazówką instalacyjną wymieniającą brakujące pakiety |
| Każda inna platforma | false |
Natywny sandbox nie jest oferowany na tej platformie |
Serwer zapisuje wynik w jednej linii startowej: agent sandbox ON plus uwaga, no OS-native agent sandbox on this host plus wskazówka albo agent sandbox DISABLED by --sandbox off. GET /healthz nie zawiera pola sandboxa.
--sandbox / CC_SERVER_SANDBOX przyjmuje on (domyślnie) albo off. To rezygnacja (opt-out), a nie włączenie: on znaczy „opakuj, gdy host oferuje backend”, nigdy „wymagaj go”.
Backend natywny
Dział zatytułowany „Backend natywny”macOS: Seatbelt
Dział zatytułowany „macOS: Seatbelt”Wykorzystuje mechanizm sandboxa Seatbelt firmy Apple (ten sam system, którego używa macOS App Sandbox).
Generowany profil jest domyślnie permisywny ((allow default)) i wycina z niego odmowy, bo w pełni odmawiający domyślnie profil czyni interaktywną powłokę bezużyteczną — wywołań dyld, XPC i Mach jest zbyt wiele, by je wyliczyć. Praktyczna konsekwencja jest taka, że agent nadal może odczytać większość hosta; Twoje zarejestrowane kopie robocze chronią jawne odmowy zapisu i zmiany nazwy, a nie niewidzialność.
- Odczyty systemu plików: odmawiane dla ścieżek z sekretami (
~/.ssh,~/.aws,~/.gnupg,~/.config/gh,~/Library/Keychainsi pozostałych ze zbioru zakazu odczytu) - Zapisy systemu plików: resetowane do odmowy, a następnie jawne zezwolenia na podścieżki, przy czym ścieżki objęte obowiązkowym zakazem (pliki rc powłoki,
.git/hooks, konfiguracja Claude, chronione kopie robocze) są blokowane nawet wewnątrz korzenia z prawem zapisu.file-write-unlinkjest odmawiany na każdej zabronionej ścieżce i jej przodkach, więc zmiana nazwy nie może ominąć zakazu zapisu - Procesy: odmowy
process-execdla zawsze niebezpiecznych plików binarnych oraz blokada wykonywania czegokolwiek z katalogu z prawem zapisu - Sieć: ograniczona do portów proxy działających w procesie plus DNS — pętla zwrotna nie jest dozwolona hurtowo, a gniazda Unix nie są dozwolone. Proxy egzekwują listę dozwolonych domen dla sesji (zobacz Ruch wychodzący w sieci)
- Konfiguracja: profile są generowane przy każdym starcie na podstawie
SandboxSpec
Wymagania:
sandbox-exec(/usr/bin/sandbox-exec), część każdej instalacji macOS — nie wymaga dodatkowych narzędzi
Linux: bubblewrap
Dział zatytułowany „Linux: bubblewrap”Używa bubblewrap (bwrap) do tworzenia przestrzeni nazw montowania i PID.
- System plików: tworzy przestrzeń nazw montowania, w której widoczne są tylko podmontowane ścieżki
- Sieć: działa w niewspółdzielonej przestrzeni nazw sieci; ruch dociera do proxy hosta przez mostki gniazd Unix
socat - Procesy: izolacja przestrzeni nazw PID
Wymagania:
- zainstalowane
bubblewrapisocat(sudo apt-get install bubblewrap socatw Debianie/Ubuntu) - obsługa przestrzeni nazw w jądrze (standard w nowoczesnym Linuksie)
Bubblewrap potrafi przesłonić istniejącą ścieżkę, ale nie potrafi zakazać nowego pliku .env,
*.key lub *.pem wewnątrz podmontowanego katalogu z prawem zapisu. Standardowa polityka wysyłania
wymaga tych zakazów dla wzorców nazw plików, więc natywne wysyłanie agentów obecnie
odmawia działania na Linuksie/WSL2, nawet gdy sonda znajdzie bubblewrap. Nie
działa z cicho osłabioną polityką. Aby przywrócić natywne wysyłanie w Linuksie,
potrzebny jest backend z regułami nazw plików działającymi w momencie tworzenia. Wyłączenie sandboxowania to
jawne, nieograniczone zrezygnowanie, a nie równoważne obejście.
Backend bez izolacji
Dział zatytułowany „Backend bez izolacji”Brak sandboxowania. Proces działa bezpośrednio na hoście, z dostępem hosta do systemu plików, sieci i procesów. ACP i narzędzie bash harnessa nadal otrzymują sanityzację środowiska oraz politykę poleceń; Claude Code przez NoSandboxAdapter dziedziczy środowisko hosta. Do tego rozwiązania schodzi wysyłanie agentów na hoście bez dostępnego backendu albo z --sandbox off i jest to domyślne ustawienie terminala, gdy klient nie wskazuje żadnego backendu.
Terminal hostowany na serwerze
Dział zatytułowany „Terminal hostowany na serwerze”Terminal jest sandboxowany na własnych zasadach, a nie przez sondę wysyłania. defaultBackend w TerminalSessionService ma wartość none i cc_server go nie nadpisuje, więc sesja terminala uruchamia powłokę hosta, chyba że klient wprost poprosi o native — panel terminala w aplikacji desktopowej tego nie robi.
Gdy zażądano native, powłoka jest opakowywana przez SandboxManager w stałym profilu terminala: $HOME i katalog roboczy sesji mają prawo zapisu, sieć jest otwarta, a ~/.ssh, ~/.aws, ~/.gnupg, ~/.config/gh i ~/Library/Keychains mają zakaz odczytu. Token hosta kodu tylko do odczytu i brama push nie mają tu zastosowania — to sprawy wysyłania. Jeśli opakowanie nie jest obsługiwane, sesja kończy się błędem, zamiast pokazywać natywną plakietkę na PTY z powłoką hosta.
Ruch wychodzący w sieci
Dział zatytułowany „Ruch wychodzący w sieci”Gdy sandbox jest uruchamiany, dostęp wychodzący do sieci jest egzekwowany przez proxy działające w procesie, a nie przez reguły firewalla jądra. Na hoście bez dostępnego backendu nic z tego nie obowiązuje, a uruchomiony proces dociera do sieci dokładnie tak, jak zrobiłby to użytkownik serwera.
- Runtime sandboxa uruchamia proxy HTTP/HTTPS oraz proxy SOCKS5 na
127.0.0.1wewnątrz procesucc_server, po jednej parze na ograniczoną sesję (http_proxy.dart,socks_proxy.dart). Równoległe uruchomienia nie dzielą pary. - Procesy w sandboxie otrzymują zmienne środowiskowe proxy (
HTTP_PROXY/HTTPS_PROXY→ proxy HTTP,ALL_PROXY→ proxy SOCKS;GIT_SSH_COMMANDkieruje git po SSH przez proxy SOCKS). W Linuksie przestrzeń nazw sieci jest niewspółdzielona, więc proxy to jedyne wyjście; w macOS sandbox współdzieli pętlę zwrotną hosta i rozmawia z nimi bezpośrednio. - Docelowy host każdego połączenia jest dopasowywany do listy dozwolonych domen sesji; wszystko inne jest odrzucane. Istnieją dwie formy wieloznaczne, każda z dokładnie jednym
*: wiodąca*.example.compasuje do dowolnej subdomeny (w tyma.b.example.com), ale nie do samej domeny głównej; środkowa etykietabedrock.*.amazonaws.compasuje do dokładnie jednej etykiety (bedrock.us-east-1.amazonaws.com, a niebedrock.evil.attacker.amazonaws.com). - Lista dozwolonych jest wyznaczana dla każdej sesji na podstawie wyselekcjonowanej bazy (
kBaselineAllowedDomains: dostawcy LLM, hosting Git, rejestry pakietów) plus domeny GitHub (kGithubDomains), plusSandboxSpec.egressAllowlist. Ścieżka wysyłania nigdy nie przekazuje dodatkowych wpisówegressAllowlist, więc w praktyce każde uruchomienie dostaje bazę plus GitHuba. - Stała lista zakazów (
kBaselineDeniedDomains: punkty końcowe metadanych chmury, ujścia telemetrii) ma pierwszeństwo przed wszystkimi zezwoleniami. networkEnabled: falsenadal uruchamia proxy dla sesji, ale lista dozwolonych jest pusta, więc każde połączenie wychodzące jest odrzucane. Wysyłanie ustawia tę wartość na starcie uruchomienia na podstawie reguły Dostęp do sieci: odmowa wyłącza sieć, zezwól i zapytaj najpierw zostawiają ją włączoną.
SandboxSpec
Dział zatytułowany „SandboxSpec”Specyfikacja przekazywana do SandboxPort.launch:
| Pole | Typ | Opis |
|---|---|---|
sessionId |
String |
Stabilny identyfikator sesji (zwykle identyfikator przestrzeni) |
workspaceId |
String |
Identyfikator obszaru roboczego będącego właścicielem |
agentId |
String? |
Agent aktualnie powiązany z sandboxem, jeśli istnieje |
bindMounts |
List<SandboxBindMount> |
Montowania host→gość; sandbox widzi tylko wymienione tu ścieżki hosta |
networkEnabled |
bool (domyślnie true) |
Ustawiane przy wysyłaniu na podstawie reguły ruchu wychodzącego sieci (wyłączone tylko wtedy, gdy rozstrzyga się na odmowę). Gdy wyłączone, proxy dla sesji nadal startują, ale lista dozwolonych jest pusta, więc każde połączenie wychodzące jest odrzucane |
egressAllowlist |
List<String> (domyślnie []) |
Dodatkowe dozwolone domeny ruchu wychodzącego; obsługiwane wieloznaczniki (*.example.com oraz środkowa forma z jedną etykietą). Wysyłanie nigdy tego nie wypełnia, więc opakowane uruchomienie dostaje wyselekcjonowaną bazę plus domeny GitHub |
guestWorkdir |
String? |
Domyślny katalog roboczy wewnątrz sandboxa; pojedyncze wywołania exec mogą go nadpisać |
mode |
Mode (domyślnie chat) |
Wycina reguły zapisu systemu plików: chat pozostawia montowania z prawem zapisu; review, plan i orchestrate są tylko do odczytu |
protectedPaths |
List<String> (domyślnie []) |
Ścieżki hosta, które nigdy nie mogą mieć prawa zapisu wewnątrz sandboxa, w żadnym trybie |
runnerStateDirs |
List<String> (domyślnie []) |
Katalogi hosta, w których runner trzyma własny stan, z prawem zapisu w każdym trybie (obecnie zarządzany przez Control Center CLAUDE_CONFIG_DIR) |
execGrantRoots |
List<String> (domyślnie []) |
Zatwierdzone przez operatora drzewa katalogów, które ponownie otwierają blokadę wykonywania z katalogu z prawem zapisu w macOS. Linux je ignoruje — bwrap nie ma blokady wykonywania w $HOME, którą można by ponownie otworzyć |
protectedPaths zawiera oryginalne, zarejestrowane kopie robocze repozytoriów, wyznaczane przy każdym wysłaniu z repozytoriów obszaru roboczego. Agenci pracują wyłącznie w kopiowanych przy zapisie worktree przypadających na rozmowę, więc oryginały nigdy nie mogą mieć prawa zapisu z wnętrza sandboxa — w macOS ogólne zezwolenie Seatbelt na zapis w $HOME pozostawiłoby im prawo zapisu przez bash. Dołączają do zestawu zakazu zapisu dla sekretów w każdym trybie, w tym w chat.
Każda ścieżka zakazu odczytu i zakazu zapisu jest emitowana zarówno w dosłownym zapisie, jak i w zapisie po rozwiązaniu dowiązań symbolicznych. Jądro dopasowuje regułę zakazu do rozwiązanej ścieżki, więc reguła zapisana względem ścieżki będącej dowiązaniem symbolicznym nigdy nie zadziała — a w macOS to przypadek częsty, nie egzotyczny, bo /tmp rozwiązuje się do /private/tmp, a /var/folders/… do /private/var/folders/…. Wpisy zawierające * lub ? są traktowane jako wzorce i pozostawiane bez zmian; ścieżka, która się nie rozwiązuje, jest zachowywana w zapisanej postaci.
SandboxBindMount
Dział zatytułowany „SandboxBindMount”| Pole | Typ | Opis |
|---|---|---|
hostPath |
String |
Ścieżka bezwzględna na hoście |
guestPath |
String |
Ścieżka wewnątrz sandboxa (w sandboxie natywnym jest równa hostPath; zachowana dla symetrii adapterów) |
readOnly |
bool (domyślnie false) |
Gdy true, montuj tylko do odczytu |
SandboxHandle
Dział zatytułowany „SandboxHandle”Zwracany przez SandboxPort.launch:
| Pole | Typ | Opis |
|---|---|---|
sessionId |
String |
Identyfikator sesji |
backend |
SandboxBackend |
Który backend działa |
state |
SandboxState |
Stan cyklu życia |
error |
Object? |
Ustawiane, gdy state ma wartość error |
details |
Map<String, Object?> |
Wewnętrzna księgowość adaptera (katalog roboczy, PID, ścieżka profilu itd.) |
SandboxState
Dział zatytułowany „SandboxState”| Stan | Opis |
|---|---|
created |
Specyfikacja utworzona, ale VM jeszcze nie wystartowała |
warm |
Działa i jest gotowa do wykonywania poleceń |
active |
Wykonuje właśnie polecenie |
suspended |
Wstrzymana / zapisana na dysk jako punkt kontrolny, aby oszczędzać RAM |
destroyed |
Rozebrana; uchwyt nie jest już ważny |
error |
Uruchomienie nie powiodło się — zobacz SandboxHandle.error |
Zdarzenia sandboxa
Dział zatytułowany „Zdarzenia sandboxa”| Typ zdarzenia | Opis |
|---|---|
stdout |
Standardowe wyjście z sandboxa |
stderr |
Standardowe wyjście błędów z sandboxa |
exit |
Proces sandboxa zakończył się (niesie exitCode) |
starting |
Sandbox się uruchamia |
ready |
Sandbox jest gotowy przyjmować wywołania exec |
killed |
Proces zabity przez hosta (OOM, przekroczenie limitu czasu, ręczne zatrzymanie) |
violation |
Naruszono politykę sandboxa (niesie SandboxViolation) |
SandboxViolation
Dział zatytułowany „SandboxViolation”| Pole | Typ | Opis |
|---|---|---|
action |
String |
Zabronione działanie (np. file-read*, network-outbound) |
target |
String |
Ścieżka lub host będący celem zabronionej operacji |
raw |
String? |
Surowa linia logu, przydatna przy debugowaniu |
Zobacz też
Dział zatytułowany „Zobacz też”- Sandbox i bezpieczeństwo
- Skonfiguruj polityki sandboxa
- Guardraile
- CLI
cc_server: flaga--sandbox