Lewati ke konten

Backend sandbox

Backend Nilai Platform Ketersediaan
VM tertutup microvm macOS, Linux, Windows (hypervisor microVM) Digerbangi probe pada runtime microVM; berlaku untuk terminal interaktif — shell berjalan di dalam rig, bukan di host
Native native macOS (Seatbelt), Linux dan WSL2 (bubblewrap) Diprobe saat boot; Linux menolak run yang memerlukan penolakan tulis berupa glob nama berkas, yang tidak dapat ditegakkan bubblewrap
Tidak ada none Semua Default penguraian, default terminal, dan fallback bila tidak ada backend yang tersedia atau --sandbox off disetel

SandboxBackend.fromName mengembalikan none untuk nilai tersimpan yang null atau tidak dikenali. Nilai "docker" yang tersimpan dipetakan ke native.

microvm adalah satu-satunya backend dengan batas kernel — beban kerjanya benar-benar tidak berjalan di host. Backend ini tidak pernah menjadi fallback senyap ke arah mana pun: memintanya secara eksplisit di host yang tidak dapat mem-boot VM akan gagal dengan berisik (“Saya meminta VM tetapi yang saya dapat laptop saya” adalah satu-satunya degradasi yang tidak boleh terjadi pada enclosure), dan hanya default yang tidak ditentukan yang turun ke native, dengan satu baris log yang menyatakannya. Backend aktual sesi dilaporkan kembali ke klien dan diberi lencana, sehingga terminal tidak pernah dapat mengklaim dirinya tertutup padahal berjalan di host. Siklus hidup, image, dan egress untuk VM itu sendiri dibahas di referensi rigs.

Windows tidak memiliki sandbox native. NativeSandboxAdapter.probe mengembalikan available: false di setiap host yang bukan macOS atau Linux/WSL2. Karena itu, pengiriman agen di Windows memakai none. Backend microvm terpisah: backend itu digerbangi probe pada runtime microVM dan berlaku untuk terminal interaktif serta rigs, bukan untuk membungkus bash di host.

Probe-lah yang menggerbangi penegakan. Probe berjalan sekali, saat boot server.

Host available Catatan / petunjuk
macOS true sandbox-exec (Seatbelt) — isolasi namespace, tanpa batas kernel
Linux atau WSL2 dengan bwrap dan socat true bubblewrap — isolasi namespace, tanpa batas kernel
Linux atau WSL2 tanpa salah satu alat false requiresInstall: true, dengan petunjuk pemasangan yang menyebutkan paket yang hilang
Platform lain apa pun false Sandbox native tidak ditawarkan di platform ini

Server mencatat hasilnya pada satu baris startup: agent sandbox ON plus catatannya, no OS-native agent sandbox on this host plus petunjuknya, atau agent sandbox DISABLED by --sandbox off. GET /healthz tidak membawa bidang sandbox.

--sandbox / CC_SERVER_SANDBOX menerima on (default) atau off. Ini adalah pengabaian opsional, bukan pengaktifan: on berarti “bungkus bila host menyediakan backend”, tidak pernah “wajibkan satu”.

Memakai mekanisme sandbox Seatbelt milik Apple (sistem yang sama yang dipakai macOS App Sandbox).

Profil yang dihasilkan permisif secara default ((allow default)) dan memahat penolakannya, karena profil yang sepenuhnya menolak secara default membuat shell interaktif tidak dapat dipakai — terlalu banyak panggilan dyld, XPC, dan Mach untuk dienumerasi. Konsekuensi praktisnya, agen masih dapat membaca sebagian besar host; checkout terdaftar Anda dilindungi oleh penolakan tulis dan rename yang eksplisit, bukan oleh ketaknampakan.

  • Pembacaan sistem berkas: ditolak untuk jalur rahasia (~/.ssh, ~/.aws, ~/.gnupg, ~/.config/gh, ~/Library/Keychains, dan sisanya dari himpunan tolak-baca)
  • Penulisan sistem berkas: diatur ulang ke tolak, lalu diizinkan secara eksplisit per subjalur, dengan jalur wajib-tolak (berkas rc shell, .git/hooks, konfigurasi Claude, checkout yang dilindungi) diblokir bahkan di dalam akar yang dapat ditulis. file-write-unlink ditolak pada setiap jalur yang ditolak beserta leluhurnya, sehingga rename tidak dapat melewati penolakan tulis
  • Proses: process-exec menolak biner yang selalu berbahaya, plus pemblokiran eksekusi apa pun dari direktori yang dapat ditulis
  • Jaringan: dibatasi ke port proksi dalam proses plus DNS — loopback tidak diizinkan secara menyeluruh dan Unix socket tidak diizinkan. Proksi menegakkan daftar izin domain per sesi (lihat Egress jaringan)
  • Konfigurasi: profil dihasilkan per peluncuran dari SandboxSpec

Persyaratan:

  • sandbox-exec (/usr/bin/sandbox-exec), bagian dari setiap pemasangan macOS — tidak perlu alat tambahan

