Для тех, кто использует Git в разработке в одиночку или малой командой и беспокоится «а вдруг я случайно закоммичу API-ключ?» Здесь нет механики атакующего — только механизм для остановки утечки секретов из вашего собственного репозитория.
Взгляд этого сайта: один .gitignore не защитит секреты
«Мой .env в .gitignore, так что всё нормально» — частая фраза, но она упускает ряд случаев. .gitignore лишь не даёт новым файлам отслеживаться; он не может поймать секреты, уже закоммиченные, принудительно добавленные впопыхах через git add -f или неожиданные имена вроде .env.local.bak. Он перекрывает лишь некоторые пути, которыми секрет попадает в репозиторий. Нужно что-то, что реально смотрит в содержимое коммитов и помечает «строки, похожие на секреты» — детектор. Для этого и нужен gitleaks.
Почему останавливать «до коммита»
Секреты опасны тем, что Git хранит историю вечно. Удалите из последнего файла — он остаётся в прошлых коммитах. А в момент push эта история копируется на другие машины, серверы и в логи CI.
Так что защита секретов — это на самом деле профилактика до утечки, а не восстановление после неё. Та же идея, что и инвентаризация «не оставляйте секреты в публичной директории» (→ инвентаризация веб-корня), применённая к коду.
На каких этапах обнаруживать секреты
На пути секрета от кода к миру можно поставить две проверки: в момент локального коммита и прямо перед тем, как им поделятся (CI).
секрет в коде
API-ключ, ключ, токен
проверка 1: pre-commit
обнаружить и прервать локально при коммите
проверка 2: CI / cron
обнаружить после push, до merge/деплоя
публично / общий доступ
после этого считать утёкшим
Как встроить gitleaks
Сначала просканируйте существующую историю
gitleaks git (gitleaks detect в версиях до v8.19.0). Найти секреты, оставшиеся в прошлых коммитах, — первая задача. Всё найденное здесь, как ниже, считается требующим отзыва.Добавьте проверку 1 хуком pre-commit
gitleaks git --pre-commit --staged (ранее gitleaks protect --staged) на каждом коммите, чтобы прерывать на месте любой коммит, содержащий секрет. Добавьте его в фреймворк pre-commit (.pre-commit-config.yaml), чтобы та же проверка применялась у всех, локально.Добавьте проверку 2 в CI / cron
gitleaks git как задание CI — или, для самостоятельных конфигураций, как периодический скан — чтобы ловить просочившееся (тот же подход машинного мониторинга, что и аудит зависимостей).Настройте ложные срабатывания в .gitleaks.toml
.gitleaks.toml. Правильная практика — не «подавить предупреждение», а «записать, почему это безопасно»: исключение без обоснования может стать причиной следующего инцидента.При обнаружении «отзыв» идёт первым; переписывание истории — потом
Когда вы находите секрет, который был закоммичен и запушен, высший приоритет — отозвать и перевыпустить (сменить) этот ключ или токен. Стереть его из истории через git filter-repo важно, но это лишь уборка, чтобы «остановить дальнейшее распространение». Исходите из того, что секрет, достигший публичного репозитория, форка, лога CI или чужого клона, невосстановим — сначала аннулируйте его, затем чистите историю. Переверните порядок — и его используют, пока вы ещё удаляете.
Опора на .gitignore
- лишь предотвращает новое отслеживание
- секреты, уже закоммиченные, остаются незамеченными
- бессилен против
git add -fили странных имён файлов - не может проверить «я не собирался это добавлять»
gitleaks (обнаружение + практика отзыва)
- реально инспектирует рабочее дерево и содержимое истории
- останавливает двумя проверками: pre-commit и CI
- при обнаружении — процедура, доходящая до отзыва
- ложные срабатывания исключены с записанным обоснованием
Какую команду использовать (v8.19.0 и новее)
В v8.19.0 gitleaks перестроил свои команды. Старые detect и protect всё ещё запускаются, но объявлены устаревшими и больше не показываются в справке. Для новой настройки используйте эти:
| Команда | Что сканирует | Типичное применение |
|---|---|---|
gitleaks git | Историю коммитов Git | Первый скан всей истории, CI, сканы по расписанию |
gitleaks git --pre-commit --staged | Изменения, которые вы собираетесь закоммитить (staged) | Хук pre-commit (официальный хук запускает именно это) |
gitleaks dir | Папки и файлы, включая те, что не в Git | Публичные веб-папки, резервные копии, распакованные zip-релизы |
gitleaks stdin | Текст, переданный через стандартный ввод | Вывод или логи других команд |
gitleaks завершается с кодом 1, если находит хотя бы одну утечку, и с кодом 0, если не находит ничего, поэтому задания CI и cron могут падать по этому коду. Добавьте --redact, чтобы сам секрет никогда не попадал в вывод или логи.
Пример настройки: хук pre-commit и GitHub Actions
С фреймворком pre-commit положите этот файл в корень репозитория. При добавлении укажите в rev последний релиз (v8.30.1 на октябрь 2026 года).
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.30.1
hooks:
- id: gitleaksПомимо gitleaks (сборка на Go), в id можно указать gitleaks-docker (запуск в Docker) или gitleaks-system (использует gitleaks, уже установленный на машине). Затем каждый выполняет это на своей машине:
pip install pre-commit # install pre-commit itself
pre-commit install # register the hook in this repo (once per clone)
pre-commit run --all-files # check every file once, right after registering
pre-commit autoupdate # run now and then to move rev to a newer releaseДля CI на GitHub есть официальный GitHub Action. Ему нужна вся история, поэтому делайте checkout с fetch-depth: 0.
# .github/workflows/gitleaks.yml
name: gitleaks
on:
pull_request:
push:
schedule:
- cron: "0 4 * * *"
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: gitleaks/gitleaks-action@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }}Для репозиториев, принадлежащих аккаунту организации, Action нужен лицензионный ключ (GITLEAKS_LICENSE). В официальном README сказано, что ключ бесплатно выдаётся на gitleaks.io и для личных аккаунтов не нужен. На собственном Git-сервере или в CI, отличном от GitHub, то же самое делает запуск gitleaks git --redact внутри задания.
Где проверять: сравнение четырёх мест
Любая отдельная проверка оставляет пробел. Если разложить, что каждая останавливает и где пропускает, становится понятно, зачем их сочетать.
| Где | Когда останавливает | Что покрывает | Пробелы и ограничения |
|---|---|---|---|
| Хук pre-commit (локально) | До коммита | Изменения в staged | Пропускается через git commit --no-verify или SKIP=gitleaks. Клонирование репозитория не устанавливает хук |
| CI (GitHub Actions и т. п.) | До merge или деплоя | Запушенные коммиты и история | Push уже произошёл. В публичном репозитории считайте секрет утёкшим |
| Скан по расписанию (cron) | Находит позже | Вся история репозитория | Задержка до обнаружения. Ловит то, что новые правила находят в старых коммитах |
| Push protection GitHub | При push в GitHub | Типы секретов, поддерживаемые GitHub | Можно обойти, указав причину. Не работает на других Git-серверах |
Push protection для пользователей GitHub по умолчанию включена для push в публичные репозитории. Это бесплатная страховка, но она не останавливает локальные коммиты, а ключи неподдерживаемых форматов или вручную собранные строки подключения могут пройти (подробнее — почему учётные данные, раскрытые на GitHub, всё ещё действуют). gitleaks покрывает шаг до этого и всё за пределами GitHub.
Как проверить свою конфигурацию
Однократная настройка не значит, что всё работает. В своём репозитории проверьте это по порядку.
Проверьте версию gitleaks
Выполните gitleaks version. В версиях старше v8.19.0 нет gitleaks git и других новых команд, поэтому обновитесь.
Проверьте, что хук зарегистрирован
Найдите .git/hooks/pre-commit. Если git config --get core.hooksPath указывает на другую папку, смотрите там. Git не копирует хуки при клонировании, поэтому на новой машине или в свежем клоне снова выполните pre-commit install.
Один раз просканируйте всю историю
Из корня репозитория выполните gitleaks git --redact -v. Без находок код завершения — 0. Если что-то найдено, по имени файла и коммиту в выводе проверьте в консоли выпустившего сервиса, действует ли ещё этот ключ.
Просканируйте и папки вне Git
Публичная папка на сервере, резервные копии и содержимое zip-архивов, которые вы выпускаете, не видны при скане истории Git. Проверьте их командой gitleaks dir (путь к папке) --redact (→ инвентаризация публичной директории).
Проверьте, коммитился ли когда-нибудь .env
Выполните git log --all --oneline -- .env, чтобы увидеть, затрагивал ли .env какой-либо прошлый коммит. Если появится хотя бы одна строка, содержимое с того момента есть в истории.
Обработка ложных срабатываний
Тестовые ключи-заглушки и примеры в документации часто помечаются. Есть три способа их исключить; используйте самый узкий из работающих.
- Для строки: добавьте комментарий
gitleaks:allowна этой строке - Для находки: добавьте отпечаток (fingerprint) из вывода в
.gitleaksignoreв корне репозитория (в README это помечено как экспериментальная функция) - Для файла или шаблона: добавьте его в allowlist в
.gitleaks.toml
Если вы пишете собственный .gitleaks.toml, укажите useDefault = true в разделе [extend], чтобы сохранить правила по умолчанию. Конфигурация только с вашими правилами молча теряет ключи, которые поймали бы правила по умолчанию.
Если в старом репозитории много существующих находок, передайте прошлый отчёт в --baseline-path, чтобы сообщались только новые находки. Но сначала отзовите ключи из этого отчёта. Включение ключа в baseline не делает его безопасным.
Частые ошибки и как их исправить
- Считать, что файла конфигурации достаточно: хук ничего не делает, пока кто-то не выполнит
pre-commit install. Пусть это сделают все, а ту же проверку запускайте в CI как второй слой. - Привыкнуть к
--no-verify: сделайте проверку в CI обязательным условием для merge, чтобы пропущенный хук всё равно был пойман. - Выводить секреты в логи CI: добавьте
--redact. Логи CI тоже читают многие. - Сканировать в CI неглубокий клон: проверяется только последний коммит, а секреты в истории пропускаются. Задайте
fetch-depth: 0. - Остановиться на удалении из истории: собственное руководство GitHub ставит первым шагом отзыв или смену секрета. Копии в форках, клонах и кэшах удалить нельзя.
- Вносить настоящий ключ в allowlist как «ложное срабатывание»: пишите причину в комментарии и проверяйте её при ревью.
Реальный случай: ключ доступа, оставленный в открытом доступе
7 октября 2022 года Toyota Motor Corporation объявила, что часть исходного кода пользовательского сайта её сервиса подключённых автомобилей T-Connect была открыта на GitHub. Согласно объявлению компании:
- В декабре 2017 года подрядчик, разрабатывавший сайт, по ошибке загрузил часть исходного кода в аккаунт GitHub с публичными настройками
- В коде был ключ доступа к серверу данных, где хранилась информация о клиентах
- Код был сделан приватным 15 сентября 2022 года, а ключ доступа сменён 17 сентября
- Затронуто 296 019 адресов электронной почты и номеров управления клиентами. Журналы доступа не показали использования третьими лицами, но компания заявила, что не может полностью это исключить
Между загрузкой и удалением прошло около пяти лет. К тому же это произошло вне собственных репозиториев компании — в аккаунте подрядчика. Сканер на ваших репозиториях не достаёт до всех мест, куда попадает ваш код, поэтому также ограничивайте, что может каждый ключ, и меняйте ключи по графику. И даже здесь ключ сменили через два дня после того, как код убрали: нашли — замените ключ.
Приватный репозиторий тоже не безопасное место для секретов. В случае CAMPFIRE в 2026 году, по словам компании, отправной точкой стали злоупотреблённые учётные данные GitHub, а информация, видимая на GitHub, была использована для получения облачных учётных данных (→ взлом CAMPFIRE). Держите секреты вне и приватных репозиториев и сканируйте их gitleaks по расписанию.
Что делает сам этот сайт
Базовое правило этого сайта — полное недопущение секретов в Git — строки подключения и API-ключи живут только в защищённой конфигурации на сервере (env-файл с ограниченными правами), никогда в открытом виде в репозитории или в передаточных заметках (→ держать секреты вне git / самостоятельный Git против GitHub). Поверх этого мы наслаиваем детекторы в расчёте на то, что люди всегда оступятся. Проектирование гарантирует «не клади внутрь», а скан вроде gitleaks ловит «оно всё равно попало» — эти два слоя и есть защита этого сайта от утечки секретов. Принцип обращения с секретами тот же, что и в статьях .env-файлы и секреты и безопасное хранение паролей.
Читать дальше
- Настройки GitHub: Как настроить двухфакторную аутентификацию на GitHub
- Основы: .env-файлы и API-ключи: что идёт не так и как их защитить
- От учётных данных GitHub до взлома: взлом CAMPFIRE (2026)
- После утечки: 543 699 учётных данных, раскрытых на GitHub, всё ещё действуют — почему нужно отзывать, а не просто удалять
- Когда атака шла без человека: вторжение в Hugging Face и допущение, от которого защитникам пора отказаться
- Инвентаризация: не оставляете ли вы секреты в публичной директории
- Самостоятельный хостинг: держать секреты вне git / самостоятельный Git против GitHub
- Глоссарий: что такое «.env» — что происходит при утечке env-файла
- Инструмент: сканер утечки секретов (вставьте и проверьте)
Источники
- gitleaks (официальный репозиторий), README: команды (git, dir, stdin), устаревание detect/protect в v8.19.0, коды завершения,
--redact,gitleaks:allow,.gitleaksignore,--baseline-path, расширение конфигурации — github.com/gitleaks/gitleaks / официальные определения хуков — .pre-commit-hooks.yaml / Releases - gitleaks-action (официальный GitHub Action), README: пример workflow и лицензионный ключ — github.com/gitleaks/gitleaks-action
- Документация pre-commit (install, run --all-files, autoupdate, SKIP) — pre-commit.com
- Документация Git, «githooks» (хук pre-commit и --no-verify) — git-scm.com
- GitHub Docs, «About push protection» — docs.github.com / «Removing sensitive data from a repository» — docs.github.com
- Toyota Motor Corporation, уведомление о возможной утечке адресов электронной почты клиентов (7 октября 2022 г., на японском) — global.toyota