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

GitLab 13.8: встроенный SAST в CI - переводим клиентские пайплайны

Переводим несколько клиентских пайплайнов на встроенный SAST GitLab 13.8 - разбираем что сканируется из коробки и когда это реальная замена SonarQube.

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

GitLab 13.8 расширяет встроенный SAST/DAST в CI-пайплайнах и добавляет политики безопасности как код через Security Policies

На фоне January supply chain новостей - SolarWinds, разговоры про SBOM, общая нервозность вокруг того что и откуда ставится - несколько клиентов начали спрашивать про security scanning в пайплайнах. Не в духе «пора бы разобраться», а уже конкретнее: «можете настроить?». Совпало с тем, что GitLab 13.8 вышел в январе и привёз заметные изменения в своей встроенной безопасности. Мы как раз начали переводить пару проектов, так что есть что рассказать.

Что вышло в 13.8

GitLab развивает SAST (Static Application Security Testing) и DAST (Dynamic Application Security Testing) как встроенные фичи, не требующие внешних инструментов. В 13.8 основные изменения:

  • Расширен список анализаторов SAST. Поддерживается Semgrep как один из движков, что даёт более гибкие правила для Python, JavaScript, Go, Ruby. Плюс обновлены Bandit (Python), ESLint security rules (JS/TS), Gosec (Go), SpotBugs (Java/Scala/Groovy).
  • Security Policies как код. Политики безопасности теперь описываются в YAML и хранятся в отдельном репозитории политик. Можно централизованно управлять: какие сканеры запускать, при каких условиях блокировать MR, какие уязвимости критичны.
  • Улучшен Security Dashboard. На уровне группы можно видеть агрегированную картину по всем проектам, не заходя в каждый.
  • DAST по расписанию. Динамическое сканирование можно запускать не только на каждый пайплайн, но и по cron - удобно для staging-окружений.

Всё это доступно начиная с уровня Ultimate. SAST в базовой форме - доступен и на Free-tier, но с ограниченным набором правил.

Зачем это интересно для небольших команд

У нас несколько клиентов, которые уже используют GitLab как основной инструмент CI/CD в рамках managed-сопровождения. Отдельного SonarQube там нет ни у кого. Исторически это объяснялось просто: SonarQube требует отдельного сервера, настройки, интеграции в пайплайн, поддержки - для команды из 3-5 разработчиков это ощутимый overhead. В итоге security scanning откладывался как «займёмся потом».

GitLab SAST в этой ситуации выглядит практично: сканер запускается как job в пайплайне, результаты видны прямо в интерфейсе GitLab, никакой отдельной инфраструктуры. Вопрос только в том, насколько это полезно по качеству.

Что сканируется из коробки

Включить базовый SAST - одна строчка в .gitlab-ci.yml:

include:
  - template: Security/SAST.gitlab-ci.yml

После этого GitLab автоматически определяет языки в репозитории и запускает соответствующие анализаторы. Не нужно вручную указывать что и как сканировать.

Что реально покрывается на проектах, которые мы переводили:

Python (Django/Flask). Bandit ловит очевидные вещи: использование eval() и exec(), небезопасные десериализаторы, жёстко прописанные credentials в коде, слабые алгоритмы хэширования. Semgrep добавляет правила для SQL injection через f-строки и небезопасные конфигурации.

JavaScript/Node. ESLint security plugin - no-eval, небезопасный innerHTML, prototype pollution паттерны. Не так глубоко как специализированные инструменты, но базовые вещи ловит.

Dockerfile. Hadolint проверяет базовые образы и флаги - запуск от root, ADD вместо COPY, отсутствие pinned версий.

Secrets detection. Отдельный шаг, который ищет в коде потенциальные credentials, API-ключи, токены по регулярным выражениям. На первом прогоне у одного клиента нашёл три места с захардкоженными тестовыми паролями в конфигурационных файлах - которые «только для разработки», но лежали в репозитории.

Где встроенный SAST уступает SonarQube

Честно про ограничения. SonarQube с настроенными правилами глубже анализирует data flow - отслеживает как данные проходят через приложение от точки входа до потенциально опасной операции. GitLab SAST на базе Semgrep/Bandit работает больше pattern-matching'ом: видит подозрительный вызов, но не всегда понимает контекст.

Второе - качество правил зависит от выбранного анализатора. Для Java/Kotlin SpotBugs даёт неплохое покрытие, для PHP - анализатор слабее.

Третье - false positives. На Django-проекте средней сложности первый прогон выдал с полсотни предупреждений, из которых реально интересных оказалось около десяти. Остальное - либо шаблонные паттерны без контекста, либо тестовый код, который SAST не умеет отфильтровать без дополнительной конфигурации.

Как мы настраиваем

Базовая конфигурация, которую поставили нескольким клиентам:

include:
  - template: Security/SAST.gitlab-ci.yml
  - template: Security/Secret-Detection.gitlab-ci.yml

variables:
  SAST_EXCLUDED_PATHS: "tests/, spec/, vendor/"
  SAST_EXCLUDED_ANALYZERS: "eslint"  # если проект не JS

sast:
  stage: test

Исключение tests/ убирает большую часть false positives - тестовый код часто содержит намеренно небезопасные паттерны. После этого отношение сигнал/шум становится значительно лучше.

Где сейчас

Два проекта уже ходят с включённым SAST в каждом пайплайне - разработчики привыкают смотреть на вкладку Security в MR. Один проект ждёт - там PHP-легаси и нужно сначала понять, что анализатор выдаст, чтобы не заблокировать работу потоком ложных срабатываний.

Полноценного SonarQube встроенный SAST не заменяет - это честная позиция. Но для небольшой команды, у которой сейчас нет вообще никакого статического анализа, это реальный шаг вперёд без отдельного сервера и отдельного специалиста по ИБ. Главное - не включать и забывать: кто-то должен периодически смотреть в Security Dashboard и разбирать накопившиеся предупреждения. Иначе это просто job, который бегает и ничего не меняет.

Контакт

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

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