Sandbox запускает shell-команды с ограничениями операционной системы и отвечает на вопрос, принципиально иной, чем permissions. Permission flow решает, нужно ли спросить пользователя перед запуском; sandbox решает, что процесс физически может прочитать, записать и куда подключиться. Это два независимых слоя, и путать их нельзя: можно разрешить команду без запроса и одновременно жёстко ограничить, к чему у неё есть доступ. Sandbox поддерживается на macOS, Linux и WSL2.
Конфигурация sandbox описывает три границы: файловую систему, сеть и credentials. По файловой системе задают, куда можно писать (allowWrite), что нельзя читать (denyRead) и что читать разрешено (allowRead); при включённой изоляции рабочий и временный каталог сессии доступны на запись по умолчанию, остальное выдают явно. По сети - allowlist доменов и сокетов, по credentials - файлы и переменные окружения с режимом deny или mask.
Важнейшая тонкость - у sandbox свой синтаксис путей, не совпадающий с permission rules. Здесь /tmp/build - обычный абсолютный путь, тильда - home, точка-слэш или путь без префикса - относительно корня проекта для project-настроек и относительно ~/.claude для user-настроек. Для пересекающихся read-правил выигрывает более конкретный путь: можно запретить весь home и открыть только один подкаталог. Массивы путей из разных scopes при этом объединяются.
Auto-allow связывает sandbox с разрешениями. С autoAllowBashIfSandboxed равным true команда, которую удалось запустить в sandbox, может выполниться без обычного prompt - но ограничения sandbox при этом не ослабляются, меняется лишь необходимость спрашивать. С false sandbox тот же, но shell-команды проходят обычный permission flow. Plan mode при этом имеет отдельную, более строгую логику и не должен неожиданно расширяться за счёт auto-allow.
У sandbox есть escape hatch, и его надо контролировать сознательно. Если команда несовместима с sandbox, Claude может повторить её с входом dangerouslyDisableSandbox:true - тогда она выполнится снаружи и вернётся в обычный permission flow. Полностью запретить такой retry можно ключом allowUnsandboxedCommands: false - в /sandbox это strict sandbox mode. Если escape hatch оставлен, практичный контроль - явный ask-правило на Bash(dangerouslyDisableSandbox:true), чтобы выход из песочницы всегда подтверждался.
Полезно один раз увидеть цельную конфигурацию sandbox, чтобы понимать, как складываются три границы. Ниже - пример с записью в build, запретом чтения ключей, allowlist доменов и deny на токены. К этой форме возвращаются, настраивая изоляцию: сеть открывают только тем хостам, что нужны package manager, VCS и тестам, а сокеты - особая осторожность, потому что сокет Docker daemon фактически даёт власть над host-контейнерами.
Credentials защищают двумя режимами. deny запрещает чтение файла или удаляет переменную из окружения sandboxed-команды; встроенного denylist нет - секреты перечисляют сами. mask показывает процессу sentinel вместо секрета, а прокси подставляет настоящее значение только при запросе к разрешённому хосту; для этого нужна корректная TLS-termination, и mask-полномочия принимаются лишь из user, managed или CLI, но не из checkout. Это корпоративная схема - начинают с deny, пока прокси не проверен.
Отключение файловой изоляции резко меняет модель угроз. Sandbox тогда сохраняет сетевую изоляцию, но даёт командам доступ к host-файловой системе - процесс может изменить shell startup, файлы в PATH или пользовательские настройки; project-настройки сами это выключить не могут. И главное: sandbox не доказательство безопасности - он ограничивает один класс последствий, но Claude всё ещё может прочитать враждебные инструкции в разрешённом файле или предложить вредное изменение. Нужны минимальные permissions, review и защита credentials.
{
"sandbox": {
"enabled": true,
"autoAllowBashIfSandboxed": true,
"allowUnsandboxedCommands": false, // strict: без escape hatch
"filesystem": {
"allowWrite": ["./build", "/tmp/project-build"],
"denyRead": ["~/.ssh", "~/.aws"],
"allowRead": ["."]
},
"network": { "allowedDomains": ["registry.npmjs.org", "github.com"] },
"credentials": {
"files": [{ "path": "~/.aws/credentials", "mode": "deny" }],
"envVars": [{ "name": "GITHUB_TOKEN", "mode": "deny" }]
}
}
}