Memakai bubblewrap (bwrap) untuk membuat namespace mount dan PID.

  • Sistem berkas: membuat namespace mount dengan hanya jalur yang di-bind yang terlihat
  • Jaringan: berjalan di namespace jaringan yang tidak dibagi; lalu lintas mencapai proksi host melalui jembatan Unix socket socat
  • Proses: isolasi namespace PID

Persyaratan:

  • bubblewrap dan socat terpasang (sudo apt-get install bubblewrap socat di Debian/Ubuntu)
  • Dukungan namespace kernel (standar di Linux modern)

Bubblewrap dapat menaungi jalur yang sudah ada tetapi tidak dapat melarang berkas .env, *.key, atau *.pem yang baru di dalam bind yang dapat ditulis. Kebijakan pengiriman standar memerlukan penolakan glob nama berkas ini, jadi pengiriman agen native saat ini gagal-tertutup di Linux/WSL2 bahkan ketika probe menemukan bubblewrap. Pengiriman itu tidak berjalan dengan kebijakan yang diam-diam lebih lemah. Backend dengan aturan nama berkas pada waktu pembuatan diperlukan untuk memulihkan pengiriman native di Linux. Menonaktifkan sandboxing adalah pengabaian tanpa kurungan yang eksplisit, bukan solusi setara.

Tanpa sandboxing. Proses berjalan langsung di host dengan akses sistem berkas, jaringan, dan proses milik host. ACP dan alat bash harness tetap mendapat sanitasi lingkungan dan kebijakan perintah; Claude Code melalui NoSandboxAdapter mewarisi lingkungan host. Inilah yang menjadi fallback pengiriman agen di host tanpa backend yang tersedia atau dengan --sandbox off, dan inilah default terminal bila klien tidak menyebutkan backend apa pun.

Terminal di-sandbox dengan ketentuannya sendiri, bukan oleh probe pengiriman. defaultBackend milik TerminalSessionService bernilai none dan cc_server tidak menimpanya, jadi sesi terminal menjalankan shell host kecuali klien secara eksplisit meminta native — panel terminal di desktop tidak memintanya.

Saat native diminta, shell dibungkus melalui SandboxManager di bawah profil terminal tetap: $HOME dan direktori kerja sesi dapat ditulis, jaringan terbuka, dan ~/.ssh, ~/.aws, ~/.gnupg, ~/.config/gh, serta ~/Library/Keychains ditolak-baca. Token forge hanya-baca dan gateway push tidak berlaku — itu urusan pengiriman. Bila pembungkusan tidak didukung, sesi gagal alih-alih menampilkan lencana native pada PTY shell host.

Saat sandbox diluncurkan, akses jaringan keluar ditegakkan oleh proksi dalam proses, bukan oleh aturan firewall kernel. Di host tanpa backend yang tersedia, tidak satu pun dari ini berlaku dan proses yang dijalankan menjangkau jaringan persis seperti yang akan dilakukan pengguna server.

  • Runtime sandbox menjalankan proksi HTTP/HTTPS dan proksi SOCKS5 di 127.0.0.1 di dalam proses cc_server, satu pasang per sesi yang dibatasi (http_proxy.dart, socks_proxy.dart). Run yang berjalan bersamaan tidak berbagi satu pasang.
  • Proses yang di-sandbox menerima variabel lingkungan proksi (HTTP_PROXY/HTTPS_PROXY → proksi HTTP, ALL_PROXY → proksi SOCKS; GIT_SSH_COMMAND mengarahkan git-over-SSH melalui proksi SOCKS). Di Linux, namespace jaringannya tidak dibagi, jadi proksilah satu-satunya jalan keluar; di macOS sandbox berbagi loopback host dan berbicara langsung dengannya.
  • Host tujuan setiap koneksi dicocokkan dengan daftar izin domain sesi; apa pun selain itu ditolak. Ada dua bentuk wildcard, masing-masing dengan tepat satu *: *.example.com di awal cocok dengan subdomain mana pun (termasuk a.b.example.com) tetapi tidak dengan apex-nya sendiri; bedrock.*.amazonaws.com dengan label di tengah cocok dengan tepat satu label (bedrock.us-east-1.amazonaws.com, bukan bedrock.evil.attacker.amazonaws.com).
  • Daftar izin disusun per sesi dari baseline terkurasi (kBaselineAllowedDomains: penyedia LLM, hosting Git, registri paket), plus domain GitHub (kGithubDomains), plus SandboxSpec.egressAllowlist. Jalur pengiriman tidak pernah meneruskan entri egressAllowlist tambahan, jadi dalam praktiknya setiap run mendapat baseline plus GitHub.
  • Daftar tolak tetap (kBaselineDeniedDomains: endpoint metadata cloud, tujuan telemetri) diutamakan atas semua izin.
  • networkEnabled: false tetap memulai proksi per sesi, tetapi daftar izinnya kosong sehingga setiap koneksi keluar ditolak. Pengiriman menyetelnya saat run dimulai dari aturan Akses jaringan: tolak mematikan jaringan, izinkan dan tanyakan dulu membiarkannya menyala.

