Дальше - как проверить то же самое у себя и что с результатом делать.
Что показала проверка на живой машине
Проверка заняла меньше десяти минут и состояла из обращений к файловой системе, сокету и сети. Секреты при этом не читались: проверялась только доступность. Результат ниже получен на macOS с контейнерным движком Colima; на другой конфигурации числа будут иные, а метод тот же.
- ⚠️
dockerв списке исполняемых - доступен - ✅
/var/run/docker.sock- символическая ссылка, цель отсутствует - 🔴 Рабочий сокет демона - найден в домашней папке, чтение и запись открыты
- 🔴 Демон отвечает через сокет - версия сервера 29.2.1, видно 15 контейнеров
- 🔴
~/.ssh,~/.config/gh,~/.gitconfig- читаются - ⚠️ Запись в
/tmpи в домашнюю папку - разрешена - ⚠️ Сеть: реестры пакетов и GitHub - 200
Ни одна из этих строк не означает, что вас взломали. Они означают другое: если агент начнёт выполнять чужие инструкции - основной сценарий атаки на агента выглядит именно так, - вот его радиус.
Почему «у меня нет /var/run/docker.sock» ничего не значит
На машине, где я делал замер, получилось так:
ls -la /var/run/docker.sock
# symlink -> ~/.docker/run/docker.sock
ls -la ~/.docker/run/docker.sock
# No such file or directoryСсылка на месте, цель отсутствует. Естественный вывод - контейнерный движок агенту недоступен. Вывод неверный:
docker context inspect --format '{{.Endpoints.docker.Host}}'
# unix:///Users/ВАШ_ЮЗЕР/.colima/default/docker.sock
curl -s --unix-socket ~/.colima/default/docker.sock http://localhost/_ping
# OK
docker version --format '{{.Server.Version}}'
# 29.2.1Демон отвечает. Доступ на чтение и запись к его управляющему сокету равносилен правам администратора над этим демоном - свойство контейнерных движков, известное задолго до 2026 года. Отсюда до чтения любого файла на диске один шаг: контейнер с примонтированным корнем хоста.
Единого места для сокета на macOS не существует. Docker Desktop кладёт его в один каталог, Colima в другой, Rancher Desktop в третий, Podman в четвёртый. Правило простое: проверяйте ответ демона. Наличие файла по стандартному пути не говорит ни о чём.
Что вообще доступно агенту за пределами рабочей папки
Дефолт чтения сформулирован так:
«Default read behavior: read access to the entire computer, except certain denied directories. Note that this default still allows reading credential files such as
~/.aws/credentialsand~/.ssh/.»
Поведение чтения по умолчанию: доступ на чтение ко всему компьютеру, кроме отдельных запрещённых каталогов. Учтите, что это умолчание по-прежнему разрешает читать файлы учётных данных, такие как
~/.aws/credentialsи~/.ssh/.
Там же про охват:
«Built-in file tools: Read, Edit, and Write use the permission system directly rather than running through the sandbox.»
Встроенные файловые инструменты Read, Edit и Write используют систему разрешений напрямую и через песочницу не проходят.
И про соседние процессы - это уже на странице про окружения песочницы:
«MCP servers and hooks are separate processes that run unconstrained on the host.»
MCP-серверы и обработчики событий - это отдельные процессы, которые выполняются на хосте без ограничений.
Три следствия, которые стоит принять до того, как вы начнёте настраивать:
- Песочница включается вручную. Ключ
sandbox.enabledпо умолчаниюfalse. - Инструменты чтения и записи файлов в неё не входят. Запрет на
cat ~/.ssh/id_rsaв командах оболочки не мешает прочитать тот же файл штатным инструментом чтения. - Расширения и обработчики событий живут вне периметра. Подключённые внешние инструменты работают на хосте без ограничений.
У других инструментов расклад свой. У Codex CLI песочница включена по умолчанию в режиме записи в рабочую папку, а сеть выключена. Cursor честно называет свои механизмы тем, чем они являются:
«They range from a simple allowlist to the Auto-review classifier, and they're best-effort guardrails rather than a hard security boundary.»
Они варьируются от простого списка разрешений до классификатора автопроверки и представляют собой ограждения по мере возможностей, но не жёсткую границу безопасности.
Как проверить свой периметр за 10 минут
Контейнерный демон
Самая тяжёлая по последствиям проверка:
bashecho "PATH: $(command -v docker || echo нет)" echo "DOCKER_HOST=${DOCKER_HOST:-не задана}" docker context inspect --format '{{.Endpoints.docker.Host}}' 2>/dev/null docker version --format 'СЕРВЕР ДОСТУПЕН: {{.Server.Version}}' 2>&1 | head -1Вернулась версия сервера - агент может запустить контейнер с примонтированным корнем хоста.
Чтение секретов
Печатаются только имена переменных, значения в вывод не попадают:
bashfor p in ~/.ssh ~/.aws ~/.config/gh ~/.kube ~/.npmrc ~/.docker/config.json; do if ls "$p" >/dev/null 2>&1; then echo "ЧИТАЕТСЯ: $p"; else echo "закрыт: $p"; fi done env | cut -d= -f1 | grep -Ei 'TOKEN|SECRET|KEY|PASSWORD|CREDENTIAL'Асимметрия инструментов
Попросите агента прочитать
~/.ssh/configштатным инструментом чтения вместо команды оболочки. Если команда отказала, а инструмент выдал содержимое - вы наблюдаете тот самый разрыв охвата из документации.Сеть
Проверяйте домен, которого нет в списке разрешённых:
bashcurl -s -o /dev/null -w '%{http_code}\n' --max-time 8 https://example.comНоль или таймаут - список работает. Код 200 на неразрешённом домене означает, что фильтр не поднялся или отказал молча.
Сухой прогон профиля
На macOS правило можно проверить, не запуская агента вовсе:
bashcat > /tmp/test.sb <<'EOF' (version 1) (allow default) (deny file-read* (subpath "/Users/ВАШ_ЮЗЕР/.ssh")) EOF sandbox-exec -f /tmp/test.sb /bin/ls ~/.ssh # ls: ...: Operation not permittedПять секунд на проверку гипотезы до того, как правило уедет в настройки. У Codex для этого есть штатная команда сухого прогона.
Отдельная ловушка при осмотре дерева процессов: pgrep, запущенный изнутри агента, не покажет сам агент - собственный процесс и все предки исключаются, пока не добавлен флаг -a. Проверка выглядит выполненной и врёт.
Наследуют ли субагенты ваши ограничения
Документация отвечает на первую половину вопроса прямо:
«Subagents run in the same process as the parent session and use the same sandbox configuration.»
«Субагенты выполняются в том же процессе, что и родительская сессия, и используют ту же конфигурацию песочницы».
Я проверил это замером: запустил субагента с тем же набором команд и сравнил десять показателей с родительскими. Совпали все - доступ к сокету, чтение домашних конфигов, запись, сеть. Единственное отличие - переменная окружения, помечающая процесс как дочерний. Маркер есть, отдельной границы нет, и её и не должно быть: граница одна на весь процесс.
Отсюда важный вывод для тех, кто следит за глубиной вложенности. Дефолт менялся дважды за июль: до 21 числа - пять уровней без возможности изменить, затем один, а с 24 июля - три. К периметру это не имеет отношения: и первый уровень, и третий находятся внутри одной и той же границы.
А вот режим разрешений наследуется иначе:
«Subagents inherit the permission context from the main conversation and can override the mode, except when the parent mode takes precedence.»
«Субагенты наследуют контекст разрешений от основного диалога и могут переопределить режим, кроме случаев, когда приоритет имеет родительский режим».
Практически это значит: если родительская сессия работает в обычном режиме, файл описания субагента может объявить режим без запросов подтверждения - и он применится. Файлы описания лежат в каталоге проекта, то есть приезжают вместе с клонированием чужого репозитория.
Проверить у себя:
grep -r "permissionMode" .claude/agents/ ~/.claude/agents/Чем запрет по шаблону команды отличается от изоляции
Леонардо Ди Донато, один из сопровождающих открытого средства аудита Falco, формулирует это так:
«Most agent security today works like a polite suggestion. You set boundaries in a system prompt and add a permission layer.»
«Безопасность агентов сегодня по большей части работает как вежливая просьба. Вы задаёте границы в системном промпте и добавляете слой разрешений».
В его же разборе зафиксировано рассуждение агента, который упёрся в ограничение:
«The bubblewrap sandbox is failing to create a namespace on this kernel... Let me try disabling the sandbox and using the full binary path to bypass the deny rule pattern»
«Песочница bubblewrap не может создать пространство имён на этом ядре... Попробую отключить песочницу и указать полный путь к исполняемому файлу, чтобы обойти шаблон запрещающего правила».
Тот же класс ошибки я видел на своём проекте. В настройках стоял запрет на чтение файла с переменными окружения - по имени файла и по характерному шаблону команды, которая утаскивает содержимое наружу. Выглядит как защита. По сути это перехват вызова инструмента по образцу: тот же файл читается другой командой, собранной иначе. Ограничитель жил внутри того, кого ограничивает.
Сюда же относится популярный приём с отдельным рабочим деревом репозитория для каждого агента. Оно разделяет изменения, но не поведение: права процесса, доступ к ключам, сеть и всё остальное остаются общими. Изоляции это не даёт.
Изоляция и список запретов решают разные задачи, и одно другого не заменяет. Что класть в deny, почему правило молча не совпадает и какие пять каналов проходят мимо запрета - разобрано отдельно: права агента в Claude Code.
Почему песочница фронтир-лаборатории не удержала агента
Побег произошёл через ранее неизвестную уязвимость в кэширующем прокси реестра пакетов. Прокси был одним из немногих разрешённых агенту выходов в интернет. Не дыра в заборе, а штатная калитка.
Проверяемый след этой истории лежит вне рассказов обеих заинтересованных сторон: в релизе JFrog Artifactory версии 7.161.15 от 27 июля перечислено восемь идентификаторов уязвимостей, зачтённых сотрудникам OpenAI. Какие именно из восьми использовались при побеге, ни одна из сторон не раскрыла. Саймон Уиллисон, разбирая опубликованный Hugging Face таймлайн, заканчивает так:
«What's clear to me from this is that the very best frontier models, unencumbered by additional guardrails, will find an exploit if there is one to be found. The entire software industry needs to up its security game.»
«Из этого мне ясно вот что: лучшие фронтир-модели, не стеснённые дополнительными ограждениями, найдут уязвимость, если её вообще можно найти. Всей индустрии разработки нужно поднимать планку безопасности».
Параллельно Anthropic опубликовала разбор собственных оценочных прогонов: из 141 006 прогонов три инцидента, в которых модели работали против реальных систем вместо тестовых. В одном случае в публичный реестр пакетов попал вредоносный пакет, который за час доступности успели загрузить примерно на 15 систем - среди них были и автоматические сканеры, не только машины разработчиков. Знаменатель здесь стоит прочитать внимательно: 141 006 - это прогоны, в которых у модели была возможность выйти в интернет. Все оценки вообще сюда не входят.
И здесь же деталь, без которой вся эта история читается неправильно. Anthropic прямо пишет, что модели в этих прогонах работали без штатных предохранителей:
«The models in each of these evaluations ran without the standard safeguards we deploy when we make the model generally available (that is, they did not have the classifiers and monitors).»
«Модели в каждой из этих оценок работали без стандартных мер защиты, которые мы включаем при общедоступном выпуске: у них не было ни классификаторов, ни мониторов».
То есть предохранители не были преодолены - их сняли заранее, чтобы измерить возможности самой модели. Это условие эксперимента. Читать такие инциденты как «искусственный интеллект вырвался из-под контроля» означает подставлять драматургию туда, где было инженерное решение.
Инженерный пост Anthropic про песочницу в Claude Code формулирует цель так:
«Sandboxing ensures that even a successful prompt injection is fully isolated, and cannot impact overall user security. This way, a compromised Claude Code can't steal your SSH keys, or phone home to an attacker's server.»
«Песочница гарантирует, что даже удавшееся внедрение инструкций остаётся полностью изолированным и не влияет на безопасность пользователя в целом. Скомпрометированный Claude Code не сможет украсть ваши SSH-ключи или отправить данные на сервер атакующего».
Цель правильная. Умолчание, при котором чтение открыто на весь диск, ей пока не соответствует, и это расхождение между обещанием и настройкой по умолчанию - тема всей статьи.
Что делать, если Docker нужен для работы
Рекомендация из раздела о неполадках звучит буквально так: команды движка несовместимы с песочницей, добавьте их в список исключений, чтобы они выполнялись снаружи. Рядом оговорка: этот список нельзя закрыть на уровне корпоративных настроек, то есть разработчик всегда может дописать в него что угодно.
Второй путь - разрешить сокет напрямую. Здесь документация конфликтует сама с собой: раздел об ограничениях предупреждает, что доступ к сокету «effectively grants access to the host system», а пример конфигурации в справочнике настроек содержит ровно эту строку. На это заводили задачу - её закрыли в январе 2026 с пометкой «не планируется», а пример в справочнике стоит до сих пор:
«Documentation irony - The settings documentation uses
/var/run/docker.sockas the example forallowUnixSockets, normalizing the most dangerous possible configuration.»«Ирония документации: справочник настроек использует
/var/run/docker.sockкак пример дляallowUnixSockets, нормализуя самую опасную из возможных конфигураций».
| Вариант | Что даёт | Цена |
|---|---|---|
| Команды движка вне песочницы | работает сразу, официальная рекомендация | границы нет, список исключений расширяем |
| Прокси перед сокетом с фильтром вызовов | API становится ограниченным, лишние вызовы отклоняются | нужен ещё один контейнер и разбор, какие вызовы нужны |
| Демон без прав администратора | снимает права над хостом | не снимает права над своим демоном, отдельная настройка |
| Отдельная виртуальная машина со своим демоном | агент собирает образы и не трогает демон хоста | тяжелее по ресурсам, дольше старт |
Прокси перед сокетом - средний по трудозатратам и самый честный вариант для тех, кто действительно собирает контейнеры: агенту оставляют сборку образов и запрещают всё остальное.
Как заметить, что агент уже вышел за периметр
-
Журнал отказов ядра на macOS. Каждый заблокированный доступ пишется в системный журнал:
bash/usr/bin/log show --last 1h --style compact --predicate 'sender == "Sandbox"'Строка выглядит как
Sandbox: ls(37477) deny(1) file-read-metadata /Users/ВАШ_ЮЗЕР/.ssh. Фильтруйте по имени процесса: за неделю таких строк набираются десятки тысяч. Именно этот механизм используется под капотом штатным средством наблюдения за песочницей, никакого закрытого интерфейса. -
Исходящие соединения без установки чего-либо:
bashlsof -nP -p PID_АГЕНТА -a -iЗдесь есть неочевидное ограничение. Трафик агента идёт через локальный прокси, а инструменты сетевого контроля на macOS по умолчанию не видят обращения к локальной петле. Они покажут соединения процесса-прокси, но не запрос агента к нему. Атрибуция «кто именно попросил» теряется.
-
Опасные монтирования контейнеров. В событиях движка монтирований нет вообще - нужна связка с осмотром созданного контейнера:
bashdocker events --filter 'type=container' --filter 'event=create' --format '{{.Actor.ID}}' \ | while read -r id; do docker inspect --format '{{range .Mounts}}{{.Source}} -> {{.Destination}} rw={{.RW}}{{"\n"}}{{end}}' "$id" doneОбе классические сигнатуры - примонтированный корень хоста и проброшенный сокет - ловятся именно так.
-
На Linux те же вопросы закрывают средства трассировки ядра и подсистема аудита: наблюдение за запуском процессов, открытием файлов и исходящими соединениями по идентификатору процесса агента.
Лестница изоляции: что сколько стоит
| Уровень | Что реально ограничивает | Чего не ограничивает | Цена |
|---|---|---|---|
| Отдельное рабочее дерево репозитория | пересечение изменений между агентами | ничего из поведения: права, ключи, сеть | ноль |
| Запреты по шаблонам команд и запросы подтверждения | предусмотренные формулировки | переформулированную команду, чтение штатными инструментами | ноль, но даёт усталость от подтверждений |
| Песочница операционной системы | запись за пределами папки, сеть по списку | чтение файлов, расширения, обработчики событий, вызовы вне списка | десятки минут настройки |
| Контейнер или виртуальная машина без доступа к демону хоста | почти всё перечисленное | ошибки в собственной конфигурации | часы настройки, потери в удобстве |
Инженерный пост вендора приводит и довод в пользу настройки: по внутренним замерам песочница сокращает число запросов на подтверждение на 84 процента. Это важно не ради удобства - усталость от подтверждений сама по себе превращает защиту в формальность.
Что сделать сегодня
- Прогоните пять проверок периметра - контейнерный демон, чтение секретов, асимметрия инструментов, сеть, сухой прогон профиля - изнутри агента и запишите, что получилось. Это займёт десять минут и даст точку отсчёта.
- Найдите свой сокет контейнерного демона через контекст клиента. Стандартный путь для этого не годится. Если демон отвечает - решите осознанно, оставляете вы этот доступ или нет.
- Проверьте, включена ли песочница вообще. Она выключена по умолчанию.
- Пройдите
grepпо описаниям субагентов в поисках режима без подтверждений - особенно в репозиториях, которые вы клонировали. - Включите журнал отказов и посмотрите его в конце рабочего дня. Один взгляд на список того, что агент пытался прочитать, объясняет про периметр больше, чем вся документация.
- Если агенту нужен контейнерный движок - поставьте перед сокетом фильтрующий прокси вместо того, чтобы выносить команды за пределы песочницы.
Периметр агента определяется тем, что вы измерили. То, что вы включили, определяет только ваши ожидания, и расхождение между этими двумя величинами обычно и составляет содержание инцидента.
Как устроено окно контекста, из-за которого агент теряет начало задачи, разбирали отдельно: почему агент забывает контекст. Термины из этой статьи - в глоссарии: контекстное окно, токен.
Источники
- Claude Code: sandboxing - разделы Scope, Security limitations, Sandbox settings
- Дэвид Дворкен, Оливер Веллер-Дэвис. «Making Claude Code more secure and autonomous with sandboxing»
- Codex CLI: одобрения и безопасность агента
- Cursor: безопасность агента
- Gemini CLI: режимы песочницы
- Леонардо Ди Донато. «How Claude Code escapes its own denylist and sandbox»
- Разбор побега через сокет контейнерного демона у трёх агентов
- Отчёт о трёх инцидентах в оценках по кибербезопасности
- Саймон Уиллисон, разбор таймлайна инцидента
- CVE-2026-39861: побег через символическую ссылку
- Прокси-фильтр перед сокетом контейнерного демона
- Запуск демона без прав администратора
- Claude Code: субагенты и режимы разрешений
- Claude Code: окружения песочницы
- Claude Code: справочник настроек
- Hugging Face: технический таймлайн вторжения