Бекенди пісочниці
Огляд бекендів
Розділ із назвою «Огляд бекендів»| Бекенд | Значення | Платформа | Доступність |
|---|---|---|---|
| Ізольована ВМ | microvm |
macOS, Linux, Windows (гіпервізор мікроВМ) | Доступний лише після зондування середовища виконання мікроВМ; застосовується до інтерактивних терміналів — шел виконується всередині rig, а не на хості |
| Нативний | native |
macOS (Seatbelt), Linux і WSL2 (bubblewrap) | Зондується під час завантаження; Linux відмовляє в запуску, який вимагає заборон запису за глобом імені файлу, яких bubblewrap не може забезпечити |
| Немає | none |
Усі | Типове значення розбору, типове значення термінала та запасний варіант, коли жоден бекенд недоступний або задано --sandbox off |
SandboxBackend.fromName повертає none для null або нерозпізнаного збереженого значення. Збережене "docker" зіставляється з native.
microvm — єдиний бекенд із межею ядра — робоче навантаження
справді не виконується на хості. Він ніколи не буває тихим запасним варіантом у
жодному напрямку: явний запит на нього на хості, який не може завантажити ВМ,
гучно зривається («я просив ВМ, а отримав ноутбук» — це єдина деградація, яку
оболонка не може собі дозволити), і лише незазначене типове значення
знижується до native, про що є рядок у журналі. Фактичний бекенд сесії
повертається клієнту й позначається бейджем, тож термінал ніколи не може
стверджувати, що він ізольований, виконуючись на хості. Життєвий цикл, образи й
вихідний трафік самої ВМ описано в довідці про rigs.
У Windows нативної пісочниці немає. NativeSandboxAdapter.probe повертає available: false на кожному хості, який не є macOS або Linux/WSL2. Тож диспетчеризація агентів у Windows використовує none. Бекенд microvm — окремий: він доступний лише після зондування середовища виконання мікроВМ і застосовується до інтерактивних терміналів і rigs, а не до загортання bash на хості.
Результати зондування
Розділ із назвою «Результати зондування»Саме зонд визначає, чи буде примус. Він виконується один раз, під час завантаження сервера.
| Хост | available |
Примітка / підказка |
|---|---|---|
| macOS | true |
sandbox-exec (Seatbelt) — ізоляція просторів імен, без межі ядра |
Linux або WSL2 з bwrap і socat |
true |
bubblewrap — ізоляція просторів імен, без межі ядра |
| Linux або WSL2, де бракує одного з інструментів | false |
requiresInstall: true, з підказкою щодо встановлення, яка називає відсутні пакети |
| Будь-яка інша платформа | false |
Нативна пісочниця на цій платформі не пропонується |
Сервер записує результат одним рядком під час запуску: agent sandbox ON разом із приміткою, no OS-native agent sandbox on this host разом із підказкою або agent sandbox DISABLED by --sandbox off. GET /healthz не несе поля про пісочницю.
--sandbox / CC_SERVER_SANDBOX приймає on (типово) або off. Це відмова від застосування, а не ввімкнення: on означає «загортати, коли хост пропонує бекенд», а не «вимагати його».
Нативний бекенд
Розділ із назвою «Нативний бекенд»macOS: Seatbelt
Розділ із назвою «macOS: Seatbelt»Використовує механізм пісочниці Seatbelt від Apple (ту саму систему, яку застосовує macOS App Sandbox).
Згенерований профіль типово дозвільний ((allow default)) і вирізає заборони, бо цілком заборонний за замовчуванням профіль робить інтерактивний шел непридатним — викликів dyld, XPC і Mach забагато, щоб їх перелічити. Практичний наслідок: агент усе ще може читати більшість хоста; ваші зареєстровані робочі копії захищені явними заборонами запису й перейменування, а не невидимістю.
- Читання файлової системи: заборонено для шляхів із секретами (
~/.ssh,~/.aws,~/.gnupg,~/.config/gh,~/Library/Keychainsі решти набору заборон на читання) - Запис у файлову систему: скидається до заборони, далі явні дозволи для підшляхів, а обов’язково заборонені шляхи (файли rc шела,
.git/hooks, конфігурація Claude, захищені робочі копії) заблоковано навіть усередині кореня з правом запису.file-write-unlinkзаборонено на кожному забороненому шляху та його предках, тож перейменування не може обійти заборону запису - Процеси: заборони
process-execдля завжди небезпечних бінарників, плюс блокування виконання будь-чого з каталогу з правом запису - Мережа: обмежена портами проксі в процесі плюс DNS — loopback не дозволено цілком, і Unix-сокети не дозволені. Проксі забезпечують список дозволених доменів для кожної сесії (див. Вихідний трафік)
- Конфігурація: профілі генеруються на кожен запуск із
SandboxSpec
Вимоги:
sandbox-exec(/usr/bin/sandbox-exec), частина кожного встановлення macOS — додаткові інструменти не потрібні
Linux: bubblewrap
Розділ із назвою «Linux: bubblewrap»Використовує bubblewrap (bwrap) для створення просторів імен монтування та PID.
- Файлова система: створює простір імен монтування, у якому видно лише змонтовані шляхи
- Мережа: працює в неспільному просторі імен мережі; трафік досягає проксі хоста через Unix-сокетні мости
socat - Процеси: ізоляція простору імен PID
Вимоги:
- Встановлені
bubblewrapіsocat(sudo apt-get install bubblewrap socatу Debian/Ubuntu) - Підтримка просторів імен ядра (стандартна в сучасному Linux)
Bubblewrap може затіняти наявний шлях, але не може заборонити новий файл
.env, *.key чи *.pem усередині придатного для запису bind. Стандартна
політика диспетчеризації вимагає цих заборон за глобом імені файлу, тож нативна
диспетчеризація агентів наразі зривається із забороною за замовчуванням на
Linux/WSL2, навіть коли зонд знаходить bubblewrap. Вона не виконується з тихо
послабленою політикою. Щоб відновити нативну диспетчеризацію в Linux, потрібен
бекенд із правилами імен файлів на етапі створення. Вимкнення пісочниці — це
явна відмова від обмежень, а не рівноцінний обхідний шлях.
Бекенд «Немає»
Розділ із назвою «Бекенд «Немає»»Жодної пісочниці. Процес виконується безпосередньо на хості, з доступом хоста до файлової системи, мережі та процесів. ACP та інструмент bash harness усе одно отримують очищення середовища й політику команд; Claude Code через NoSandboxAdapter успадковує середовище хоста. Саме до цього відкочується диспетчеризація агентів на хості без доступного бекенда або з --sandbox off, і це типове значення термінала, коли клієнт не називає жодного.
Термінал на сервері
Розділ із назвою «Термінал на сервері»Термінал потрапляє в пісочницю на власних умовах, а не за рішенням зонда диспетчеризації. defaultBackend у TerminalSessionService — це none, і cc_server його не перевизначає, тож сесія термінала виконує шел хоста, якщо клієнт явно не попросить native; панель термінала застосунку для робочого столу цього не робить.
Коли запитують native, шел загортається через SandboxManager під фіксованим профілем термінала: $HOME і робочий каталог сесії доступні для запису, мережа відкрита, а ~/.ssh, ~/.aws, ~/.gnupg, ~/.config/gh і ~/Library/Keychains заборонені для читання. Токен хостингу коду лише для читання та шлюз push тут не діють — це справа диспетчеризації. Якщо загортання не підтримується, сесія зривається, а не показує бейдж нативного бекенда на PTY шела хоста.
Вихідний трафік
Розділ із назвою «Вихідний трафік»Коли пісочниця запускається, вихідний доступ до мережі забезпечують проксі в процесі, а не правила брандмауера ядра. На хості без доступного бекенда ніщо з цього не діє, і породжений процес дістається мережі так само, як це зробив би користувач сервера.
- Середовище виконання пісочниці запускає проксі HTTP/HTTPS і проксі SOCKS5 на
127.0.0.1усередині процесуcc_server, по одній парі на кожну обмежену сесію (http_proxy.dart,socks_proxy.dart). Паралельні запуски не ділять пару. - Процеси в пісочниці отримують змінні середовища проксі (
HTTP_PROXY/HTTPS_PROXY→ проксі HTTP,ALL_PROXY→ проксі SOCKS;GIT_SSH_COMMANDспрямовує git-over-SSH через проксі SOCKS). У Linux простір імен мережі неспільний, тож проксі — єдиний шлях назовні; у macOS пісочниця ділить loopback хоста й спілкується з ними напряму. - Цільовий хост кожного з’єднання зіставляється зі списком дозволених доменів сесії; усе інше відхиляється. Дві форми шаблону з рівно одним
*кожна: на початку*.example.comзбігається з будь-яким піддоменом (зокремаa.b.example.com), але не з самим доменом; у середній мітціbedrock.*.amazonaws.comзбігається рівно з однією міткою (bedrock.us-east-1.amazonaws.com, а неbedrock.evil.attacker.amazonaws.com). - Список дозволених розв’язується для кожної сесії з дбайливо підібраного базового набору (
kBaselineAllowedDomains: провайдери LLM, хостинг Git, реєстри пакетів), плюс домени GitHub (kGithubDomains), плюсSandboxSpec.egressAllowlist. Шлях диспетчеризації ніколи не передає додаткових записівegressAllowlist, тож на практиці кожен запуск отримує базовий набір плюс GitHub. - Фіксований список заборонених (
kBaselineDeniedDomains: кінцеві точки метаданих хмари, стоки телеметрії) має перевагу над усіма дозволами. networkEnabled: falseусе одно запускає проксі для сесії, але список дозволених порожній, тож кожне вихідне з’єднання відхиляється. Диспетчеризація задає це значення під час старту запуску за правилом Доступ до мережі: заборона вимикає мережу, дозволити й спочатку запитати залишають її ввімкненою.
SandboxSpec
Розділ із назвою «SandboxSpec»Специфікація, яку передають у SandboxPort.launch:
| Поле | Тип | Опис |
|---|---|---|
sessionId |
String |
Стабільний ідентифікатор сесії (зазвичай id простору) |
workspaceId |
String |
Id робочого простору-власника |
agentId |
String? |
Агент, наразі прив’язаний до пісочниці, якщо є |
bindMounts |
List<SandboxBindMount> |
Монтування хост→гість; пісочниця бачить лише перелічені тут шляхи хоста |
networkEnabled |
bool (типово true) |
Задається під час диспетчеризації за правилом вихідного мережевого трафіку (вимкнено лише тоді, коли воно розв’язується в заборону). Коли вимкнено, проксі для сесії все одно стартують, але список дозволених порожній, тож кожне вихідне з’єднання відхиляється |
egressAllowlist |
List<String> (типово []) |
Додаткові дозволені домени вихідного трафіку; шаблони підтримуються (*.example.com, а також середня форма з однією міткою). Диспетчеризація ніколи це не заповнює, тож загорнутий запуск отримує дбайливо підібраний базовий набір плюс домени GitHub |
guestWorkdir |
String? |
Типовий робочий каталог усередині пісочниці; окремі виклики exec можуть його перевизначити |
mode |
Mode (типово chat) |
Вирізає правила запису у файлову систему: chat лишає bind-монтування доступними для запису; review, plan та orchestrate — лише для читання |
protectedPaths |
List<String> (типово []) |
Шляхи хоста, які ніколи не повинні бути доступними для запису всередині пісочниці, в жодному режимі |
runnerStateDirs |
List<String> (типово []) |
Каталоги хоста, у яких раннер тримає власний стан, доступні для запису в кожному режимі (нині це керований Control Center CLAUDE_CONFIG_DIR) |
execGrantRoots |
List<String> (типово []) |
Схвалені оператором дерева каталогів, які знову відкривають блокування exec для каталогів із правом запису в macOS. Linux їх ігнорує — у bwrap немає блокування exec для $HOME, яке можна знову відкрити |
protectedPaths містить оригінальні зареєстровані робочі копії репозиторіїв, розв’язані на кожну диспетчеризацію з репозиторіїв робочого простору. Агенти працюють виключно у власних worktree з copy-on-write для кожної розмови, тож оригінали ніколи не повинні бути доступними для запису зсередини пісочниці — інакше в macOS загальний дозвіл Seatbelt на запис у $HOME лишав би їх доступними для запису через bash. Вони долучаються до набору заборон на запис для секретів у кожному режимі, включно з chat.
Кожен шлях заборони читання й заборони запису видається і в буквальному написанні, і в розв’язаному через символьні посилання. Ядро зіставляє правило заборони з розв’язаним шляхом, тож правило, написане проти шляху із символьним посиланням, ніколи не спрацьовує — а в macOS це радше звичайний, ніж екзотичний випадок, адже /tmp розв’язується в /private/tmp, а /var/folders/… — у /private/var/folders/…. Записи, що містять * або ?, вважаються глобами й лишаються без змін; шлях, який не розв’язується, зберігається як написано.
SandboxBindMount
Розділ із назвою «SandboxBindMount»| Поле | Тип | Опис |
|---|---|---|
hostPath |
String |
Абсолютний шлях на хості |
guestPath |
String |
Шлях усередині пісочниці (з нативною пісочницею дорівнює hostPath; збережено для симетрії адаптерів) |
readOnly |
bool (типово false) |
Монтувати лише для читання, коли true |
SandboxHandle
Розділ із назвою «SandboxHandle»Повертає SandboxPort.launch:
| Поле | Тип | Опис |
|---|---|---|
sessionId |
String |
Ідентифікатор сесії |
backend |
SandboxBackend |
Який бекенд виконується |
state |
SandboxState |
Стан життєвого циклу |
error |
Object? |
Встановлюється, коли state дорівнює error |
details |
Map<String, Object?> |
Внутрішній облік адаптера (робочий каталог, PID, шлях до профілю тощо) |
SandboxState
Розділ із назвою «SandboxState»| Стан | Опис |
|---|---|
created |
Специфікацію створено, але ВМ ще не запущено |
warm |
Виконується й готова приймати команди exec |
active |
Наразі виконує команду |
suspended |
Призупинено / знято контрольну точку на диск, щоб заощадити RAM |
destroyed |
Згорнуто; дескриптор більше не чинний |
error |
Запуск не вдався — див. SandboxHandle.error |
Події пісочниці
Розділ із назвою «Події пісочниці»| Тип події | Опис |
|---|---|
stdout |
Стандартний вивід із пісочниці |
stderr |
Стандартна помилка з пісочниці |
exit |
Процес пісочниці завершився (несе exitCode) |
starting |
Пісочниця запускається |
ready |
Пісочниця готова приймати виклики exec |
killed |
Процес убито хостом (OOM, тайм-аут, ручна зупинка) |
violation |
Порушено політику пісочниці (несе SandboxViolation) |
SandboxViolation
Розділ із назвою «SandboxViolation»| Поле | Тип | Опис |
|---|---|---|
action |
String |
Заборонене дієслово (наприклад, file-read*, network-outbound) |
target |
String |
Шлях або хост, що був ціллю забороненої операції |
raw |
String? |
Сирий рядок журналу, корисний для зневадження |
Дивіться також
Розділ із назвою «Дивіться також»- Пісочниця та безпека
- Політики пісочниці
- Обмеження
- CLI cc_server: прапорець
--sandbox