Забытые пароли в коде: ищем их сканером TruffleHog
Старый коммит с ключом платёжки или базы остаётся в истории, даже если файл давно удалён. Разбираю, как TruffleHog находит такие секреты, как его запустить и что делать с найденным до передачи проекта клиенту, смены подрядчика или открытия репозитория.
Где пароль лежит годами и никому не мешает
Студия сдаёт проект. Заказчик получает архив или доступ к репозиторию и через месяц нанимает другую команду. Новые люди клонируют код и видят в старом коммите файл с настройками: ключ платёжной системы, пароль от базы, токен бота, ключ от SMS-рассылки. Файл давно удалён, но в истории он остался целиком.
Так бывает чаще, чем кажется. Разработчик в спешке кладёт ключ прямо в код, потом переносит его в переменные окружения, а старый коммит живёт дальше.
Три ситуации, когда проверка обязательна:
- вы передаёте проект заказчику и хотите убедиться, что в коде нет ваших личных ключей;
- вы меняете подрядчика и не знаете, что осталось у прежней команды;
- вы собираетесь сделать репозиторий публичным или отдать его инвестору, партнёру, на аудит.
Что находит TruffleHog
Проект trufflesecurity/trufflehog описывает больше 800 типов секретов: ключи AWS, Stripe, Cloudflare, строки подключения к Postgres и многое другое. Искать он умеет не только в файлах. Источники: git-репозитории, организации на GitHub и GitLab, папки на диске, образы Docker, бакеты S3 и GCS, а ещё Postman, Jenkins, CircleCI, Elasticsearch и стандартный ввод.
Главное отличие от простого поиска по шаблону в том, что он проверяет находку. Например, найдя ключ AWS, он обращается к API Amazon методом GetCallerIdentity и смотрит, жив ли ключ. Результат получает один из трёх статусов: verified (ключ работает), unverified (похож на ключ, но не подтверждён) и unknown (проверка не прошла из-за сетевой ошибки). Начинать стоит с verified: это ключи, которыми прямо сейчас можно воспользоваться.
Лицензия AGPL-3.0. Для проверки собственного кода она не мешает. Если же вы хотите встроить TruffleHog в свой сервис, который работает для сторонних пользователей, условия AGPL нужно прочитать внимательно или показать юристу.
Как запустить
Самый простой путь, если на машине есть Docker. Из папки с проектом:
docker run --rm -it -v "$PWD:/pwd" trufflesecurity/trufflehog:latest git file:///pwd --results=verified,unknown
В PowerShell и в командной строке Windows путь к папке пишется по-своему, примеры лежат в README проекта. Без Docker есть Homebrew (brew install trufflehog), готовые бинарники на странице релизов и установочный скрипт из репозитория. Для Windows пакетного менеджера в README нет, поэтому берут Docker или бинарник.
Команды для типовых случаев:
trufflehog git file://. --results=verified,unknownпроверяет всю историю локального репозитория;trufflehog github --org=название --results=verifiedпроходит по всей организации на GitHub;trufflehog filesystem путь/к/папкесмотрит файлы, даже если это не git, например архив от прежнего подрядчика;trufflehog docker --image имя/образапроверяет собранный образ, где ключ мог остаться в слое.
Чтобы это работало постоянно, TruffleHog подключают к GitHub Actions: шаг trufflesecurity/trufflehog@main с параметром extra_args: --results=verified,unknown. Для pull request добавляют --since-commit и --branch, чтобы проверялись только новые коммиты. Флаг --fail возвращает код 183, если что-то найдено, и сборка останавливается. Есть и pre-commit-хук: проверка срабатывает до коммита, и ключ вообще не попадает в историю.
Что делать, когда ключ нашёлся
Удалить файл и сделать новый коммит мало. Старый коммит остаётся в истории, и любой, у кого есть копия репозитория, достанет ключ оттуда. Если репозиторий хоть раз был публичным, считайте ключ скомпрометированным.
Порядок такой. Сначала отозвать ключ у сервиса и выпустить новый: для платёжки, базы, бота, облака это делается в личном кабинете. Затем положить новый ключ туда, где ему место, в переменные окружения или менеджер секретов, о котором мы писали в статье про Bitwarden и Vaultwarden для команды. После этого можно чистить историю инструментом вроде git-filter-repo и переписать репозиторий. Чистка истории убирает мусор из репозитория, но защищает от злоумышленника только отозванный ключ: копия старого коммита могла уже уйти.
Если по логам видно, что ключом пользовался кто-то чужой, это уже инцидент. Что делать дальше, разобрано в статье про план реагирования на утечку данных.
Что важно учесть
Ложные срабатывания будут. Статус unverified означает только «похоже на ключ», и среди таких находок попадаются тестовые строки и примеры из документации. Если смотреть только verified, часть живых секретов можно пропустить: не для каждого типа секрета есть проверка, а при сетевой ошибке находка получает статус unknown. Поэтому для аудита берут verified и unknown вместе.
Проверка отправляет найденный ключ в API сервиса. Для своего кода это нормально, а в закрытой сети или с чужим репозиторием без разрешения владельца включать её не стоит. Флаг --no-verification отключает проверку.
Сканер видит то, что уже попало в код. Если команда продолжает класть ключи в код, TruffleHog будет находить их снова. Нужны менеджер секретов, переменные окружения и правило, что ключи в репозиторий не попадают. Не заменяет он и ротацию, и разделение доступов между людьми.
Что можно сделать уже сейчас
- Запустите сканирование главного репозитория командой выше.
- Составьте список всех ключей, которые нашлись, и отзовите живые, даже если они вам «уже не нужны». Лишний живой ключ остаётся дверью.
- Перед передачей проекта клиенту проверьте и код, и историю, и образы Docker. Результат приложите к акту: заказчик видит, что вы проверили.
- Поставьте TruffleHog в GitHub Actions или pre-commit, чтобы проверка шла сама.
Если вы заказчик и принимаете проект от студии, попросите отчёт такого сканирования как часть приёмки. Если подрядчик уходит, а доступы остаются, начните с проверки, а потом заберите то, что принадлежит вам, как в разборе про возврат домена у бывшего разработчика. Такую проверку я делаю как часть услуги по кибербезопасности, стоимость обсуждаем под ваш объём кода.
Частые вопросы
Видит ли TruffleHog секреты в удалённых файлах?
Да, если репозиторий сканируется как git, он идёт по всей истории коммитов, в том числе по файлам, которых уже нет в текущей версии. Поэтому находка в старом коммите настоящая, ключ надо отзывать.
Можно ли проверить чужой публичный репозиторий?
Технически да, можно указать адрес в команде git. Но проверять репозитории, которые вам не принадлежат, и отправлять найденные ключи в API сервиса без разрешения владельца не стоит.
Хватит ли одного сканера, чтобы не было утечек?
Нет. Он ловит ключи в коде, а базу клиентов, доступы сотрудников и бэкапы в открытых папках он не увидит. Начать проще с короткой проверки на утечки данных.
Коротко о главном
TruffleHog за вечер показывает, какие ключи и пароли остались в коде и истории проекта, и отделяет живые от мёртвых. Дальше работа обычная: отозвать, перевыпустить, убрать в менеджер секретов, подключить проверку к сборке.
Хотите передать проект клиенту, сменить подрядчика или открыть репозиторий, и нужна проверка кода на забытые пароли? Напишите мне в Telegram слово «УТЕЧКИ». Прогоню репозиторий, покажу, что нашлось, и помогу закрыть найденное.
Что я делаю для бизнеса
- Боты в Telegram, MAX, VK
- Автоматизация процессов и CRM
- Аналитика и дашборды
- Сайты и лендинги под ключ
Бесплатно: чек-лист «Готов ли ваш бизнес к 152-ФЗ»
12 пунктов, которые проверяют готовность за час: данные, согласия, уведомление в РКН, локализация, защита. Отметьте, что уже сделано, и увидите дыры, за которые сейчас штрафуют.
Готовы обсудить вашу задачу?
Бесплатная консультация — разберём, как внедрить это в вашем бизнесе под ключ. Без форм, пишите напрямую.
Разборы, кейсы и практика — без воды. Выходит регулярно, читать 3–5 минут.


