← Все новости

Claude Code записал пароли в файл настроек: 1 122 публичных копии на GitHubClaude Code stored passwords in a settings file: 1,122 public copies on GitHub

Apiiro нашла в публичных репозиториях 1 122 файла .claude/settings.local.json, в которых лежат пароли, токены и ключи: опция «да, больше не спрашивать» сохраняет команду целиком, вместе с секретом. Всего в них 1 379 секретов, включая 379 паролей к базам данных и 23 ключа AWS.Apiiro found 1,122 public .claude/settings.local.json files containing passwords, tokens and keys: the "yes, don't ask again" option stores the whole command, secret included. Together they hold 1,379 secrets, including 379 database passwords and 23 AWS keys.

Механика простая и потому неприятная. Перед запуском команды Claude Code спрашивает разрешение; если выбрать «да, больше не спрашивать», агент записывает правило в .claude/settings.local.json внутри проекта. Когда правило описывает не шаблон, а точную команду, в файл дословно попадает всё, что в ней было, — включая PGPASSWORD=, токен в curl -H "Authorization: Bearer …" или пароль в mysql -p.

Apiiro проверила 104 185 публичных копий файла в 103 617 репозиториях. Секрет нашёлся в 1 122 файлах — около 1,1%. Кроме 379 паролей к базам данных там 43 SSH-логина на публичные серверы, 42 токена GitHub, GitLab и npm и 23 ключа AWS. Среди владельцев — 63 организации, в основном софтверные компании; в одном случае это был административный облачный ключ самого вендора баз данных.

Почему одного .gitignore мало

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

Удаление файла не отменяет утечку: старые версии остаются в истории, а 211 форков 74 репозиториев несут те же секреты. С учётом истории, общих .claude/settings.json и логов чатов исследователи насчитали 2 539 секретов в 1 994 репозиториях.

Сканеры видят не всё

Gitleaks нашёл секреты в 564 файлах, TruffleHog — в 643, а 215 файлов не увидел ни один. Чаще всего пропускают пароли внутри команд: они не похожи на ключ по формату. При этом 1 122 файла всё ещё лежали в основной ветке, в половине случаев — минимум 217 дней.

Что делать

Сначала ротация, потом уборка: сменить пароли, токены и ключи, затем git rm --cached, .gitignore, проверка истории и форков. В командах использовать $DB_URL из хранилища секретов и подтверждать шаблоны вроде Bash(npm run:*), а не отдельные команды с секретами.

The mechanics are simple. Claude Code asks before running a command; choose “yes, don’t ask again” and the agent writes an allow rule into .claude/settings.local.json inside the project. When the rule captures an exact command rather than a pattern, everything in that command is stored verbatim — including PGPASSWORD=, a token in curl -H "Authorization: Bearer …" or a password in mysql -p.

Apiiro searched 104,185 public copies of the file across 103,617 repositories. At least one secret turned up in 1,122 files, about 1.1%. Besides 379 database passwords, they held 43 SSH logins to public servers, 42 GitHub, GitLab and npm tokens and 23 AWS keys. The owners include 63 organisations, mostly software companies; one case was a database vendor’s own admin-level cloud key.

Why .gitignore alone is not enough

When Claude Code first writes the file, it adds it to the user’s global Git excludes on that machine. That is a local setting for one person: it does not travel with the project, does not help if the file is already committed, and does not stop the agent from committing it. In 539 of 1,105 traced repositories, a commit listing Claude as co-author changed the file.

Old versions stay in history, and 211 forks of 74 repositories carry the same secrets. Counting history, shared .claude/settings.json files and saved chat logs, the researchers found 2,539 secrets across 1,994 repositories.

Scanners miss a lot

Gitleaks flagged secrets in 564 files, TruffleHog in 643, and neither flagged 215. Most misses are passwords inside commands, which do not look like keys by format. All 1,122 remained on the default branch, and in half of the repositories they had been there for at least 217 days.

What to do

Rotate first, clean second: change every password, token and key, then git rm --cached, add the path to .gitignore, and check history and forks. Use $DB_URL-style variables from a secrets manager, and approve patterns such as Bash(npm run:*) instead of individual commands containing secrets.

Источники