Открой свой GitHub прямо сейчас. Скорее всего, там лежат твои ключи
Если ты что-то вайб-кодишь — твои API-ключи, скорее всего, уже в публичном репозитории. У меня аудитор тоже нашёл ключи в открытом репо живого проекта с клиентами. Это не редкость, это норма. Ниже — как проверить за 5 минут, что делать, если уже утекло, и как закрыть дыру навсегда.
Почему это массовая проблема вайбкодинга
Происходит всё примерно так. Ты просишь AI «подключи приём платежей» — он прекрасно подключает, но ключ пишет прямо в код. Ты делаешь commit и push — и ключ улетает на GitHub. Всё работает идеально, тебя не ломают. Беда приходит позже.
Публичные репозитории сканируются ботами круглосуточно — они ищут именно такие ключи. Для тебя это значит: месяц всё работает, а потом приходит счёт на чудовищное количество токенов, которые потратили через твой ключ. Или списывают деньги через твой Stripe. Платишь — ты.
Я не пишу это с позиции «я-то всё делаю правильно». Мой аудитор нашёл ключи в публичном репозитории живого проекта с клиентами. Это случается у всех, кто кодит быстро. Вопрос не в том, умный ты или нет — вопрос только в том, проверил ты или ещё нет.
Проверь прямо сейчас — есть ли твои ключи в репозитории
Три уровня проверки: от самого быстрого (поиск глазами) до автоматического сканера. Сделай хотя бы первые два.
А. Поиск по GitHub — за 60 секунд
Открой свой репозиторий на github.com, нажми / или клавишу поиска по репо и вбей характерные префиксы ключей. Ищи прямо во всех файлах:
# Префиксы реальных ключей — если найдёшь в коде, это утечка: sk- # OpenAI / многие LLM sk-ant- # Anthropic (Claude) sk_live_ # Stripe (боевой ключ платежей!) AKIA # AWS Access Key AIza # Google API ghp_ / github_pat_ # GitHub Personal Access Token postgres:// / mysql:// # строки подключения к БД с паролем
Б. Проверь историю git — ключ мог быть удалён, но остаться в коммитах
Самое коварное: ты удалил ключ из файла, но он навсегда остался в истории. Проверь локально:
# Найти любое упоминание строки во ВСЕЙ истории коммитов git log -p -S "sk-" --all # Поиск по содержимому всех файлов в истории (regex) git grep -n -e "sk-ant-" $(git rev-list --all) # Какие .env и подобные файлы вообще попадали в коммиты git log --all --oneline -- "*.env" ".env*"
В. Автоматический сканер — gitleaks или trufflehog
Самый надёжный способ. Эти инструменты понимают сотни форматов ключей и проходят по всей истории.
# macOS brew install gitleaks # Просканировать ВСЮ историю репозитория gitleaks detect --source . --verbose # Проверить только незакоммиченные изменения (для хука) gitleaks protect --staged
# Скан репозитория; --only-verified шлёт ключ в API и проверяет, # что он реально рабочий (меньше ложных срабатываний) trufflehog git file://. --only-verified # Можно сканировать и удалённый репо напрямую trufflehog github --repo=https://github.com/USER/REPO
Любой реальный ключ в коде или в истории = утечка. Даже если репо «приватный» — приватность не отменяет того, что ключ нужно ротировать: его мог видеть любой, у кого был доступ, а историю forks/CI/локальных копий ты не контролируешь.
Ключ уже в репозитории — порядок действий
Удалить ключ из файла и сделать новый commit НЕ помогает — старый ключ остаётся в предыдущих коммитах, в forks, в кэше GitHub и, возможно, уже в чьей-то базе. Поэтому порядок такой: сначала отзови ключ, потом чисти историю. Не наоборот.
Немедленно отзови (revoke) ключ
Зайди в дашборд сервиса и удали/перевыпусти ключ. Это мгновенно делает утёкший ключ бесполезным. Это главный и обязательный шаг — всё остальное вторично.
Выпусти новый ключ и положи его в .env
Новый ключ — только в переменные окружения / секрет-менеджер (раздел 05), никогда обратно в код.
Проверь логи и биллинг на чужую активность
Загляни в usage/billing сервиса: не было ли всплеска трат за период, пока ключ был открыт. Для Stripe — проверь подозрительные транзакции и refunds.
Вычисти ключ из истории git
Чтобы ключ не «светился» в репо дальше — перепиши историю (раздел 04). Это уже гигиена, а не спасение: спасает только revoke из шага 1.
| Тип ключа | Где отозвать | Чем грозит утечка |
|---|---|---|
| Stripe sk_live_ | Dashboard → Developers → API keys → Roll | списания, доступ к платежам клиентов |
| OpenAI sk- | platform.openai.com → API keys → Revoke | счёт за токены |
| Anthropic sk-ant- | console.anthropic.com → API Keys | счёт за токены |
| AWS AKIA… | IAM → Users → Security credentials → Deactivate | майнинг на твоих серверах, огромный счёт |
| GitHub PAT ghp_ | Settings → Developer settings → Tokens → Revoke | доступ к твоему коду и репо |
| DB postgres:// | смени пароль БД, закрой внешний доступ | слив/удаление данных пользователей |
ВАЖНО Сначала revoke по таблице выше, и только потом всё остальное.
Как вычистить ключ из истории git
Обычный git rm + commit не удаляет ключ из прошлых коммитов. Нужно
переписать историю. Два рабочих инструмента: git filter-repo
(рекомендуется официально) и BFG Repo-Cleaner (проще для разовой задачи).
# Установка brew install git-filter-repo # Заменить утёкшую строку во ВСЕЙ истории на ***REMOVED*** # создай файл replacements.txt со строкой: sk-ant-xxxxx==>***REMOVED*** git filter-repo --replace-text replacements.txt # Либо полностью выкинуть файл из всей истории git filter-repo --path .env --invert-paths
# Удалить конкретный файл из всей истории bfg --delete-files .env # Заменить секреты по списку (по строке на ключ в secrets.txt) bfg --replace-text secrets.txt # После BFG обязательно сжать историю git reflog expire --expire=now --all git gc --prune=now --aggressive
# После переписи нужен force-push (история изменилась) git push origin --force --all git push origin --force --tags
Даже после идеальной чистки считай ключ скомпрометированным: он мог попасть в forks, в кэш GitHub, в чьи-то клоны. Единственная настоящая защита — отозвать ключ. Перепись истории нужна, чтобы не «светить» секрет дальше и не палить других людей в команде.
Настрой один раз: .env + .gitignore + переменные окружения
Базовая идея: секреты никогда не лежат в коде. Код читает их из окружения. В репозиторий уходит только пример без значений.
1. Положи ключи в .env
# .env (реальные значения, остаётся только у тебя) STRIPE_SECRET_KEY=sk_live_51Abc...настоящий ANTHROPIC_API_KEY=sk-ant-api03-...настоящий DATABASE_URL=postgres://user:pass@host/db
2. Добавь .env в .gitignore ДО первого коммита
# Секреты и окружение .env .env.local .env.*.local *.pem *.key secrets/ # Частые «случайные» утечки .aws/ *.sqlite credentials.json
Добавить в .gitignore мало — git уже отслеживает файл. Убери из индекса:
git rm --cached .env, закоммить, и обязательно почисти историю (раздел 04) + отзови ключи.
3. Коммить пример без значений — .env.example
# .env.example — шаблон без секретов, для команды STRIPE_SECRET_KEY=# твой Stripe secret key ANTHROPIC_API_KEY=# ключ из console.anthropic.com DATABASE_URL=# postgres://user:pass@host:5432/db
4. Читай ключи из окружения, не из кода
# Python import os key = os.environ["ANTHROPIC_API_KEY"] # ✅ из окружения # Node.js const key = process.env.STRIPE_SECRET_KEY; # ✅ из окружения # ❌ НИКОГДА так: const key = "sk_live_51Abc...";
Для боевых проектов с клиентами держи секреты в менеджере, а не в файле на сервере: Doppler, HashiCorp Vault, AWS Secrets Manager, 1Password Secrets / Infisical. Плюс — ротация и аудит доступа из коробки.
Как заставить AI / Claude Code не писать секреты в код
Корень проблемы — AI по умолчанию вставляет ключ прямо в исходник. Лечится двумя слоями: правило в памяти агента + автоматический хук, который физически не даст запушить секрет.
1. Правило в CLAUDE.md (или в системном промпте агента)
# Правила безопасности
- НИКОГДА не вписывай API-ключи, токены, пароли и секреты
прямо в код. Только через переменные окружения.
- Любой секрет читать из process.env / os.environ.
- Новые переменные добавлять в .env.example БЕЗ значений.
- Убедись, что .env есть в .gitignore.
- Перед коммитом не оставлять хардкод-ключей в diff.
Claude Code и аналоги читают CLAUDE.md как постоянный контекст — это снижает частоту проблемы. Но на одно правило полагаться нельзя: нужен автоматический барьер.
2. Pre-commit хук с gitleaks — физический барьер
Хук запускается перед каждым commit и блокирует его, если находит секрет. Даже если AI зашил ключ — push не пройдёт.
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.4
hooks:
- id: gitleaks
pip install pre-commit # или: brew install pre-commit pre-commit install # активирует хук в репозитории # Прогнать по всем файлам сразу (разовая проверка) pre-commit run --all-files
Правило в CLAUDE.md — это «попроси AI быть аккуратным». Pre-commit хук — это «не дай совершить ошибку». Первое снижает риск, второе закрывает дыру. Нужны оба, но если выбирать одно — ставь хук.
Чек-лист безопасности перед каждым git push
- Глянул свой diff:
git diff --staged— нет ли строк видаsk-,sk_live_, паролей, токенов. - .env в .gitignore и реально не отслеживается:
git statusне показывает.env. - Никаких хардкод-ключей в коде — всё через
process.env/os.environ. - Прогнал сканер:
gitleaks protect --staged(или активный pre-commit хук). - Новые секреты добавлены в
.env.exampleбез значений, не в код. - Не закоммичены файлы
*.pem,*.key,credentials.json, дампы БД. - Если ставишь публичным — отдельно пробежался по истории:
gitleaks detect --source .
Поставь gitleaks как pre-commit хук, вынеси все ключи в .env,
добавь .env в .gitignore, пропиши правило
в CLAUDE.md. Один раз настроил — и эта проблема у тебя больше не появляется.
Хочешь разбираться в этом дальше?
Я веду канал, где разбираю AI-инструменты, вайбкодинг и безопасность человеческим языком — без хайпа и «успешного успеха». Реальные грабли и как их обходить. Заходи, если откликнулось.
→ Читать @timur_sevos_blogИнструменты и источники
| Инструмент | Для чего | Ссылка |
|---|---|---|
| gitleaks | скан секретов в истории + pre-commit хук | github.com/gitleaks/gitleaks |
| trufflehog | скан + проверка «живых» ключей | github.com/trufflesecurity/trufflehog |
| git-filter-repo | перепись истории, удаление секретов | github.com/newren/git-filter-repo |
| BFG Repo-Cleaner | простая чистка файлов/строк из истории | rtyley.github.io/bfg-repo-cleaner |
| pre-commit | фреймворк git-хуков | pre-commit.com |
| Doppler / Infisical | секрет-менеджеры для прода | doppler.com · infisical.com |
| GitHub Secret Scanning | встроенное сканирование GitHub | docs.github.com → secret-scanning |
Материал образовательный. Команды актуальны на июнь 2026 — синтаксис инструментов меняется, сверяйся с официальной документацией по ссылкам выше. Перед force-push в общий репозиторий предупреди команду: вы перепишете историю.