GitHub поделился опытом внутреннего проекта по очистке репозиториев от уязвимых секретов и рассказал, как за девять месяцев снизил количество открытых оповещений по secret scanning c 20 000+ до нуля.
Несколько лет назад команда безопасности GitHub запустила инициативу по улучшению работы с секретами и в её рамках протестировала тогда ещё разрабатываемую функцию Secret Scanning. Проверка показала более 20 000 срабатываний по более чем 15 000 репозиториев, что оказалось намного больше ожидаемого.
Детальный анализ результатов показал, что около 18 000 оповещений приходилось всего на пять репозиториев, где секреты были неактивными: тестовые данные, отключённые учётные данные и фейковые, но правдоподобные значения, используемые в тестах. Оставшиеся более 2 000 оповещений относились к потенциально действующим секретам и требовали ручной оценки рисков и планов по ревокации и замене.
Секреты обнаружили не только в исходном коде. GitHub нашёл уязвимые данные в тикетах поддержки, отчётах по программе bug bounty, заметках по инцидентам и на внутренних вики‑страницах. Для таких случаев были выработаны общие регламенты совместно с технической поддержкой, командой реагирования на инциденты и программой bug bounty, включая правила сокрытия значений секретов перед передачей задач командам.
Чтобы остановить рост долга, GitHub включил secret scanning и защиту при push‑запросах для всех предприятий и организаций, использующих GitHub Advanced Security. Настройки были зафиксированы на уровне организации, чтобы команды не могли отключать проверку локально. Push Protection блокировала загрузку новых секретов, что позволило работать с уже существующим бэклогом.
Для уменьшения шума инженеры разбили оповещения по репозиториям, типу секретов и возрасту. Для большого числа низкорисковых срабатываний были сформулированы критерии пакетного закрытия: если секрет находился в отдельном тестовом репозитории, никогда не был активным и соответствовал известному шаблону тестовых данных, его можно было пометить как решённый. Так за несколько дней закрыли около 18 000 оповещений.
Дальше команде пришлось определяться с подходами к устранению проблем. Вопросы касались, например, того, как поступать с секретами в задачах: редактировать текст и сокращать историю изменений или сохранять полную аудит‑историю. Аналогично для репозиториев: GitHub предпочёл не удалять старые репозитории, чтобы не терять данные для форензики, а вместо этого отзывал секреты и при необходимости архивировал репозитории.
Основной принцип — по возможности сначала отзывать или ротировать обнаруженный секрет. Затем оценивать, оправдана ли перепись истории Git, учитывая риски форс‑push и нарушенные pull‑requests. В ряде случаев отказывались от переписывания истории, если отозванный секрет в истории не создавал существенного остаточного риска.
Для приоритизации проблем GitHub разработал механизм проверки актуальности секретов, поскольку на момент начала проекта в secret scanning ещё не было встроенной функции валидации. Целью было минимально возможным запросом понять, работает ли credential и кому он принадлежит. Для токенов GitHub, например, использовался простой запрос к низкорисковому API‑эндпоинту вроде GET /user.
При этом учитывались ограничения по приватности: даже чтение с использованием чужого действующего токена требует согласования с юристами и командой по защите данных. В неоднозначных случаях ответы считались неокончательными, без дополнительных обращений к приватным ресурсам.
Параллельно продуктовая команда GitHub внедрила проверку актуальности секретов в саму систему secret scanning, что ускорило дальнейшую работу. Эта совместная работа обнаружила ещё одну проблему — не у всех репозиториев и секретов были понятные владельцы, что затрудняло ротацию.
Для GitHub‑токенов (например, персональных токенов доступа) в оповещениях начали показывать метаданные: кто создал токен, когда, и какие у него права. Это позволило не использовать сам токен для поиска владельца. Для остальных секретов вопрос владельца оказался сложнее и показал необходимость улучшения модели собственности на репозитории.
GitHub опирался на внутренние стандарты Engineering Fundamentals, которые требуют закрепления ответственных за сервисы и поддерживают связь между сервисами и репозиториями. Однако не все репозитории были жёстко связаны с сервисами, поэтому компания запустила отдельную инициативу по управлению владением репозиториев на основе Custom Properties и проект параллельной инвентаризации секретов в менеджере учётных данных с указанием ответственных.
Даже с валидацией и дополнительными данными многие оповещения требовали ручного решения: к чему даёт доступ конкретный секрет, был ли он уже ротирован, кто владеет системой и каков путь исправления. Для каждого отклонённого оповещения фиксировалось, по какой причине оно закрыто (например, отозван, использовался в тестах, ложное срабатывание) и добавлялся комментарий с контекстом, таким как ссылка на задачу по исправлению или согласованное исключение.
Финальный шаг касался закрепления ответственности. Работа по секретам была связана с программой Engineering Fundamentals и стала одним из показателей для команд разработки. Для них установили понятные ожидания и прозрачность статуса. В результате гигиена работы с секретами перешла в разряд общей инженерной ответственности, а не задачи только команды безопасности.
Многие из решений, которые GitHub изначально реализовал вручную, теперь доступны как готовые функции secret scanning: проверка актуальности секретов, улучшенное определение владельцев и массовая triage‑обработка. Разработчикам и компаниям предлагается включить secret scanning и Push Protection в GitHub Advanced Security и использовать эти механизмы для защиты собственных проектов.
Автором описанного подхода выступил Майкл Рекачис (Michael Recachinas), старший инженер по безопасности GitHub, отвечающий за крупные программы в сфере управления уязвимостями, инструментов безопасной разработки и автоматизации безопасности, фокусирующейся на удобстве для разработчиков.
Источник: материалы GitHub.






















