Эфир 18.11 · Поток 318 ноября в 19:00 МСК — бесплатный практический эфир по ИИ-агентам · Живой Поток 3 стартует 23.11Эфир 18 ноября →Поток 3 (23.11)
РелизКод / SDK · В работуGitLab Blog→ оригинал

Claude Code сохраняет токены в файл, и 1 122 репозитория выдали их публично

Когда разработчик жмёт в Claude Code «Yes, and don't ask again», агент записывает команду целиком в .claude/settings.local.json. Если в ней был токен или пароль, он оказывается в файле. Защиту от git Claude добавляет только в глобальный exclude на ноутбуке, поэтому файл спокойно коммитится. По данным Apiiro, в публичных репозиториях нашли 104 185 копий, в 1 122 из них был хотя бы один секрет.

AI-обработка оригинала GitLab Blog; редакция Hamidun News
Claude Code сохраняет токены в файл, и 1 122 репозитория выдали их публично
Источник: GitLab Blog. Коллаж: Hamidun News.
Слушать статью
Паспорт материала и цифры
ПараметрДанные
ПервоисточникGitLab Blog ↗
Главный редактор
Ключевой факт #1Добавьте .claude/settings.local.json в .gitignore каждого проекта
Ключевой факт #2Запретите имя файла push-правилом на уровне группы GitLab
Проверьте историю коммитовудалённый файл — тоже утечка

Знакомая ситуация: агент просит разрешения запустить shell-команду, вы устали подтверждать одно и то же и жмёте «Yes, and don't ask again». Claude Code запоминает выбор и записывает команду в файл .claude/settings.local.json внутри проекта. Проблема в том, что команда сохраняется буквально. Если вы дёргали API через curl с заголовком PRIVATE-TOKEN, токен окажется в этом файле в открытом виде.

Почему файл уезжает в репозиторий

Чтобы файл не попадал в git, Claude Code добавляет его в личный глобальный exclude разработчика, а не в .gitignore проекта. Эта защита живёт на одном ноутбуке и не передаётся вместе с репозиторием. Коллега, CI-окружение или второй компьютер этого исключения не знают. git add . подхватывает файл, и он уходит туда, где лежит репозиторий.

Масштаб оценила компания Apiiro в начале ноября 2026 года. В публичных репозиториях нашлось 104 185 копий файла, и в 1 122 из них был хотя бы один секрет. Ещё сотни секретов остались только в истории, в файлах, которые уже удалили. Удаление файла не отменяет утечку: токен всё равно лежит в старых коммитах.

Руководство GitLab написано для тех, кто хранит код у них, но логика переносится на любой git-хостинг. GitLab при этом заявляет, что собственные инфраструктурные секреты защищены.

Как закрыть дыру: четыре слоя

Группа настраивается один раз, дальше защита работает сама. Слои идут от простого к сложному.

1. .gitignore. Самый дешёвый вариант: строка .claude/settings.local.json в каждом репозитории. На тарифах Premium и Ultimate её можно положить в .gitignore шаблонного проекта группы, и все новые проекты унаследуют её сами.

2. Push-правило (Premium и Ultimate). В настройках группы, в разделе запрещённых имён файлов, указывается регулярное выражение (^|/)\\.claude/settings\\.local\\.json$. Любой push с таким файлом, в корне или в подпапке, на любой ветке, будет отклонён, а разработчик увидит сообщение с шаблоном.

3. Secret Push Protection (Ultimate). Этот слой смотрит не на имя файла, а на содержимое пуша. Если находится токен известного формата, пуш отклоняется. Это спасёт и тогда, когда секрет попал в файл с другим именем.

4. Политика сканирования (Ultimate). Политика на верхнем уровне группы запускает Secret Detection в каждом проекте, даже без .gitlab-ci.yml, и отдельные проекты не могут её отключить. Одно правило срабатывает на каждом пайплайне, второе по недельному расписанию. С переменной SECRET_DETECTION_HISTORIC_SCAN: 'true' расписание проверяет всю историю, а не только новые коммиты.

Подводные камни

У push-правил есть два ограничения. Во-первых, они проверяют только добавление файлов, а не изменения уже отслеживаемых, поэтому сначала нужно убрать существующие копии. Во-вторых, правило группы копируется только в проекты, созданные после его появления. Для старых проектов его нужно задать отдельно, например через API: POST /api/v4/projects/<id>/push_rule с параметром file_name_regex. Если у проекта уже есть свои правила, используйте PUT, иначе получите ошибку 422 Project push rule exists.

