Sandbox dan keamanan
Mengapa isolasi penting di sini
Bagian berjudul “Mengapa isolasi penting di sini”Agen membaca berkas, menjalankan perintah shell, dan memanggil API eksternal atas nama Anda. Kegagalan yang Anda khawatirkan jarang berupa niat jahat — melainkan agen yang salah membaca jalur lalu menulis ulang checkout kerja Anda, atau agen yang mendorong cabang yang belum selesai Anda tinjau. Jadi pertanyaan yang harus dijawab produk ini bukan “apakah agen ini dapat dipercaya” melainkan “seberapa besar radius dampaknya saat agen salah”.
Control Center menjawabnya secara berlapis, dan lapisan-lapisan itu sengaja dibuat independen. Jika satu hilang, yang lain tetap bertahan. Itu penting, karena lapisan terluar — sandbox OS — adalah satu-satunya yang bersyarat: ia bergantung pada host yang menyediakan backend, dan di Windows tidak ada host yang menyediakannya.
Apa yang benar-benar membatasi agen
Bagian berjudul “Apa yang benar-benar membatasi agen”Ada lima hal yang membatasi eksekusi agen di setiap host, dengan atau tanpa sandbox. Tidak satu pun merupakan batas kernel; semuanya nyata. Bila host menyediakan backend, sandbox OS berada di atasnya, dan “Apa yang ditambahkan sandbox dan di mana batasnya” di bawah membahas apa yang berubah karenanya.
Worktree copy-on-write-nya sendiri. Setiap percakapan menyediakan
checkout-nya sendiri untuk tiap repo yang ditautkan, diklon secara
copy-on-write melalui rift native yang dibundel alih-alih disalin byte demi
byte, sehingga isolasinya cukup murah untuk dijadikan bawaan. Repositori
terdaftar yang Anda tambahkan ke ruang kerja bukanlah direktori tempat agen
bekerja — dua percakapan yang menyentuh repo yang sama tidak dapat melihat
suntingan satu sama lain dan keduanya tidak menyunting checkout Anda.
Butirannya perlu diperjelas: worktree bersifat per percakapan, bukan per
agen. Dua agen dalam percakapan yang sama mendapat direktori kerja overlay
yang berbeda yang berbagi repos/ percakapan tersebut — dan memang itu
tujuannya, karena keduanya berkolaborasi pada satu perubahan — sementara
direktori agen privat masing-masing tetap terpisah. Copy-on-write adalah
satu-satunya backend di mana pun rift tersedia: sistem berkas yang tidak
dapat melakukan reflink, atau direktori data pada volume berbeda dari repo,
menggagalkan penyediaan alih-alih beralih ke cara lain. Windows adalah
pengecualian — tidak ada backend copy-on-write di sana, jadi git worktree
adalah backendnya, bukan degradasi diam-diam.
Pembatasan jalur di alat berkas harness bawaan. Alat read, write,
edit, apply_patch, search, find, dan search_files milik harness
menyelesaikan setiap jalur terhadap direktori kerja eksekusi plus akar
bersama — direktori repos/ percakapan, tempat worktree berada, dan direktori
lampiran space bila ada — dan menolak apa pun yang berada di luarnya. Jalur
absolut hanya diterima jika memang sudah berada di dalam. Symlink di dalam
worktree yang menunjuk ke luar juga diselesaikan lalu ditolak. Inilah sebabnya
agen tidak dapat write ke ~/.ssh bahkan tanpa sandbox sama sekali.
Permukaan alat milik mode. Mode
sebuah percakapan menentukan alat mana yang diwujudkan untuk eksekusi
tersebut. Dalam mode hanya-baca (plan, review, orchestrate), alat yang
mengubah keadaan memang tidak ada di registri dan kebijakan perintah shell
untuk mode tersebut menolak setiap perintah yang mengubah keadaan secara
langsung — git commit, git push, npm install, docker, dan lainnya —
alih-alih menanyakannya. Alat yang tidak ada tidak dapat dipanggil, dan itu
jaminan yang lebih kuat daripada alat yang ada tetapi dijaga.
Pagar pengaman tindakan yang terpadu. Setiap alat yang mengubah keadaan
mendeklarasikan kelas efek yang dapat dihasilkannya dan mesin kebijakan
menyelesaikan masing-masingnya menjadi izinkan, tanya, atau tolak sebelum
panggilan berjalan. Sebuah prompt tanpa penyetuju yang terhubung
diselesaikan menjadi ditolak — pertanyaan yang tidak dapat dijawab siapa pun
tidak pernah menjadi ya. Lihat
Pagar pengaman untuk model
penyelesaiannya.
Kredensial dari broker dan lingkungan yang disanitasi. Kredensial dibuat per peluncuran dan dicabut saat eksekusi berakhir, dan token GitHub yang dipegang eksekusi dapat membaca tetapi tidak dapat push — lihat “Push melewati Control Center” di bawah. ACP, bash harness, dan Claude Code di
bawah pembungkus native mendapat lingkungan yang dibersihkan dari vektor
injeksi dynamic-linker dan interpreter (LD_PRELOAD, DYLD_INSERT_LIBRARIES,
NODE_OPTIONS, GIT_SSH_COMMAND, dan sejenisnya) sebelum proses dimulai.
Claude Code melalui NoSandboxAdapter mewarisi lingkungan host.
Di mana batas-batas itu menipis
Bagian berjudul “Di mana batas-batas itu menipis”Alat berkas milik harness berjalan di dalam proses server, bukan di proses
anak, sehingga tidak ada profil sandbox yang dapat membatasinya bahkan jika
dipasang — hanya bash yang melewati runner perintah yang di-sandbox.
Pembatasannya adalah pemeriksaan jalur yang dijelaskan di atas, dan karena itu
pemeriksaan tersebut bersifat menopang, bukan sekadar lapisan pertahanan
kedua.
Alat bash adalah tempat lain yang perlu ketelitian. Perintahnya dievaluasi
terhadap kebijakan perintah mode lalu dijalankan dengan lingkungan yang
disanitasi dan worktree sebagai direktori kerjanya. Bila backend tersedia,
proses itu dibungkus, jadi sandbox-lah yang mencegah perintah shell menulis di
luar worktree; bila tidak ada — Windows, atau Linux tanpa bwrap dan socat —
kebijakan perintah adalah satu-satunya yang berdiri antara perintah dan sisa
disk. Dalam mode chat kebijakan menolak secara keras daftar tetap (eskalasi
hak istimewa, penghancuran sistem dan disk, pelarian kontainer dan namespace)
dan menanyakan mutasi keadaan jarak jauh (git push, gh pr create,
publikasi dan pemasangan paket). Apa pun yang tidak ada di kedua daftar itu
akan berjalan. Pipeline, rantai, dan sub-shell diurai dan tiap sub-perintah
dievaluasi terpisah, dengan keputusan paling ketat yang menang.
Claude Code, saat dipakai sebagai adapter, adalah kasus ketika sandbox
memikul beban terbesar. Control Center meluncurkannya dengan
--dangerously-skip-permissions, karena claude -p yang non-interaktif akan
tersendat selamanya pada prompt persetujuannya sendiri. Panggilan baca, tulis, dan edit-nya terjadi di dalam prosesnya sendiri dan Control Center tidak pernah melihatnya. Panggilan Bash-nya dikirim, sebelum dijalankan, ke hook di server yang mengklasifikasikan baris perintah dan menanyakan aturan yang cocok, dan alat mcp__* yang dilayani Control Center melewati gerbang seperti biasa. Bila backend tersedia,
panggilan tak terlihat itu tetap terjadi di dalam pembungkus sandbox, jadi
OS-lah batas di sekelilingnya. Bila tidak ada, tidak ada apa pun. Setiap
adapter menyatakan hal ini dalam matriks penegakannya — lihat matriks
kejujuran adapter.
Push melewati Control Center
Bagian berjudul “Push melewati Control Center”Tidak ada flag izin per agen. Apakah agen boleh membuat commit, melakukan push, membuka pull request, menulis ke pelacak, atau menjangkau jaringan ditentukan oleh pagar pengaman — izinkan, tanyakan dulu, atau tolak — dan aturan yang sama berlaku adapter mana pun yang menjalankan agen.
Push adalah aksi yang harus tetap bertahan bahkan terhadap agen yang mencoba
mengakali aturan, jadi push ditegakkan lewat apa yang dipegang agen, bukan lewat
apa yang dijalankannya. Dengan GitHub App yang terkonfigurasi, eksekusi di
worktree GitHub mendapat token instalasi bercakupan repo yang dapat membaca
konten dan bekerja dengan pull request, tetapi tidak dapat push. Konfigurasi git
eksekusi menulis ulang setiap URL push GitHub (https://github.com/,
git@github.com:, ssh://git@github.com/) ke gateway run agen, sebuah
endpoint loopback di cc_server. Gateway membaca ref mana yang diperbarui oleh
push, menanyakan aturan Push ke remote — sehingga aturan yang dibatasi ke
branch, seperti “tolak push ke main”, ikut berlaku — dan baru setelah itu
meneruskan push ke GitHub dengan token tulis yang dibuatnya untuk keperluan itu
dan tidak pernah diserahkan ke agen. Push yang ditolak muncul di keluaran git
itu sendiri:
! [remote rejected] main -> main (Control Center policy: …)Gateway hanya meneruskan push ke repo milik worktree itu sendiri atau ke repo GitHub yang ditautkan ke ruang kerja. Fetch langsung ke GitHub dengan token baca.
Perintah shell lainnya menemui gerbang yang lebih lunak. Alat bash milik
harness dan, melalui hook, alat Bash milik Claude Code mengklasifikasikan
setiap baris perintah dan menanyakan aturan yang menaunginya: git commit,
merge, rebase, cherry-pick, revert, dan am adalah Buat commit;
gh pr create adalah Buka pull request; gh pr merge, review,
comment, dan close adalah Publikasikan review atau merge;
gh issue create, edit, comment, dan close adalah Tulis ke pelacak
eksternal; instalasi paket adalah Instal paket; curl dan wget adalah
Akses jaringan. Ini mengenali penulisan lazim sebuah aksi, dan agen yang
bertekad menyembunyikannya (eval, berkas skrip, panggilan API langsung) bisa
melakukannya. Push tidak bergantung pada hal ini.
Tidak ada kunci API tiket yang ditaruh di sandbox. Agen menulis tiket melalui alat MCP Control Center, yang menanyakan Tulis ke pelacak eksternal.
Aturan Akses jaringan dibaca sekali, saat eksekusi dimulai. Jaringan sandbox
hanya bisa menyala atau mati, jadi tolak mematikannya sementara izinkan dan
tanyakan dulu membiarkannya menyala; alat web_fetch dan web_search milik
harness tetap bertanya di setiap panggilan. Kredensial dicabut saat eksekusi
dibongkar, bersama setiap token tulis yang dibuat gateway, jadi handle tidak
hidup lebih lama daripada eksekusi.
Apa yang ditambahkan sandbox dan di mana batasnya
Bagian berjudul “Apa yang ditambahkan sandbox dan di mana batasnya”Enum SandboxBackend memiliki tiga nilai — native (Seatbelt di macOS,
bubblewrap di Linux dan WSL2), none, dan microvm. Pembungkusan perintah
agen hanya memakai dua yang pertama: microvm adalah backend VM tertutup
untuk terminal interaktif dan rigs, bukan peningkatan diam-diam dari pembungkus
bash. Memahami bentuk native menjelaskan apa yang Anda dapatkan saat backend
terpasang dan apa yang memang tidak akan pernah diberikannya.
cc_server menyelidiki host sekali saat boot dan bila backend merespons ia
mengisi kedua titik sambung yang dimiliki jalur pengiriman, karena transportnya
tidak berbagi satu. Yang pertama (SandboxPort) membungkus CLI Claude Code.
Yang kedua (SandboxManager) membungkus adapter ACP dan alat bash harness
bawaan. Mengisi hanya salah satu akan membuat yang lain dijalankan tanpa
pembungkus, dan itulah yang dahulu terjadi. Di host tanpa backend, atau di
bawah --sandbox off, semuanya dijalankan tanpa pembungkus dan server
menyebutkan kasus mana yang Anda alami di baris startup-nya. ACP dan bash
harness tetap menyanitasi lingkungan; Claude Code melalui NoSandboxAdapter
mewarisi lingkungan host.
Satu permukaan sengaja memilih keluar: terminal yang dihosting server menerima
argumen backend per sesi dan cc_server membangunnya dengan bawaan shell host,
jadi terminal yang Anda buka dari aplikasi berjalan tanpa sandbox kecuali
klien menyebut native secara eksplisit. Itu adalah shell sungguhan di host
server, bukan eksekusi agen.
Di Linux, bubblewrap membangun namespace mount, sehingga agen benar-benar
hanya melihat apa yang di-bind ke dalamnya. Di macOS, sandbox-exec menerapkan
profil Seatbelt yang permisif secara bawaan — profil yang sepenuhnya
menolak secara bawaan membuat shell interaktif tidak dapat dipakai, karena
jumlah panggilan dyld, XPC, dan Mach yang harus dienumerasi tidak praktis.
Karena itu profil macOS dimulai dari (allow default) lalu memahat
penolakannya: pembacaan jalur rahasia, kebijakan tulis yang diatur ulang ke
tolak dengan izin eksplisit di atasnya, pemblokiran unlink pada setiap jalur
yang ditolak beserta leluhurnya agar rename tidak dapat melewati penolakan
tulis, penolakan exec untuk biner yang selalu berbahaya dan untuk apa pun yang
disalin ke direktori yang dapat ditulis, serta jaringan yang dibatasi ke port
proksi loopback plus DNS.
Konsekuensi praktisnya: di Linux pandangan agen terhadap sistem berkas dipersempit; di macOS agen masih dapat membaca sebagian besar host dan checkout terdaftar Anda dilindungi oleh penolakan tulis dan rename yang eksplisit, bukan oleh ketaknampakan. Keduanya adalah isolasi tingkat namespace, bukan batas keamanan kernel — para backend menyatakannya di catatan kemampuan mereka masing-masing.
Himpunan bind-mount itulah tempat batas antaragen ditarik. Pengiriman overlay
(Claude Code dan ACP) me-mount hingga empat jalur, yang diselesaikan per
eksekusi: direktori kerja overlay agen dengan akses baca-tulis, direktori
konfigurasi agen dengan akses hanya-baca, direktori repos/ bersama milik
percakapan dengan akses baca-tulis bila ada, dan direktori lampiran space
dengan akses hanya-baca bila ada. Direktori agen saudara tidak pernah
di-mount. Pembungkus bash harness lebih sempit: ia hanya me-bind-mount
direktori kerja eksekusi. Ini bentuk yang sama dengan yang ditegakkan
pemeriksaan jalur dalam proses milik harness di perangkat lunak, jadi keduanya
sejalan — tetapi hanya pemeriksaan jalur yang mencakup alat berkas milik
harness sendiri, yang sama sekali tidak pernah mencapai namespace mount.
Checkout terdaftar Anda bergabung ke himpunan tolak-tulis di atas itu, dalam
setiap mode dan pada ketiga jalur yang dibungkus (Claude Code, ACP, bash
harness), dan tiap aturan dikeluarkan dalam ejaan literalnya maupun ejaan yang
sudah diselesaikan symlink-nya. Ejaan kedua bukan sekadar kerapian: kernel
mencocokkan aturan tolak terhadap jalur yang sudah diselesaikan dan macOS
menjadikan penyelesaian itu kasus umum, bukan kasus langka — /tmp sebenarnya
/private/tmp, /var/folders/… sebenarnya /private/var/folders/… — sehingga
checkout yang dicapai lewat keduanya akan dapat ditulis padahal profil tampak
melarangnya.
Jaringan, di bawah sandbox, adalah daftar izin domain per sesi yang
ditegakkan oleh proksi loopback dalam proses. Egress ditolak secara bawaan:
saat jaringan mati, proksi tetap dimulai tetapi daftar izinnya kosong, jadi
setiap koneksi keluar ditolak. Saat menyala, resolver menyusun daftar izin dari
baseline terkurasi — penyedia API LLM, hosting git, registri paket, katalog
model — plus domain GitHub, lalu mencocokkan host tujuan setiap koneksi
dengannya. Wildcard berfungsi (*.example.com cocok dengan subdomain, bukan
apex-nya). Daftar yang selalu ditolak terpisah menang atas daftar izin dan
mencakup endpoint metadata cloud serta tujuan telemetri. Yang tidak dapat
dikonfigurasi adalah daftar itu sendiri: spesifikasi membawa bidang
egressAllowlist untuk domain tambahan, tetapi tidak ada apa pun di jalur
pengiriman yang mengisinya, jadi dalam praktiknya setiap eksekusi mendapat
baseline plus GitHub dan tidak lebih.
Penolakan, di macOS, dapat diamati: sebuah monitor menyadap log sistem untuk
penolakan Sandbox, menyaring derau yang dikenal, menghilangkan duplikat badai
percobaan ulang, dan memunculkan masing-masingnya sebagai SandboxViolation
yang menyebutkan apa yang dicoba dan apa yang diblokir. Di
Linux jalur pembungkus mengurai stderr untuk EPERM,
Operation not permitted, dan Permission denied lalu memancarkan jenis
peristiwa yang sama — tidak ada penyadapan log sistem. Peristiwa itu tiba di
aliran peristiwa milik eksekusi, sehingga panggilan sistem yang ditolak muncul
di transkrip, bukan hanya di log. Telemetri ini hanya ada selama sandbox native
benar-benar membungkus proses — di host tanpa backend tidak ada apa pun untuk
diamati. Ini juga tidak berkaitan dengan pagar pengaman: pelanggaran berasal dari panggilan sistem yang ditolak, tidak pernah dari pencarian aturan.
Konfirmasi berasal dari pagar pengaman, bukan sandbox
Bagian berjudul “Konfirmasi berasal dari pagar pengaman, bukan sandbox”Sandbox tidak punya jalur persetujuan. Ia meluncurkan, mengeksekusi, memancarkan peristiwa, lalu membongkar; tidak ada tempat di dalamnya bagi manusia untuk menjawab pertanyaan. Saat Anda melihat konfirmasi di sebuah space — setujui push ini, setujui penghapusan ini — konfirmasi itu dimunculkan oleh mesin pagar pengaman (atau kebijakan perintah harness) sebelum tindakan itu mencapai runtime sama sekali.
Urutan ini disengaja. Persetujuan yang terjadi setelah panggilan sistem hanyalah catatan audit, bukan gerbang. Itu juga sebabnya aturan gagal-tertutup berada di pagar pengaman: bila tidak ada penyetuju yang terhubung, keputusan dibuat sebelum apa pun berjalan dan hasilnya adalah penolakan.
Diagnostik
Bagian berjudul “Diagnostik”Jalankan diagnosis agen adalah satu-satunya tempat yang menyatakan apa yang dapat diperiksa secara manual.
Konsep terkait
Bagian berjudul “Konsep terkait”- Rigs dan lingkungan terisolasi: langkah di atas sandbox — ketika pekerjaan membutuhkan mesin sekali pakai utuh dengan batas kernel, bukan proses yang dibungkus
- Pagar pengaman: lapisan kebijakan di atas dasar OS dan tempat persetujuan sebenarnya berasal
- Siklus hidup pengiriman agen: tempat isolasi masuk ke dalam alur pengiriman
- Mode: bagaimana mode mempersempit permukaan alat dan kebijakan perintah
- Referensi backend sandbox: backend dan konfigurasinya
Panduan terkait
Bagian berjudul “Panduan terkait”- Konfigurasi kebijakan sandbox: aturan aksi, penegakan push, dan postur sistem berkas
- Jalankan diagnosis agen: cakupan pemeriksaan diagnostik