Сервис развивается: тестируем формат, собираем идеи, улучшаем сервис. Есть идеи?

Написать
Войти
Дайджесты новостей
Рабочее место разработчика с терминалом, отображающим процесс выполнения bash-скрипта и визуализацию системных логов в пиксель-арт стиле

Анатомия сбоя ИИ-агента: почему Claude удалил 700 ГБ данных во время теста защитного скрипта

Инженерный постмортем потери данных разработчика при тестировании утилиты очистки каталогов с помощью ИИ-агента Claude. Детальный разбор логической коллизии в bash-скрипте, механики срабатывания EXIT trap при отказе проверок и правил построения жесткой изоляции агентов через Linux namespaces.

Анатомия сбоя ИИ-агента: почему Claude удалил 700 ГБ данных во время теста защитного скрипта

В августе 2026 года инженерное сообщество обсуждало резонансный инцидент с потерей данных разработчика Себастьяна Гиймо. При попытке автоматизировать очистку временных директорий /tmp, засоряемых автономными ИИ-агентами, кодинг-ассистент Claude сгенерировал защитный bash-скрипт. Его запуск привел к внезапному удалению около 700 ГБ файлов из домашней директории пользователя ($HOME). Процесс прервали до полного разрушения системы, восстановив часть проектов из Git, Nix и логов сессий. Инцидент стал наглядным примером того, как сочетание классических ошибок bash и специфики систем безопасности LLM создает критические риски в среде разработки.

Хронология событий: как проверялся отказной сценарий

Автономные агенты создают множество временных файлов и кэшей, быстро переполняющих /tmp. Разработчик поручил ИИ-агенту написать утилиту безопасной очистки с механизмом самотестирования (self-test).

Скрипт должен был гарантированно отклонять попытки удаления каталогов за пределами префикса /tmp. Однако при генерации тестов агент добавил в список проверяемых «опасных путей» реальный домашний каталог пользователя $HOME.

Последовательность шагов сбоя:

  1. Генерация скрипта с самопроверкой: Агент передал путь $HOME в функцию очистки, рассчитывая, что валидатор прервет выполнение с ошибкой.
  2. Некорректный порядок операций: В коде переменная удаляемого каталога инициализировалась до завершения проверки пути по регулярному выражению.
  3. Срабатывание системной ловушки: Валидатор распознал, что $HOME не лежит в /tmp, и вызвал функцию аварийного выхода _pin_die.
  4. Катастрофический cleanup: Выход из скрипта активировал обработчик trap ... EXIT, где была зарегистрирована команда rm -rf с уже заполненной переменной пути.
  5. Экстренная остановка: Разработчик вручную прервал процесс, однако скрипт успел удалить 700 ГБ рабочих данных и локальных конфигураций.

Разбор бага в коде: почему EXIT trap сработал на уничтожение

В кодовой базе возникла коллизия между механизмом валидации и системным обработчиком завершения процесса. Реконструированный фрагмент логики демонстрирует ошибку:

# 1. Присвоение непроверенного значения переменной очистки
PIN_CANARY="$TMP_REAPER_SELFTEST_CANARY_DIR"

# 2. Проверка пути по белому списку (allowlist)
[[ "$PIN_CANARY" =~ ^/tmp/[^/]+$ ]] || _pin_die

# 3. Функция очистки и регистрация ловушки выхода
pin_cleanup() {
    rm -rf -- "$PIN_CANARY"
}
trap pin_cleanup EXIT

Анализ выполнения вскрывает цепочку проблем:

  • Загрязнение переменной: Переменная PIN_CANARY принимает входящее значение немедленно. При передаче $HOME переменная сразу связывается с домашним каталогом.
  • Отказ проверки: Проверка [[ "$PIN_CANARY" =~ ^/tmp/[^/]+$ ]] завершается ошибкой для /home/user и вызывает _pin_die.
  • Семантика GNU Bash: Функция _pin_die завершает работу шелла. По стандарту Bash ловушка trap ... EXIT срабатывает всегда при завершении процесса — как успешном, так и аварийном.
  • Инверсия защиты: Обработчик pin_cleanup выполняет rm -rf -- "$PIN_CANARY", уничтожая путь, проверка которого только что завершилась отказом.

