anthropic

Песочница Claude Code сама глушила запрос на подтверждение

Promtime

anthropic

Самое неприятное в этой истории то, что запроса на подтверждение не было именно из-за включённой песочницы: когда её включают, Claude Code оборачивает команды агента в Seatbelt и перестаёт спрашивать. Accomplish показала, что в такой конфигурации хватает одного короткого сообщения, чтобы команда из открытого репозитория выполнилась на хостовом Mac вне песочницы; Anthropic закрыла дыру в Claude Code 2.1.247.

Коротко

  • Accomplish включила песочницу, выставила строгий режим «не спрашивать», открыла репозиторий в Claude Code и отправила одно сообщение: команда из этого репозитория выполнилась на хостовом Mac без единого запроса.
  • Обвязка индексирует репозиторий своими git-командами вне песочницы; одна из них, git ls-files, не обнуляла core.fsmonitor, а эта настройка выполняется как shell-команда прямо из .git/config.
  • Цепочку можно запустить и через непрямую инъекцию промпта; Anthropic разобрала отчёт в тот же день, но первая правка от 6 августа 2026 закрыла не все git-вызовы, и полный фикс вышел только 26 августа.

Если вы не следили, это уже второй такой разбор от Accomplish. Раньше они описывали SharedRoot, побег из песочницы Claude Cowork: по их собственному отчёту, хватило подключить папку к свежей сессии и отправить короткое сообщение, чтобы агент добрался до файлов на хостовом Mac без запросов. Тот отчёт, по их же словам, Anthropic закрыла со статусом «Informative», а Cowork с тех пор по умолчанию исполняется в облаке.

Seatbelt оборачивает Bash, но git обвязка запускает мимо него

В документации Claude Code сказано, что песочница меняет саму модель разрешений: вместо подтверждения каждой команды вы описываете, к каким файлам и доменам можно обращаться, а границу держит операционная система для каждой Bash-команды и всех её дочерних процессов. На macOS это встроенный Seatbelt, на Linux и WSL2 нужны bubblewrap и socat. Отсюда и строгий режим «не спрашивать»: команды внутри песочницы одобряются автоматически.

Проблема в том, что сам Claude Code запускает git не через Bash-инструмент. Обвязка в фоне индексирует репозиторий своими git-вызовами, и они идут вне Seatbelt. Значит, тому, кто хочет выбраться наружу, нужны всего две вещи: положить в .git/config настройку core.fsmonitor и дождаться git-команды обвязки, которая её прочитает.

Четыре защиты, и мимо каждой нашёлся обход

git-вызовы обвязки закалены: они передают флаги, которые обнуляют core.fsmonitor и другие опасные опции, так что обвязка их не исполняет. Accomplish нашла невычищенный вызов, тот самый, который обновляет файловый индекс: git ls-files.

Папку .git тоже защищают. Файловые инструменты Claude отказываются писать внутрь неё, Seatbelt запрещает туда писать из bash, свежий клон конфиг с удалённого сервера не приносит, git никогда не копирует его специально, а переименование чужой папки в .git заблокировано. Но правило Seatbelt закрывает только .git в корне проекта; для вложенных папок такого правила в профиле нет.

Дальше проще. Скрипт установки собирает git-папку под другим именем, вписывает в её конфиг core.fsmonitor и переименовывает её в .git внутри подкаталога. Обвязка запускает git не в корне проекта, а в том каталоге, который последним использовал Bash-инструмент, поэтому скрипт просто переходит в подкаталог с отравленным .git.

Как чтение одного файла дотягивает до полезной нагрузки

core.fsmonitor придуман ради скорости. По описанию Cobalt, вместо обхода всего дерева git спрашивает у маленькой программы-помощника, какие файлы изменились, и запускает указанный в локальном конфиге исполняемый файл вслепую, потому что доверяет конфигурации репозитория. Бытовая аналогия: на двери висит записка с телефоном мастера, и git звонит по указанному номеру, не проверяя, кто его туда вписал.

Остаётся заставить обвязку выполнить нужный git-вызов. Последняя строка скрипта просит Claude прочитать отчёт о сборке в том же подкаталоге. Когда Claude читает файл, он проверяет папку на наличие навыков и подгружает найденное, а загрузка навыка автоматически дёргает обновление файлового индекса. Невычищенный git ls-files отрабатывает в подкаталоге с отравленным .git, без единого действия пользователя.

Отчёт от 13 июля 2026 года и полный фикс 26 августа

Accomplish отправила отчёт 13 июля 2026 года, Anthropic разобрала его в тот же день. 6 августа вышла первая закалка в версии 2.1.223, но она задела не все git-вызовы, и побег переехал на соседний; исследователи прислали оставшиеся. Полный фикс приехал 26 августа в 2.1.247: теперь каждая git-команда обвязки обнуляет core.fsmonitor, и конфиг репозитория ничего запустить не может.

Своё решение Accomplish строит от обратного: весь агент живёт в виртуальной машине, туда же уходят bash, git и все порождённые процессы. Настоящие учётные данные в гостевую систему не попадают, у агента только заглушки, а трафик идёт через прокси на хосте, который агент не может перенастроить. Отравленный core.fsmonitor при этом всё равно выполнится, только внутри виртуальной машины.

Accomplish упоминает и второй путь запуска цепочки, непрямую инъекцию промпта, но деталей этого сценария в разборе нет; нет и оценки, встречалась ли атака вне лаборатории. На наш взгляд, главный сюжет здесь дизайнерский: включение песочницы снимает запросы на подтверждение, поэтому любая щель в изоляции стоит дороже, чем в обычном режиме с вопросами.

Что осталось невычищенным после 2.1.247 После этой версии конфиг репозитория не должен запускать ничего через core.fsmonitor: Anthropic закрыла все вызовы, которые ей прислали. Открытым остаётся другое: разбор не говорит, добавили ли в профиль Seatbelt недостающее правило про переименование вложенной .git, так что исходный пробел в защите папок нигде не описан как закрытый. Сроков следующих проверок никто не называл, а пользователям более старых версий остаётся обновиться.

Комментарии

Пока никто не написал. Будьте первым.

Присоединяйтесь к разговору

Войдите через Google, чтобы оставить комментарий. Имя и аватар подставятся из вашего профиля Google, а комментарий появится после модерации.

Из Google мы используем только имя и аватар. Почту не сохраняем.