Как понять, есть ли у вас проблема

Сначала нужен список затронутых репозиториев. Есть три способа:

  • GitLab Duo Agentic Chat. Вы просите чат найти все проекты группы, где когда-либо был этот файл, включая удалённые копии и другие ветки. На группу примерно из ста проектов уходит несколько минут. Зато он находит то, что поиск не видит.
  • Поиск по коду (Premium и Ultimate). Работает быстро, но видит только дефолтную ветку в её нынешнем состоянии. Синтаксис зависит от движка: для exact code search file:\\.claude/settings\\.local\\.json$ с регулярками, для advanced search filename:settings.local.json path:.claude. В API держите exclude_forks=false, иначе форки пропадут из выдачи.
  • Commits API (все тарифы). Запрос repository/commits?path=.claude/settings.local.json&all=true по каждому проекту показывает, существовал ли файл на какой-либо ветке. Пустой ответ значит, что файла не было никогда. Форки проверяются так же, как обычные проекты.

Что делать на практике

Начните с поиска по истории, а не по текущему состоянию: удалённые файлы опаснее всего, потому что про них забывают. Всё, что нашлось в файле, считайте скомпрометированным и перевыпускайте, даже если репозиторий приватный. Затем включайте защиту: хотя бы .gitignore и push-правило, а при Ultimate ещё и проверку содержимого.

Отдельная мысль для команд, которые внедряют агентов: кнопка «больше не спрашивать» превращает одноразовое разрешение в постоянную запись о командах, и секреты из этих команд попадают туда вместе с ними. Не передавайте токены агенту аргументами командной строки, используйте переменные окружения или менеджер секретов, тогда сохранённая команда будет безопасной.

Ограничение: в предоставленном тексте руководство обрывается до раздела с массовой очисткой, поэтому порядок очистки истории нужно смотреть в оригинале.

Сюжет

Вопросы и ответы по материалу

Что известно по теме: почему файл уезжает в репозиторий?

Чтобы файл не попадал в git, Claude Code добавляет его в личный глобальный exclude разработчика, а не в .gitignore проекта. Эта защита живёт на одном ноутбуке и не передаётся вместе с репозиторием. Коллега, CI-окружение или второй компьютер этого исключения не знают. git add . подхватывает файл, и он уходит туда, где лежит репозиторий. Масштаб оценила компания Apiiro в начале ноября 2026 года. В публичных репозиториях нашлось 104 185 копий файла, и в 1 122 из них был хотя бы один секрет.

Что известно по теме: как закрыть дыру: четыре слоя?

Группа настраивается один раз, дальше защита работает сама. Слои идут от простого к сложному. 1. .gitignore. Самый дешёвый вариант: строка .claude/settings.local.json в каждом репозитории. На тарифах Premium и Ultimate её можно положить в .gitignore шаблонного проекта группы, и все новые проекты унаследуют её сами. 2. Push-правило (Premium и Ultimate). В настройках группы, в разделе запрещённых имён файлов, указывается регулярное выражение (^|/)\\.claude/settings\\.local\\.json$.

Что известно по теме: подводные камни?

У push-правил есть два ограничения. Во-первых, они проверяют только добавление файлов, а не изменения уже отслеживаемых, поэтому сначала нужно убрать существующие копии. Во-вторых, правило группы копируется только в проекты, созданные после его появления. Для старых проектов его нужно задать отдельно, например через API: POST /api/v4/projects/<id>/push_rule с параметром file_name_regex. Если у проекта уже есть свои правила, используйте PUT, иначе получите ошибку 422 Project push rule exists.

ЖХ
Жемал Хамидун — CPO Alpina Digital, продакт-менеджер AlpinaGPT. Делает AI-продукты с 2019 года. Hamidun News — pet project, который вырос в production-агрегатор с 6000+ читателей.
✦ Практика · Hamidun Academy

Соберите рабочего ИИ-агента или сервис своими руками без ручного кода

В Академии Жемала Хамидуна (academy.hamidun.com) открыт бесплатный 72-часовой тест-драйв: интерактивные скетч-уроки по Claude Code и Cursor, живой Tech Radar и готовые шаблоны агентов.

Открыть 72ч бесплатный доступ →Интенсив по Вайб-кодингу
Что вы думаете?
Загружаем комментарии…