Ветка кода, созданная для предотвращения опасных удалений, сама инициировала исполнение деструктивной команды.

Анализ барьеров защиты: матрица уязвимостей

Кажущаяся надежность опиралась на пять уровней защиты, каждый из которых содержал уязвимость:

Защитный барьерПредполагаемая рольФактическая уязвимость
Self-test suiteПроверить отклонение недопустимых путейНаправил реальное удаление на рабочий $HOME
Regex-валидаторЗаблокировать пути вне /tmpЗначение переменной сохранилось до валидации
EXIT trapГарантировать удаление мусораСработал при аварийном выходе после отказа
Подтверждение агента (UI)Запросить одобрение на командыОднократное подтверждение запустило весь сценарий
GitОбеспечить восстановлениеНе защищает untracked-файлы, ключи и настройки

Роль LLM и систем безопасности: версия о даунгрейде моделей

В обсуждениях инцидента упоминалась версия о влиянии фильтров безопасности провайдера модели (Anthropic safety harness). По оценке разработчика, при генерации кода защитная система среагировала на слова об удалении файлов и автоматически переключила сессию на более слабую модель (Opus 4.8).

Менее способная модель не удержала в контексте связи между POSIX-ловушками trap и порядком вычислений в Bash, что привело к генерации некорректного кода.

Однако с инженерной точки зрения ключевой вывод иной: сгенерированный скрипт не может служить границей безопасности (security boundary) внутри пользовательской сессии. Текстовые промпты и внутренние проверки в коде не заменяют системную изоляцию ОС.

Принципы проектирования деструктивных скриптов

Разбор инцидента позволяет сформулировать базовые правила написания сценариев с потенциально опасными операциями:

  1. Не использовать боевые пути в негативных тестах: Проверка отказа должна тестироваться на изолированных одноразовых каталогах или через dry-run с логированием намерений без вызова rm.
  2. Разделение валидации и capability: Входные аргументы канонизируются и проверяются в локальных переменных. Переменная для деструктивной команды инициализируется только после успешной валидации.
  3. Отложенная регистрация trap: Регистрировать cleanup следует строго после создания временной фикстуры и подтверждения ее принадлежности безопасному корню.
  4. Двухфазное исполнение (Plan and Apply): Скрипт формирует манифест удаляемых объектов, выводит его пользователю и запрашивает подтверждение на конкретный список путей.
  5. Проверка резервных копий: Регулярные изолированные бэкапы (снапшоты, BorgBackup, Restic) должны регулярно тестироваться на процедуру восстановления.

Практическая изоляция ИИ-агентов

Автономные ассистенты требуют среды с минимальными привилегиями. Домашняя директория ($HOME), ключи SSH/GPG, токены облаков, сокет Docker и конфигурация Kubernetes должны быть скрыты.

Инструменты изоляции на Linux:

  • Unprivileged Sandboxing через bubblewrap (bwrap): Утилита создает изолированные пространства имен (user, pid, mount namespaces) без прав root. Системные библиотеки монтируются через --ro-bind только для чтения, а запись разрешается во временный каталог проекта. Попытка обратиться к $HOME завершается ошибкой ядра.
  • Контейнеры и виртуальные машины: Запуск сессий в Docker или MicroVM с пробросом только целевого репозитория.

Чек-лист безопасности для разработчиков

  • Агент запускается от выделенного непривилегированного пользователя или в контейнере без доступа к хостовому $HOME.
  • Секреты, ключи SSH/GPG и токены облаков исключены из видимости агента.
  • Скрипты с командами rm, mkfs, dd проходят ручной аудит перед запуском.
  • Автоматические тесты разрушительных операций выполняются на tmpfs.
  • Настроено создание снапшотов и проверено восстановление из бэкапа.