ADG Оставить заявку
Блог DevOps 5 мин чтения

GitLab 12.7: подключаем Dependency Scanning и получаем 47 предупреждений на первом прогоне

GitLab 12.7 выводит Dependency Scanning в GA. Подключаем в CI клиентского проекта - первый прогон выдаёт полсотни CVE, разбираем как с этим жить.

Контекст момента

GitLab 12.7: Dependency Scanning переходит в GA, Secret Detection получает улучшенный движок обнаружения, Merge Request Reviews стабилизируются

GitLab 12.7 вышел в конце января, и главное в нём для нас - не Merge Request Reviews, которые наконец-то стабилизировались, и не улучшения Secret Detection, хотя это тоже приятно. Главное - Dependency Scanning перешёл из экспериментального статуса в GA. Мы давно присматривались к этой фиче, и релиз стал поводом наконец подключить её на одном из клиентских проектов в managed-сопровождении.

Результат первого прогона нас немного удивил: 47 предупреждений. Не страшно само по себе, но нужно было разобраться что с этим делать.

Что такое Dependency Scanning в GitLab

Механика простая: GitLab запускает в пайплайне анализатор зависимостей проекта, который сравнивает список пакетов с базами CVE - NVD, OSS Index и другими. Результаты появляются прямо в интерфейсе Merge Request, с разбивкой по severity. Поддерживаются основные экосистемы - npm, pip, Maven, Composer, Bundler, Go modules.

Для активации достаточно добавить в .gitlab-ci.yml одну строку:

include:
  - template: Dependency-Scanning.gitlab-ci.yml

Дальше GitLab сам подтягивает нужные анализаторы в виде Docker-образов и прогоняет их на каждый MR. Artifact с отчётом в формате JSON остаётся в хранилище, а интерфейс его рендерит поверх.

Подводный камень первый: для полноценной работы нужен Ultimate-план или хотя бы Gold. На бесплатном GitLab.com шаблон подключить можно, но визуализация в MR и управление политиками ограничены. Клиентский проект на self-hosted GitLab с Ultimate - так что у нас полный вариант.

Первый прогон: 47 предупреждений

Запустили на основной ветке. Node.js-проект, примерно 180 npm-зависимостей включая transitive. Результат: 47 позиций в отчёте.

Первая реакция команды клиента была предсказуемой: «это ненормально, у нас дыры везде». Пришлось потратить время на расшифровку.

На деле картина оказалась более спокойной. Разбили по severity:

  • Critical и High - около десяти позиций. Это реальный приоритет. Большинство касались либо lodash старых версий (CVE про prototype pollution встречается в трёх-четырёх вариантах для разных версий), либо прямых зависимостей с известными RCE и path traversal.
  • Medium - основная масса. Уязвимости реальные, но либо требуют специфических условий эксплуатации, либо вектор атаки не применим к данному проекту (например, CVE про CLI-инструмент, который используется только в dev-зависимостях и никогда не попадает в продакшн-билд).
  • Low и Info - шум. Deprecated API, потенциальные проблемы конфигурации, рекомендации без реального CVE-идентификатора.

Типичная ситуация с npm-экосистемой: одна уязвимость в популярном пакете порождает волну дублирующих предупреждений, потому что десятки других пакетов зависят от него через разные цепочки. lodash - классический пример.

Как приоритизировали

Вместо того чтобы бросаться патчить всё подряд, составили рабочий список по нескольким критериям.

Первый - exploitability. CVE с публичным PoC и активной эксплуатацией в дикой природе - в самый верх, независимо от severity по CVSS. GitLab в отчёте иногда даёт ссылки на источники, но не всегда - пришлось смотреть NVD и advisories вендоров вручную.

Второй - attack surface. Зависимость используется только в build-скриптах или попадает в продакшн-бандл? Если пакет присутствует только в devDependencies и не включается в финальный артефакт - риск существенно ниже. Для Node.js это важный фильтр: часть уязвимостей в dev-инструментах реально не влияет на пользователей системы.

Третий - наличие фикса. Если исправленная версия существует и обратно совместима - патч элементарен, нет смысла откладывать. Если мажорный апгрейд с breaking changes - нужно время на тестирование, это в бэклог с оценкой трудозатрат.

Четвёртый - transitive vs direct. Уязвимость в прямой зависимости - ваша задача. Уязвимость в транзитивной зависимости - иногда закрывается апгрейдом прямой зависимости, иногда требует принудительной подстановки версии через resolutions (Yarn) или сторонние workaround-ы вроде npm-force-resolutions, иногда вовсе ждёт патча апстрима.

По этим критериям из 47 позиций в первый спринт попало восемь. Остальные - в отдельный трекер с регулярным ревью.

Secret Detection: что изменилось в 12.7

Параллельно с Dependency Scanning подключили обновлённый Secret Detection. Он теперь сканирует не только текущее состояние файлов, но и историю коммитов - по умолчанию последние 50 коммитов в MR.

Нашёл одну позицию: закомментированный API-ключ в тестовом конфиге, который попал в репозиторий три месяца назад. Ключ уже был ротирован (случайно, при другом обновлении), так что боевого влияния нет. Но факт: без автоматического скана это бы осталось висеть в истории до следующего аудита.

Ложных срабатываний было около пяти - тестовые данные в формате, похожем на токены, и захардкоженные placeholder-значения типа YOUR_API_KEY_HERE. Настройки фильтрации достаточно гибкие, через .gitleaks.toml можно исключить паттерны.

Где сейчас

Пайплайн работает на всех MR, команда клиента привыкает к тому, что блок Security появляется в каждом запросе на слияние. Первый шок от цифры «47» прошёл, когда стало понятно что это не 47 дыр в продакшне, а 47 позиций требующих оценки, из которых приоритетных меньше десяти.

Патчинг прямых зависимостей с критическими CVE займёт неделю. Транзитивные уязвимости в lodash разберём по мере апгрейда зависящих от него пакетов - там нет быстрого способа не сломав ничего.

Самое полезное, что дал первый прогон - понимание реального состояния зависимостей. До этого дерево зависимостей обновлялось по принципу «если работает - не трогай», и накопился приличный технический долг. Теперь он хотя бы виден и измерим.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.