Библиотека
Июнь 2026
Безопасность · Вайбкодинг

Открой свой GitHub прямо сейчас. Скорее всего, там лежат твои ключи

Если ты что-то вайб-кодишь — твои API-ключи, скорее всего, уже в публичном репозитории. У меня аудитор тоже нашёл ключи в открытом репо живого проекта с клиентами. Это не редкость, это норма. Ниже — как проверить за 5 минут, что делать, если уже утекло, и как закрыть дыру навсегда.

Время на проверку: ~5 минут Уровень: для тех, кто кодит с AI Все команды: рабочие
01 / Контекст

Почему это массовая проблема вайбкодинга

Происходит всё примерно так. Ты просишь AI «подключи приём платежей» — он прекрасно подключает, но ключ пишет прямо в код. Ты делаешь commit и push — и ключ улетает на GitHub. Всё работает идеально, тебя не ломают. Беда приходит позже.

🤖 Как ловят утёкшие ключи

Публичные репозитории сканируются ботами круглосуточно — они ищут именно такие ключи. Для тебя это значит: месяц всё работает, а потом приходит счёт на чудовищное количество токенов, которые потратили через твой ключ. Или списывают деньги через твой Stripe. Платишь — ты.

Скорость обнаружения
< 1 мин
боты находят ключ почти сразу после push
Главная причина
AI в коде
ключ зашит в исходник, а не в .env
Где платишь
Токены / $
счёт за LLM, списания со Stripe
Лечится
за вечер
revoke + чистка истории + .gitignore
⚖️ Честно — у меня тоже было

Я не пишу это с позиции «я-то всё делаю правильно». Мой аудитор нашёл ключи в публичном репозитории живого проекта с клиентами. Это случается у всех, кто кодит быстро. Вопрос не в том, умный ты или нет — вопрос только в том, проверил ты или ещё нет.

02 / Диагностика

Проверь прямо сейчас — есть ли твои ключи в репозитории

Три уровня проверки: от самого быстрого (поиск глазами) до автоматического сканера. Сделай хотя бы первые два.

А. Поиск по 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 — поиск секретов в истории
# Найти любое упоминание строки во ВСЕЙ истории коммитов
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

Самый надёжный способ. Эти инструменты понимают сотни форматов ключей и проходят по всей истории.

gitleaks (рекомендую начать с него)
# macOS
brew install gitleaks

# Просканировать ВСЮ историю репозитория
gitleaks detect --source . --verbose

# Проверить только незакоммиченные изменения (для хука)
gitleaks protect --staged
trufflehog — альтернатива, проверяет «живые» ключи
# Скан репозитория; --only-verified шлёт ключ в API и проверяет,
# что он реально рабочий (меньше ложных срабатываний)
trufflehog git file://. --only-verified

# Можно сканировать и удалённый репо напрямую
trufflehog github --repo=https://github.com/USER/REPO
🧠 Что считать находкой

Любой реальный ключ в коде или в истории = утечка. Даже если репо «приватный» — приватность не отменяет того, что ключ нужно ротировать: его мог видеть любой, у кого был доступ, а историю forks/CI/локальных копий ты не контролируешь.

03 / Если уже утекло

Ключ уже в репозитории — порядок действий

🚨 Правило №1: ключ в истории git = скомпрометирован навсегда

Удалить ключ из файла и сделать новый 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 по таблице выше, и только потом всё остальное.

04 / Чистка истории

Как вычистить ключ из истории git

Обычный git rm + commit не удаляет ключ из прошлых коммитов. Нужно переписать историю. Два рабочих инструмента: git filter-repo (рекомендуется официально) и BFG Repo-Cleaner (проще для разовой задачи).

Вариант A — git filter-repo (рекомендуется)
# Установка
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
Вариант B — BFG Repo-Cleaner (проще)
# Удалить конкретный файл из всей истории
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
⚠️ Чистка истории НЕ заменяет revoke

Даже после идеальной чистки считай ключ скомпрометированным: он мог попасть в forks, в кэш GitHub, в чьи-то клоны. Единственная настоящая защита — отозвать ключ. Перепись истории нужна, чтобы не «светить» секрет дальше и не палить других людей в команде.

05 / Как правильно

Настрой один раз: .env + .gitignore + переменные окружения

Базовая идея: секреты никогда не лежат в коде. Код читает их из окружения. В репозиторий уходит только пример без значений.

1. Положи ключи в .env

.env — этот файл НЕ коммитится
# .env (реальные значения, остаётся только у тебя)
STRIPE_SECRET_KEY=sk_live_51Abc...настоящий
ANTHROPIC_API_KEY=sk-ant-api03-...настоящий
DATABASE_URL=postgres://user:pass@host/db

2. Добавь .env в .gitignore ДО первого коммита

.gitignore
# Секреты и окружение
.env
.env.local
.env.*.local
*.pem
*.key
secrets/

# Частые «случайные» утечки
.aws/
*.sqlite
credentials.json
💡 Если .env уже закоммичен

Добавить в .gitignore мало — git уже отслеживает файл. Убери из индекса: git rm --cached .env, закоммить, и обязательно почисти историю (раздел 04) + отзови ключи.

3. Коммить пример без значений — .env.example

.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. Плюс — ротация и аудит доступа из коробки.

06 / Дисциплина AI

Как заставить AI / Claude Code не писать секреты в код

Корень проблемы — AI по умолчанию вставляет ключ прямо в исходник. Лечится двумя слоями: правило в памяти агента + автоматический хук, который физически не даст запушить секрет.

1. Правило в CLAUDE.md (или в системном промпте агента)

CLAUDE.md — положи в корень проекта
# Правила безопасности
- НИКОГДА не вписывай API-ключи, токены, пароли и секреты
  прямо в код. Только через переменные окружения.
- Любой секрет читать из process.env / os.environ.
- Новые переменные добавлять в .env.example БЕЗ значений.
- Убедись, что .env есть в .gitignore.
- Перед коммитом не оставлять хардкод-ключей в diff.

Claude Code и аналоги читают CLAUDE.md как постоянный контекст — это снижает частоту проблемы. Но на одно правило полагаться нельзя: нужен автоматический барьер.

2. Pre-commit хук с gitleaks — физический барьер

Хук запускается перед каждым commit и блокирует его, если находит секрет. Даже если AI зашил ключ — push не пройдёт.

.pre-commit-config.yaml (framework pre-commit)
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 хук — это «не дай совершить ошибку». Первое снижает риск, второе закрывает дыру. Нужны оба, но если выбирать одно — ставь хук.

07 / Перед пушем

Чек-лист безопасности перед каждым 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 .
✅ Минимальная гигиена за 1 вечер

Поставь gitleaks как pre-commit хук, вынеси все ключи в .env, добавь .env в .gitignore, пропиши правило в CLAUDE.md. Один раз настроил — и эта проблема у тебя больше не появляется.

Хочешь разбираться в этом дальше?

Я веду канал, где разбираю AI-инструменты, вайбкодинг и безопасность человеческим языком — без хайпа и «успешного успеха». Реальные грабли и как их обходить. Заходи, если откликнулось.

→ Читать @timur_sevos_blog
08 / Инструменты

Инструменты и источники

ИнструментДля чегоСсылка
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встроенное сканирование GitHubdocs.github.com → secret-scanning
📌 Дисклеймер

Материал образовательный. Команды актуальны на июнь 2026 — синтаксис инструментов меняется, сверяйся с официальной документацией по ссылкам выше. Перед force-push в общий репозиторий предупреди команду: вы перепишете историю.