Claude Code снёс прод за 9 секунд. 7 хуков на ночь
В апреле 2026 основатель PocketOS оставил Cursor с Claude Opus в режиме --dangerously-skip-permissions на ночь, чтобы агент закончил рефакторинг. Утром не было ни прод-базы, ни бэкапов. На дамп через Railway API ушло 9 секунд.
Я гоняю Claude Code в /loop на ночь регулярно. До той истории думал, что permissions.deny в settings.json хватит. Не хватит. Дальше - что я перенастроил после того кейса и после двух открытых GitHub-issues, в которых deny работает не так, как написано в документации.
За 9 секунд база ушла. Хук, который ловит DROP до выполнения
Хронология PocketOS: запрос «прибери в репо», Claude интерпретировал как «приведи окружение к канону», нашёл RAILWAY_TOKEN в .env, дёрнул railway environment delete. Девять секунд. Бэкапы тоже хранились в Railway. Восстановление - из памяти разработчика и git-истории миграций.
Аналогичная история у пользователя browningstreet на HackerNews: «попросил Клода прибраться, он снёс и прод, и dev в одной транзакции».
Защита уровня PreToolUse-хука, которая бы остановила оба кейса до выполнения. Положи в ~/.claude/hooks/block-destructive-sql.sh, дай chmod +x:
В settings.json зарегистрировать:
Хук возвращает permissionDecision: deny детерминированно. Никакой LLM-классификации. DROP TABLE, TRUNCATE, инфраструктурные «удалить окружение» обрываются до того, как Bash их выполнит.
Регистрация хука нужна на уровне пользователя (~/.claude/settings.json), а не проекта. Проектный settings.json Клод предложит подтвердить - и в --dangerously-skip-permissions он этот файл может перезаписать сам себе.
Два открытых GitHub-issue, из-за которых permissions.deny не работает
В документации Anthropic написано: «положи в permissions.deny шаблон файла - Read будет отказан». На практике Клод читает .env через grep, cat -A, head, отдаёт содержимое в transcript.
Issue #24846 (открыт 11 февраля 2026): permissions.read.deny с шаблонами **/.env* не применяется для Bash-инструмента. То есть Read("./env") действительно блокируется, но Bash("cat .env") проскакивает.
Issue #44868 (открыт 7 апреля 2026): даже после явного запрета чтения .env в CLAUDE.md, Клод выполняет grep -n FOO .env и эхит результат в свой ответ. Запрет на уровне инструкции игнорируется.
Оба issue до сих пор открыты. До фикса работает только хук, который смотрит на содержимое команды независимо от имени инструмента. Промпт-фильтр в CLAUDE.md не страхует.
Хук-блокер для секретов:
Четыре слоя защиты по приоритету боли
Когда я разбирал инцидент PocketOS, понял: одного слоя нет. Нужно четыре, в правильном порядке.
Слой 1 - permissions.deny в ~/.claude/settings.json. Базовый словарь запретов, поднимаемый при каждой сессии. Включает шаблоны секретов, опасных директорий, ssh-ключей. Работает для штатных Read-операций.
Слой 2 - PreToolUse-хуки. Закрывают дыры в Слое 1 (grep .env, cat .pem, railway environment delete). Детерминированы, не зависят от LLM. Работают на любом инструменте, потому что смотрят на содержимое команды.
Слой 3 - sandbox + network allowlist. В Claude Code 2026 включается через sandbox.filesystem и sandbox.network. Anthropic Engineering пишет, что sandboxing убирает 84% запросов на permission и одновременно ограничивает blast-radius до пределов разрешённой директории.
Слой 4 - worktree-изоляция. Для долгой ночной сессии - git worktree add отдельную копию репо. Клод работает в ней, прод-ветка не пересекается. Если что-то ушло не так, worktree удаляется командой, прод не задет.
Эти четыре слоя закрывают разные классы рисков. Слой 1 ловит наивные запросы. Слой 2 перехватывает обходные манёвры через Bash. Слой 3 ограничивает сетевые удары и попытки залезть в ~/.aws. Слой 4 локализует последствия, если что-то всё-таки прошло.
Подробнее про общий блок безопасности ИИ-кодинга - как не дать ИИ-агенту взломать твоё приложение в 2026. Там разобраны supply-chain атаки и MCP-серверы как вектор.
Семь хуков, которые ловят опасное до выполнения
Я держу семь PreToolUse-хуков. Каждый - короткий bash + jq, кладётся в ~/.claude/hooks/. Регистрация - одна запись в settings.json через matcher.
Хук 1 - Block-destructive-SQL. Ловит DROP/TRUNCATE/DELETE без WHERE. Скрипт выше.
Хук 2 - Block-force-push. Force-push на main/master/prod/production отменяется. Force-push на feature-ветку проходит.
Хук 3 - Block-secret-files. Скрипт выше, перехватывает .env, .pem, ~/.ssh.
Хук 4 - Block-rm-rf-no-scope. Блокирует rm -rf ., rm -rf /, rm -rf ~, rm -rf *. Точечные rm -rf node_modules проходят.
Хук 5 - Ask-for-new-deps. Установка нового пакета через npm install <name>, pip install <name>, uv add <name> уходит в permissionDecision: ask. Чистый npm install без аргумента (восстановление по lockfile) проходит без вопросов.
Хук 6 - Audit-log. Каждая Bash/Write/Edit-команда пишется в .claude/audit.jsonl. После инцидента есть кому показать хронологию без догадок.
Хук 7 - Block-deploy-from-bypass. Если сессия запущена с --dangerously-skip-permissions, любая команда деплоя (vercel deploy, coolify, railway up --detach, flyctl deploy) отменяется. Чтобы выложить на прод, переключись в обычный режим - это секундное действие, но останавливает агента.
Эти семь хуков покрывают пять классов инцидентов: DDL-удаление, force-push, утечка секретов, файловый снос, supply-chain через свежий пакет. Шестой добавляет наблюдаемость. Седьмой страхует именно автономный режим, где --dangerously остаётся включённым дольше задачи.
Из семи готовых bash-снипетов выше скопируй три блока кода (хуки 1, 2, 4) и audit-log (хук 6). Хуки 3, 5, 7 собираются по аналогии за минуту: возьми тот же jq -n-шаблон, поменяй регекс в grep.
auto-mode даёт 17% ложных negatives. Где он не работает
Anthropic во внутреннем тестировании отчиталась: auto-mode определяет 83% опасных действий и блокирует их без человека. Остальные 17% проходят. На большой ночной сессии каждая пятая-шестая опасная команда добегает до Bash.
Лимит на сессию: auto-mode останавливается либо после 3 подряд отказов, либо после 20 общих отказов. На бэкенд-рефакторинге Клод легко набирает 20 отказов за час, после этого мод выключается, агент стоит. Так задумано: иначе он крутится в цикле «попробую ещё раз», пока не получит подтверждение.
Семь анти-паттернов, которые я перестал делать:
- Запускать /loop на ночь без worktree. Один файл .git/config в проде ломает рабочую копию у всех.
- Держать .env рядом с CLAUDE.md. Клод видит CLAUDE.md и читает соседние файлы. Сложи секреты в ~/.config/<project>/env.
- Полагаться на CLAUDE.md как на permissions. CLAUDE.md - это контекст, а не enforcement. Issue #44868 это доказал.
- Открывать --dangerously-skip-permissions для «одной задачи». Сессия живёт час-два, агент успевает зайти в чужой контекст.
- Не отключать MCP-серверы с записью на прод. Любой MCP - это новая поверхность атаки. На ночь оставляй только read-only.
- Бэкапить базу в тот же провайдер, где живёт прод. В PocketOS бэкапы хранились в Railway, удалить их получилось одной командой.
- Не вести audit.jsonl. После инцидента непонятно, что произошло. Хук 6 решает это в три строки.
Контр-интуитивный вывод: проблема не в --dangerously-skip-permissions. Проблема в том, что один слой защиты тренирует ложное ощущение безопасности. Слойная защита снимает 99% риска не потому, что каждый слой идеален, а потому что их четыре.
12 пунктов, которые я прохожу перед /loop на ночь
Это чек-лист, который я запускаю руками перед тем, как уйти спать. Каждый пункт - одна команда или одна минута проверки.
- git status чист, worktree изолирован: git worktree add ../night-session feature/refactor.
- Бэкап прод-БД сделан в другой провайдер. Не в тот же Railway/Render/Coolify.
- ~/.claude/settings.json содержит disableBypassPermissionsMode: "disable" - даже если по ошибке передам флаг, агент откажется.
- Все 7 хуков лежат в ~/.claude/hooks/, chmod +x стоит.
- audit.jsonl пуст или ротирован - после ночи легче читать хронологию.
- MCP-серверы с записью отключены: claude mcp list показывает только read-only.
- .env файлы прячусь в ~/.config/<project>/env, в проекте ссылка через dotenv-cli.
- Sandbox включён: sandbox.filesystem.allow указывает только ${CLAUDE_PROJECT_DIR}.
- Network-allowlist ограничен api.anthropic.com + github.com + npm/pypi. Никакого *.
- Прогон тестов прошёл локально без агента: npm test зелёный.
- Промпт для /loop явно сужает scope: «работай только в src/billing/, не трогай миграции, не пиши в .env».
- Telegram-уведомление о завершении настроено - утром виден итог без логина в систему.
12 пунктов занимают 8-10 минут, если делать впервые. После третьего раза уходит 2 минуты. Это дешевле, чем восстанавливать прод-базу из git-истории миграций.
Полный план автономной ночной сессии с примерами /goal-промптов разобрал отдельно - как запустить Claude Code и Codex на ночь через /goal. Там схема, при которой агент завершает 14-часовой рефакторинг без участия.
Что я бы сделал на твоём месте
- Скопируй четыре хука выше прямо сейчас. Это 15 минут. Они отрабатывают на любом проекте без правок.
- Поставь disableBypassPermissionsMode: "disable" в ~/.claude/settings.json. Это одна строка, но она снимает 80% риска необратимых ночных команд.
- Перенеси прод-бэкапы в другой провайдер. История PocketOS - про это, а не про «плохой Клод».
- Не запускай /loop без worktree. Изолированная копия репо стоит ноль и спасает рабочую ветку коллег.
ИИ не удалил твою базу. Ты удалил, потому что один слой защиты тренирует ложное ощущение безопасности. К 2027 году агентский режим станет настройкой по умолчанию, и разработчики без хуков начнут терять прод чаще, чем верстальщики ломают вёрстку при мердже. Слойная защита для ночных сессий это такая же гигиена, как git под рукой.
А что у тебя в ~/.claude/hooks/ сейчас лежит? Если ноль - какой первый хук поставишь после этой статьи?