Claude Code: файл «Don't Ask Again» хранит пароли и ключи в открытом виде на GitHub

Claude Code — ИИ-ассистент для программирования от Anthropic — сохраняет команды, которые разработчик одобрил кнопкой «Yes, and don't ask again», в файл проекта .claude/settings.local.json. Если в команде был пароль или токен, он попадает туда же — открытым текстом. Компания Apiiro, занимающаяся безопасностью ПО, нашла на публичном GitHub 1 122 копии этого файла, где лежит хотя бы один секрет. Проверять, работают ли эти ключи, исследователи не стали, но одна компания, которую они уведомили, подтвердила: её ключ был действующим.

Как секрет попадает в файл проекта

По умолчанию Claude Code спрашивает разрешение перед запуском большинства shell-команд. Выбор «Yes, and don't ask again» записывает правило в .claude/settings.local.json внутри проекта, и дальше подходящие команды выполняются без вопросов. Правило покрывает только то, что предлагалось в запросе: иногда это шаблон вроде npm test *, иногда одна точная команда. Во втором случае любой пароль или токен, набранный в ней, сохраняется дословно.

В публичных файлах исследователи находили сохранённые команды вместе с секретами и воспроизвели поведение на последних моделях — Opus 5.5 и Fable 5.1.

Claude Code пытается не пускать файл в git: при первой записи в репозитории он добавляет его в глобальные исключения git пользователя, и git на этой машине игнорирует файл во всех репозиториях. Но защита живёт в настройках одного пользователя на одном компьютере и ничего не делает для файла, который уже попал в коммит. В .gitignore самого проекта Claude Code файл не добавляет, так что защита не переезжает вместе с проектом. В 539 из 1 105 отслеженных репозиториев файл менял коммит, где Claude указан соавтором, — исследователи считают, что ассистент нередко коммитит файл сам.

Что именно нашла Apiiro

Поиск по публичному GitHub дал 104 185 копий файла в 103 617 репозиториях. Примерно 1,1% из них — 1 122 копии — содержат хотя бы один секрет, всего 1 379 различных секретов. Значение считалось секретом, если совпадало с известным форматом ключа или если пароль либо токен стоял рядом с адресом публичного сервера; вердикт должен был подтвердить ещё и ИИ-ревьюер.

  • 379 паролей от баз данных; больше трети всех секретов открывают доступ к базе напрямую;
  • 43 логина SSH к публичным серверам;
  • 42 токена для GitHub, GitLab и npm;
  • 23 ключа AWS.

Среди владельцев файлов — 63 организации, в основном софтверные компании разного размера. Самые серьёзные случаи: администраторский облачный ключ самого вендора баз данных и пароль владельца базы медицинских записей.

На понедельник каждая копия с секретом всё ещё была в основной ветке своего репозитория, а в половине репозиториев файл лежал там минимум 217 дней. Удаление файла утечку не отменяет: старые версии остаются в истории git и в форках. Ещё 734 секрета в 509 репозиториях есть только в прежних версиях файла — обычно потому, что файл удалили. Форки разнесли его дальше: 211 форков 74 репозиториев несут те же секреты, что и оригиналы.

Секреты нашлись и в 298 из 76 011 копий общего .claude/settings.json — его команды коммитят намеренно, чаще всего внутри allow-правил. С учётом старых версий и сохранённых журналов чатов агента общий итог — 2 539 секретов в 1 994 репозиториях.

Из 16 кодирующих агентов, чью документацию сравнивали исследователи, Claude Code — единственный, про кого подтверждено, что он по умолчанию сохраняет полную одобренную команду в файле проекта.

Что делать разработчику

Apiiro советует такой порядок:

  1. Ищите .claude/settings.local.json и .claude/settings.json по всей организации на GitHub и проверяйте историю git каждого репозитория — даже там, где файлов уже нет.
  2. Сначала смените все пароли, токены и ключи, которые файлы когда-либо содержали, и только потом чистите.
  3. Снимите локальный файл с отслеживания: git rm --cached .claude/settings.local.json, и добавьте его в .gitignore самого репозитория.
  4. Откройте файл на своей машине, даже если он никогда не коммитился, и удалите все правила с секретами.
  5. Не держите секреты в командах — подставляйте переменные из менеджера секретов, например $DB_URL, тогда в правиле останется имя переменной.
  6. Одобряйте шаблоны вроде Bash(npm run:*), а не отдельные команды.

Копии, которые не дошли до GitHub, тоже важны: это обычный JSON в папке проекта, и он может уехать внутрь npm-пакета, Docker-образа, zip-архива или синхронизируемой папки. Вредоносное ПО уже искало секреты на машинах разработчиков: в сентябре 2025 года червь Shai-Hulud прогонял по заражённым компьютерам сканер TruffleHog, и тот пометил больше половины файлов как содержащие секреты.

