Backend sandbox
Ringkasan backend
Bagian berjudul “Ringkasan backend”| 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.
Hasil probe
Bagian berjudul “Hasil probe”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”.
Backend native
Bagian berjudul “Backend native”macOS: Seatbelt
Bagian berjudul “macOS: Seatbelt”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-unlinkditolak pada setiap jalur yang ditolak beserta leluhurnya, sehingga rename tidak dapat melewati penolakan tulis - Proses:
process-execmenolak 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
Linux: bubblewrap
Bagian berjudul “Linux: bubblewrap”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:
bubblewrapdansocatterpasang (sudo apt-get install bubblewrap socatdi 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.
Backend none
Bagian berjudul “Backend none”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 yang dihosting server
Bagian berjudul “Terminal yang dihosting server”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.
Egress jaringan
Bagian berjudul “Egress jaringan”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.1di dalam prosescc_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_COMMANDmengarahkan 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.comdi awal cocok dengan subdomain mana pun (termasuka.b.example.com) tetapi tidak dengan apex-nya sendiri;bedrock.*.amazonaws.comdengan label di tengah cocok dengan tepat satu label (bedrock.us-east-1.amazonaws.com, bukanbedrock.evil.attacker.amazonaws.com). - Daftar izin disusun per sesi dari baseline terkurasi (
kBaselineAllowedDomains: penyedia LLM, hosting Git, registri paket), plus domain GitHub (kGithubDomains), plusSandboxSpec.egressAllowlist. Jalur pengiriman tidak pernah meneruskan entriegressAllowlisttambahan, jadi dalam praktiknya setiap run mendapat baseline plus GitHub. - Daftar tolak tetap (
kBaselineDeniedDomains: endpoint metadata cloud, tujuan telemetri) diutamakan atas semua izin. networkEnabled: falsetetap 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.
SandboxSpec
Bagian berjudul “SandboxSpec”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.
SandboxBindMount
Bagian berjudul “SandboxBindMount”| 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 |
SandboxHandle
Bagian berjudul “SandboxHandle”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.) |
SandboxState
Bagian berjudul “SandboxState”| 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 |
Peristiwa sandbox
Bagian berjudul “Peristiwa sandbox”| 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) |
SandboxViolation
Bagian berjudul “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 |
Lihat juga
Bagian berjudul “Lihat juga”- Sandbox dan keamanan
- Kebijakan sandbox
- Pagar pengaman
- CLI cc_server: flag
--sandbox