Kotak pasir dan keselamatan
Mengapa pengasingan penting di sini
Bahagian bertajuk “Mengapa pengasingan penting di sini”Ejen membaca fail, menjalankan perintah shell dan memanggil API luaran bagi pihak anda. Kegagalan yang anda risaukan jarang berpunca daripada niat jahat — ia ialah ejen yang tersalah baca laluan dan menulis semula checkout kerja anda, atau ejen yang push cawangan yang belum anda selesai semak. Jadi persoalan yang perlu dijawab oleh produk ini bukan “bolehkah ejen dipercayai” tetapi “apakah jejari letupan apabila ia tersilap”.
Control Center menjawabnya secara berlapis dan lapisan-lapisan itu memang sengaja berdikari. Jika satu hilang, yang lain masih bertahan. Itu penting, kerana lapisan paling luar — kotak pasir OS — ialah satu-satunya yang bersyarat: ia bergantung pada hos yang menawarkan bahagian belakang dan pada Windows tiada hos yang berbuat demikian.
Apa yang sebenarnya membataskan ejen
Bahagian bertajuk “Apa yang sebenarnya membataskan ejen”Lima perkara membataskan larian ejen pada setiap hos, dengan atau tanpa kotak pasir. Tiada satu pun daripadanya sempadan kernel; semuanya nyata. Apabila hos menawarkan bahagian belakang, kotak pasir OS duduk di atasnya dan “Apa yang ditambah oleh kotak pasir dan di mana ia berhenti” di bawah merangkumi apa yang berubah.
Worktree copy-on-write tersendiri. Setiap perbualan menyediakan checkout
sendiri bagi setiap repo yang dipautkan, diklon secara copy-on-write melalui
natif rift yang disertakan dan bukan disalin bait demi bait, jadi pengasingan
cukup murah untuk dijadikan lalai. Repositori berdaftar yang anda tambahkan pada
ruang kerja bukanlah direktori tempat ejen bekerja — dua perbualan yang menyentuh
repo yang sama tidak dapat melihat suntingan satu sama lain dan kedua-duanya tidak
menyunting checkout anda.
Butirannya wajar diperjelas: worktree adalah bagi setiap perbualan, bukan setiap
ejen. Dua ejen dalam perbualan yang sama mendapat direktori kerja overlay yang
berbeza yang berkongsi repos/ perbualan itu — itulah maksudnya, kerana mereka
bekerjasama pada satu perubahan — sementara direktori ejen peribadi mereka kekal
berasingan. Copy-on-write ialah satu-satunya bahagian belakang di mana sahaja
rift disertakan: sistem fail yang tidak boleh reflink, atau dir data pada volum
berbeza daripada repo, menggagalkan penyediaan dan bukannya berpatah balik.
Windows ialah pengecualian — tiada bahagian belakang copy-on-write di sana, jadi
git worktree ialah bahagian belakangnya, bukan kemerosotan senyap.
Kekangan laluan dalam alat fail harness terbina. Alat read, write, edit,
apply_patch, search, find dan search_files harness menyelesaikan setiap
laluan terhadap direktori kerja larian serta akar kongsi — direktori repos/
perbualan, tempat worktree berada, dan dir lampiran ruang apabila wujud — dan
menolak apa-apa yang terletak di luar. Laluan mutlak hanya diterima jika ia sudah
berada di dalam. Symlink di dalam worktree yang menunjuk ke luar juga diselesaikan
dan ditolak. Inilah sebabnya ejen tidak boleh write ke ~/.ssh walaupun tanpa
kotak pasir.
Permukaan alat modus. Modus sesuatu
perbualan menentukan alat mana yang dizahirkan untuk larian itu sama sekali. Dalam
modus baca sahaja (plan, review, orchestrate), alat yang mengubah keadaan
langsung tidak ada dalam daftar dan polisi perintah shell bagi modus tersebut
menolak setiap perintah yang mengubah keadaan secara terus — git commit,
git push, npm install, docker dan seumpamanya — dan bukannya meminta
pengesahan untuknya. Alat yang tidak hadir tidak boleh dipanggil, dan itu jaminan
yang lebih kukuh daripada alat yang hadir tetapi dipagari.
Guardrail tindakan bersatu. Setiap alat yang mengubah keadaan mengisytiharkan
kelas kesan yang boleh dihasilkannya dan enjin polisi menyelesaikan setiap satu
kepada benarkan, tanya dahulu, atau tolak sebelum panggilan itu dijalankan. Satu
prompt tanpa pelulus yang bersambung diselesaikan kepada ditolak — soalan
yang tiada siapa dapat jawab tidak pernah menjadi ya. Lihat
Guardrail untuk model penyelesaiannya.
Kelayakan melalui broker dan persekitaran yang disanitasi. Kelayakan ditempa setiap pelancaran dan ditarik balik apabila larian tamat, dan token GitHub yang dipegang larian boleh membaca tetapi tidak boleh push — lihat “Push melalui Control Center” di bawah. ACP, bash harness dan Claude Code di bawah balutan natif
mendapat persekitaran yang dilucutkan vektor suntikan pemaut dinamik dan
penterjemah (LD_PRELOAD, DYLD_INSERT_LIBRARIES, NODE_OPTIONS,
GIT_SSH_COMMAND dan seumpamanya) sebelum proses bermula. Claude Code melalui
NoSandboxAdapter mewarisi persekitaran hos.
Di mana sempadan itu menipis
Bahagian bertajuk “Di mana sempadan itu menipis”Alat fail harness berjalan dalam proses pelayan, bukan dalam proses anak, jadi
tiada profil kotak pasir dapat membataskannya walaupun satu dilekatkan — hanya
bash melalui pelari perintah berkotak pasir. Kekangan mereka ialah semakan
laluan yang dihuraikan di atas, dan oleh itu semakan itu menanggung beban utama
dan bukan sekadar barisan pertahanan kedua.
Alat bash ialah tempat lain yang perlu diperjelas. Perintahnya dinilai terhadap
polisi perintah modus dan kemudian dilancarkan dengan persekitaran yang
disanitasi serta worktree sebagai direktori kerjanya. Apabila bahagian belakang
wujud, pelancaran itu dibalut, jadi kotak pasirlah yang menghalang perintah shell
daripada menulis di luar worktree; apabila tiada — Windows, atau Linux tanpa
bwrap dan socat — polisi perintah ialah satu-satunya perkara antara perintah
itu dan seluruh cakera yang lain. Dalam modus chat, polisi itu menolak secara
mutlak senarai tetap (peningkatan keistimewaan, pemusnahan sistem dan cakera,
pelarian kontena dan namespace) dan meminta pengesahan bagi mutasi keadaan jauh
(git push, gh pr create, penerbitan dan pemasangan pakej). Apa-apa yang tiada
dalam kedua-dua senarai akan berjalan. Saluran paip, rantaian dan subshell
dihuraikan dan setiap sub-perintah dinilai secara berasingan, dengan keputusan
paling ketat yang menang.
Claude Code, apabila digunakan sebagai penyesuai, ialah kes yang kotak pasir
memikul beban paling berat. Control Center melancarkannya dengan
--dangerously-skip-permissions, kerana claude -p bukan interaktif akan
tersekat selama-lamanya pada gesaan kelulusannya sendiri. Panggilan baca, tulis dan edit-nya berlaku di dalam prosesnya sendiri dan Control Center tidak pernah melihatnya. Panggilan Bash-nya dihantar, sebelum dijalankan, kepada hook pada pelayan yang mengelaskan baris perintah dan bertanya kepada peraturan yang sepadan, dan alat mcp__* yang disediakan Control Center melalui pintu pagar seperti biasa. Apabila bahagian belakang wujud,
panggilan yang tidak kelihatan itu masih berlaku di dalam balutan kotak pasir,
jadi OS ialah sempadan di sekelilingnya. Apabila tiada, tiada apa-apa. Setiap
penyesuai menyatakan hal ini dalam matriks penguatkuasaannya — lihat matriks
kejujuran penyesuai.
Push melalui Control Center
Bahagian bertajuk “Push melalui Control Center”Tiada bendera kebenaran bagi setiap ejen. Sama ada ejen boleh mencipta commit, push, membuka pull request, menulis ke penjejak atau mencapai rangkaian ditentukan oleh guardrail — benarkan, tanya dahulu atau tolak — dan peraturan yang sama terpakai tanpa mengira penyesuai yang menjalankan ejen.
Push ialah tindakan yang mesti bertahan walaupun terhadap ejen yang cuba
memintas sesuatu peraturan, jadi ia dikuatkuasakan melalui apa yang dipegang
ejen, bukan melalui apa yang dijalankannya. Dengan GitHub App dikonfigurasikan,
larian dalam worktree GitHub mendapat token pemasangan berskop repo yang boleh
membaca kandungan dan bekerja dengan pull request tetapi tidak boleh push.
Konfigurasi git larian menulis semula setiap URL push GitHub
(https://github.com/, git@github.com:, ssh://git@github.com/) kepada
gerbang larian ejen, titik akhir loopback pada cc_server. Gerbang itu
membaca ref mana yang dikemas kini oleh push, bertanya kepada peraturan
Push ke remote — jadi peraturan yang dihadkan kepada cabang, seperti “tolak
push ke main”, turut terpakai — dan barulah memajukan push itu ke GitHub
dengan token tulis yang ditempanya untuk tujuan itu dan tidak pernah diserahkan
kepada ejen. Push yang ditolak muncul dalam output git sendiri:
! [remote rejected] main -> main (Control Center policy: …)Gerbang itu hanya memajukan push ke repo worktree itu sendiri atau ke repo GitHub yang dipautkan kepada ruang kerja. Fetch terus ke GitHub dengan token baca.
Perintah shell lain menemui pintu pagar yang lebih lembut. Alat bash harness
dan, melalui hook, alat Bash Claude Code mengelaskan setiap baris perintah
dan bertanya kepada peraturan yang menaunginya: git commit, merge,
rebase, cherry-pick, revert dan am ialah Cipta commit;
gh pr create ialah Buka pull request; gh pr merge, review, comment
dan close ialah Terbitkan semakan atau cantuman; gh issue create,
edit, comment dan close ialah Tulis ke penjejak luaran; pemasangan
pakej ialah Pasang pakej; curl dan wget ialah Akses rangkaian. Ini
mengenali cara lazim menulis sesuatu tindakan, dan ejen yang bertekad
menyembunyikannya (eval, fail skrip, panggilan API terus) boleh berbuat
demikian. Push tidak bergantung padanya.
Tiada kunci API tiket diletakkan dalam kotak pasir. Ejen menulis tiket melalui alat MCP Control Center, yang bertanya kepada Tulis ke penjejak luaran.
Peraturan Akses rangkaian dibaca sekali, apabila larian bermula. Rangkaian
kotak pasir sama ada hidup atau mati, jadi tolak mematikannya manakala benarkan
dan tanya dahulu membiarkannya hidup; alat web_fetch dan web_search harness
masih bertanya pada setiap panggilan. Kelayakan ditarik balik apabila larian
dimusnahkan, bersama setiap token tulis yang ditempa oleh gerbang, jadi sesuatu
pemegang tidak hidup lebih lama daripada larian.
Apa yang ditambah oleh kotak pasir dan di mana ia berhenti
Bahagian bertajuk “Apa yang ditambah oleh kotak pasir dan di mana ia berhenti”Enum SandboxBackend mempunyai tiga nilai — native (Seatbelt pada macOS,
bubblewrap pada Linux dan WSL2), none, dan microvm. Pembalutan perintah ejen
hanya menggunakan dua yang pertama: microvm ialah bahagian belakang VM terasing
untuk terminal interaktif dan stesen, bukan peningkatan senyap bagi balutan
bash. Memahami bentuk natif menjelaskan apa yang anda peroleh apabila satu
dilekatkan dan apa yang ia tidak akan pernah berikan.
cc_server menyiasat hos sekali semasa permulaan dan apabila bahagian belakang
menjawab, ia menyuap kedua-dua sambungan yang ada pada laluan penghantaran,
kerana pengangkutan itu tidak berkongsi satu. Yang pertama (SandboxPort)
membalut CLI Claude Code. Yang kedua (SandboxManager) membalut penyesuai ACP
dan alat bash harness terbina. Menyuap hanya satu akan menyebabkan yang lain
dilancarkan tanpa balutan, yang memang pernah berlaku. Pada hos tanpa bahagian
belakang, atau di bawah --sandbox off, semuanya dilancarkan tanpa balutan dan
pelayan menyatakan kes mana yang anda alami pada baris permulaannya. ACP dan
bash harness masih menyanitasi persekitaran; Claude Code melalui
NoSandboxAdapter mewarisi persekitaran hos.
Satu permukaan sengaja mengecualikan diri: terminal yang dihoskan pelayan
menerima argumen bahagian belakang bagi setiap sesi dan cc_server membinanya
dengan lalai kepada shell hos, jadi terminal yang anda buka dari aplikasi berjalan
tanpa kotak pasir melainkan klien menamakan native secara eksplisit. Itu shell
sebenar pada hos pelayan, bukan larian ejen.
Pada Linux, bubblewrap membina namespace mount, jadi ejen benar-benar melihat
hanya apa yang diikat masuk ke dalamnya. Pada macOS, sandbox-exec mengenakan
profil Seatbelt yang permisif secara lalai — profil yang menolak secara lalai
sepenuhnya menjadikan shell interaktif tidak boleh digunakan, kerana bilangan
panggilan dyld, XPC dan Mach untuk disenaraikan tidak praktikal. Oleh itu profil
macOS bermula daripada (allow default) dan mengukir penolakan: bacaan laluan
rahsia, polisi tulis yang ditetapkan semula kepada tolak dengan benarkan eksplisit
di atasnya, penyekatan unlink pada setiap laluan yang ditolak dan nenek moyangnya
supaya penamaan semula tidak dapat memintas penolakan tulis, penolakan exec untuk
binari yang sentiasa berbahaya dan untuk apa-apa yang disalin ke direktori boleh
tulis, serta rangkaian yang dihadkan kepada port proksi loopback dan DNS.
Akibat praktikalnya: pada Linux, pandangan ejen terhadap sistem fail disempitkan; pada macOS, ejen masih boleh membaca sebahagian besar hos dan checkout berdaftar anda dilindungi oleh penolakan tulis dan penamaan semula yang eksplisit dan bukannya oleh ketaknampakan. Kedua-duanya ialah pengasingan peringkat namespace, bukan sempadan keselamatan kernel — bahagian belakang sendiri menyatakannya dalam nota keupayaan masing-masing.
Set bind-mount ialah tempat sempadan antara ejen dilukis. Penghantaran overlay
(Claude Code dan ACP) melekatkan sehingga empat laluan, diselesaikan bagi setiap
larian: direktori kerja overlay ejen sebagai baca-tulis, direktori konfigurasi
ejen sebagai baca sahaja, direktori repos/ kongsi perbualan sebagai baca-tulis
apabila wujud, dan direktori lampiran ruang sebagai baca sahaja apabila wujud.
Direktori ejen rakan sebaya tidak pernah dilekatkan. Balutan bash harness lebih
sempit: ia hanya melekatkan direktori kerja larian. Ini bentuk yang sama yang
dikuatkuasakan oleh semakan laluan dalam proses harness melalui perisian, jadi
kedua-duanya sependapat — tetapi hanya semakan laluan yang meliputi alat fail
harness sendiri, yang langsung tidak sampai ke namespace mount.
Checkout berdaftar anda menyertai set tolak-tulis di atas itu, dalam setiap modus
dan pada ketiga-tiga laluan yang dibalut (Claude Code, ACP, bash harness), dan
setiap peraturan dikeluarkan dalam ejaan literal serta ejaan yang diselesaikan
symlink. Ejaan kedua bukan sekadar hal kecil: kernel memadankan peraturan
penolakan terhadap laluan yang diselesaikan dan macOS menjadikan penyelesaian itu
kes biasa dan bukan kes eksotik — /tmp sebenarnya /private/tmp,
/var/folders/… sebenarnya /private/var/folders/… — jadi checkout yang dicapai
melalui mana-mana satu pun akan boleh ditulis sedangkan profil itu kelihatan
melarangnya.
Rangkaian, di bawah kotak pasir, ialah senarai benarkan domain bagi setiap
sesi yang dikuatkuasakan oleh proksi loopback dalam proses. Keluar adalah tolak
secara lalai: apabila rangkaian dimatikan, proksi tetap bermula tetapi senarai
benarkannya kosong, jadi setiap sambungan keluar ditolak. Apabila ia dihidupkan,
penyelesai membina senarai benarkan daripada dasar yang dikurasi — penyedia API
LLM, hos git, daftar pakej, katalog model — serta domain GitHub, dan memadankan
hos sasaran setiap sambungan dengannya. Kad liar berfungsi (*.example.com
memadankan subdomain, bukan puncak domain). Senarai yang sentiasa ditolak secara
berasingan menang ke atas senarai benarkan dan meliputi titik akhir metadata
awan serta pengumpul telemetri. Apa yang tidak boleh dikonfigurasi ialah
senarai itu sendiri: spesifikasi membawa medan egressAllowlist untuk domain
tambahan, tetapi tiada apa-apa dalam laluan penghantaran yang mengisinya, jadi
dalam praktiknya setiap larian mendapat dasar itu serta GitHub dan tiada lagi.
Penolakan, pada macOS, boleh diperhatikan: pemantau menyadap log sistem untuk
penolakan Sandbox, menapis bunyi yang diketahui, menyahduplikasi badai cubaan
semula dan memunculkan setiap satu sebagai SandboxViolation yang menamakan apa yang dicuba dan apa yang disekat. Pada Linux, laluan
balutan menghurai stderr untuk EPERM, Operation not permitted dan
Permission denied dan mengeluarkan jenis peristiwa yang sama — tiada penyadapan
log sistem. Semuanya tiba pada aliran peristiwa larian itu sendiri, jadi panggilan
sistem yang ditolak muncul dalam transkrip dan bukan hanya dalam log. Telemetri
itu hanya wujud semasa kotak pasir natif benar-benar membalut proses itu — pada
hos tanpa bahagian belakang tiada apa-apa untuk diperhatikan. Ia juga tidak berkaitan dengan guardrail: pelanggaran datang daripada panggilan sistem yang ditolak, tidak pernah daripada carian peraturan.
Pengesahan datang daripada guardrail, bukan kotak pasir
Bahagian bertajuk “Pengesahan datang daripada guardrail, bukan kotak pasir”Kotak pasir tiada laluan kelulusan. Ia melancarkan, melaksanakan, mengeluarkan peristiwa dan memusnahkan; tiada tempat di dalamnya untuk manusia menjawab soalan. Apabila anda melihat pengesahan dalam sesuatu ruang — luluskan push ini, luluskan pemadaman ini — ia dibangkitkan oleh enjin guardrail (atau polisi perintah harness) sebelum tindakan itu sampai ke masa jalan sama sekali.
Susunan ini memang disengajakan. Kelulusan yang berlaku selepas panggilan sistem hanyalah rekod audit, bukan pintu pagar. Itulah juga sebab peraturan gagal-tertutup terletak dalam guardrail: tanpa pelulus yang bersambung, keputusan dibuat sebelum apa-apa berjalan dan keputusan itu ialah penolakan.
Diagnostik
Bahagian bertajuk “Diagnostik”Jalankan diagnosis ejen ialah satu-satunya tempat yang menyatakan apa yang boleh diperiksa secara manual.
Konsep berkaitan
Bahagian bertajuk “Konsep berkaitan”- Stesen dan persekitaran terasing: langkah di atas kotak pasir — apabila kerja memerlukan mesin pakai buang sepenuhnya dengan sempadan kernel, bukan proses yang dibalut
- Guardrail: lapisan polisi di atas lantai OS dan tempat kelulusan sebenarnya datang
- Kitaran hayat penghantaran ejen: di mana pengasingan berada dalam aliran penghantaran
- Modus: bagaimana sesuatu modus menyempitkan permukaan alat dan polisi perintah
- Rujukan bahagian belakang kotak pasir: bahagian belakang dan konfigurasinya
Panduan berkaitan
Bahagian bertajuk “Panduan berkaitan”- Konfigurasikan polisi kotak pasir: peraturan tindakan, penguatkuasaan push dan postur sistem fail
- Jalankan diagnosis ejen: apa yang diliputi oleh pemeriksaan diagnostik