Обычные сканеры секретов такие файлы часто пропускают. Исследователи прогнали gitleaks и TruffleHog по всем копиям без шага верификации: из 1 122 файлов с секретом gitleaks отметил 564, TruffleHog — 643, а 215 не нашёл ни один. Большинство промахов — пароли внутри команд: сканеры ищут известные форматы ключей, а пароль после PGPASSWORD=, sshpass -p или mysql -p выглядит как обычное слово в обычной командной строке.

Что делать безопаснику

  • Считайте папки агентов — .claude/, .cursor/, .gemini/, .specstory/ — и файлы памяти агентов хранилищами секретов наравне с .env, и на ноутбуках, и в репозиториях.
  • Добавьте их в pre-commit и CI-сканирование секретов вместе с историей git и убедитесь, что сканер ловит пароли внутри команд, а не только известные форматы ключей.
  • Внесите .claude/settings.local.json в шаблоны .gitignore организации.
  • В первую очередь проверяйте учётные данные, привязанные к публичному серверу: именно они дают доступ.

О проблеме сообщали и раньше. Баг-репорт от 11 августа 2025 года говорил, что одобренные команды с API-ключами и токенами сохраняются в settings.local.json дословно. Автоматический бот закрыл его как «not planned» 3 января, после 60 дней без активности. На сегодня все четыре связанных отчёта, на которые ссылаются исследователи, закрыты тем же ботом, последний — вчера. Ответа от Anthropic, по их словам, не получил ни один.

Для российских команд, которые используют Claude Code в разработке, практика та же: файл лежит в проекте, а не в защищённом хранилище, и при публикации репозитория уезжает наружу вместе с историей. Если доступ к Claude Code ограничен, это не отменяет проверку уже существующих репозиториев — секреты в них остаются читаемыми. Смежная проблема из того же семейства — побег ИИ-агента Claude Cowork из виртуальной машины: там речь о границах изоляции, здесь — о том, что агент складывает в проект по своей воле.

Частые вопросы

Кого это касается в первую очередь?

Тех, кто одобрял в Claude Code точные команды с паролями или токенами и чей проект попадал в публичный GitHub. Apiiro насчитала 1 122 таких файла в 103 617 репозиториях и 63 организации среди владельцев.

Файл удалён из репозитория — утечка закрыта?

Нет. Старые версии остаются в истории git и в форках; 734 секрета живут только в прежних версиях файла в 509 репозиториях, а 211 форков 74 репозиториев несут те же секреты, что оригиналы. С историей git приходится разбираться и в других случаях — например, когда path traversal в GitLab с CVSS 10 заставляет пересматривать доступ к репозиториям.

С чего начинать — с ротации или с очистки?

С ротации. Исследователи прямо советуют сначала сменить все пароли, токены и ключи, которые файл когда-либо содержал, и лишь потом чистить историю и файлы.

Как перестать коммитить файл?

Снять с отслеживания командой git rm --cached .claude/settings.local.json и добавить путь в .gitignore репозитория. Глобальные исключения git, которые Claude Code прописывает сам, действуют только на одной машине и не спасают уже сделанные коммиты.

Как одобрять команды, чтобы секреты не сохранялись?

Одобрять шаблоны вроде Bash(npm run:*), а не отдельные команды, и подставлять секреты переменными из менеджера секретов — например $DB_URL. Тогда в правиле останется имя переменной, а не значение.

Поймает ли это gitleaks или TruffleHog?

Часто нет. Из 1 122 файлов с секретом gitleaks отметил 564, TruffleHog — 643, а 215 не нашёл ни один: сканеры ищут известные форматы ключей и пропускают пароли после PGPASSWORD=, sshpass -p или mysql -p. Похожая история с инструментами, которые ищут уязвимости по формальным признакам: эксплуатация OpenSSH SSHole началась через несколько часов после раскрытия, и сигнатурные проверки тут запаздывают так же, как проверки форматов ключей.

Какие секреты утекали чаще всего?

Больше трети открывают базу данных напрямую, включая 379 паролей. Дальше идут 43 логина SSH к публичным серверам, 42 токена GitHub, GitLab и npm и 23 ключа AWS.

Это уже исправлено в Claude Code?

В статье нет сведений об исправлении. Известно, что четыре связанных баг-репорта закрыл автоматический бот, последний — 6 ноября, и ответа от Anthropic авторы отчётов не получили.

Достаточно ли проверить только репозитории на GitHub?

Нет. Файл может остаться в npm-пакете, Docker-образе, zip-архиве или синхронизируемой папке, поэтому его стоит проверить и на машинах разработчиков, даже если он никогда не коммитился.

Чем это отличается от утечки .env?

.env обычно попадает в репозиторий по недосмотру, а здесь секрет сохраняет сам инструмент — в правиле разрешения, которое выглядит как обычная настройка проекта. Поэтому такие папки, как .claude/, .cursor/, .gemini/ и .specstory/, безопасники советуют считать хранилищами секретов наравне с .env.

Источник: thehackernews.com