Spesifikasi yang diteruskan ke SandboxPort.launch:

Bidang Tipe Deskripsi
sessionId String Pengenal sesi yang stabil (biasanya id space)
workspaceId String Id ruang kerja pemilik
agentId String? Agen yang saat ini terikat ke sandbox, bila ada
bindMounts List<SandboxBindMount> Mount host→guest; sandbox hanya melihat jalur host yang terdaftar di sini
networkEnabled bool (default true) Disetel saat pengiriman dari aturan egress jaringan (mati hanya bila aturan itu diselesaikan menjadi tolak). Bila mati, proksi per sesi tetap dimulai tetapi daftar izinnya kosong sehingga setiap koneksi keluar ditolak
egressAllowlist List<String> (default []) Domain egress tambahan yang diizinkan; wildcard didukung (*.example.com, plus bentuk tengah satu label). Pengiriman tidak pernah mengisi ini, jadi run yang dibungkus mendapat baseline terkurasi plus domain GitHub
guestWorkdir String? Direktori kerja default di dalam sandbox; panggilan exec individual dapat menimpanya
mode Mode (default chat) Memahat aturan tulis sistem berkas: chat membuat bind mount tetap dapat ditulis; review, plan, dan orchestrate bersifat hanya-baca
protectedPaths List<String> (default []) Jalur host yang tidak boleh dapat ditulis di dalam sandbox, dalam mode apa pun
runnerStateDirs List<String> (default []) Direktori host tempat runner menyimpan statusnya sendiri, dapat ditulis di setiap mode (yang berlaku saat ini adalah CLAUDE_CONFIG_DIR yang dikelola Control Center)
execGrantRoots List<String> (default []) Pohon direktori yang disetujui operator yang membuka kembali pemblokiran exec direktori yang dapat ditulis di macOS. Linux mengabaikannya — bwrap tidak memiliki pemblokiran exec $HOME untuk dibuka kembali

protectedPaths berisi checkout repo terdaftar yang asli, yang diselesaikan per pengiriman dari repo milik ruang kerja. Agen bekerja secara eksklusif di worktree copy-on-write per percakapan, jadi yang asli tidak boleh dapat ditulis dari dalam sandbox — di macOS, izin tulis $HOME menyeluruh milik Seatbelt kalau tidak akan membuatnya tetap dapat ditulis melalui bash. Checkout itu bergabung ke himpunan tolak-tulis rahasia di setiap mode, termasuk chat.

Setiap jalur tolak-baca dan tolak-tulis dikeluarkan dalam ejaan literalnya maupun ejaan yang sudah diselesaikan symlink-nya. Kernel mencocokkan aturan tolak terhadap jalur yang sudah diselesaikan, sehingga aturan yang ditulis terhadap jalur bersymlink tidak pernah aktif — dan di macOS itu adalah kasus umum, bukan kasus langka, karena /tmp diselesaikan menjadi /private/tmp dan /var/folders/… menjadi /private/var/folders/…. Entri yang memuat * atau ? diperlakukan sebagai glob dan dibiarkan apa adanya; jalur yang tidak dapat diselesaikan dipertahankan seperti tertulis.

Bidang Tipe Deskripsi
hostPath String Jalur absolut di host
guestPath String Jalur di dalam sandbox (pada sandbox native ini sama dengan hostPath; dipertahankan demi kesimetrisan adapter)
readOnly bool (default false) Mount hanya-baca bila true

Dikembalikan oleh SandboxPort.launch:

Bidang Tipe Deskripsi
sessionId String Pengenal sesi
backend SandboxBackend Backend mana yang berjalan
state SandboxState Status siklus hidup
error Object? Diisi bila state bernilai error
details Map<String, Object?> Pembukuan privat adapter (direktori kerja, PID, jalur profil, dll.)
Status Deskripsi
created Spesifikasi dibuat tetapi VM belum dimulai
warm Berjalan dan siap mengeksekusi perintah
active Sedang mengeksekusi perintah
suspended Dijeda / di-checkpoint ke disk untuk menghemat RAM
destroyed Dibongkar; handle tidak lagi valid
error Peluncuran gagal — lihat SandboxHandle.error
Jenis peristiwa Deskripsi
stdout Keluaran standar dari sandbox
stderr Galat standar dari sandbox
exit Proses sandbox berhenti (membawa exitCode)
starting Sandbox sedang dimulai
ready Sandbox siap menerima panggilan exec
killed Proses dihentikan oleh host (OOM, timeout, penghentian manual)
violation Kebijakan sandbox dilanggar (membawa SandboxViolation)
Bidang Tipe Deskripsi
action String Verb yang ditolak (mis. file-read*, network-outbound)
target String Jalur atau host yang menjadi target operasi yang ditolak
raw String? Baris log mentah, berguna untuk penelusuran kesalahan