SAST и SCA встраивают в GitLab CI отдельными заданиями (jobs) на этапе test: они запускаются на каждом merge request, формируют отчёт, а quality gate решает, блокировать ли слияние. Начните в режиме «только информирование», затем включайте блокировку для критичных находок. Ниже — архитектура пайплайна, пример конфигурации и типичные ошибки.
Где SAST и SCA стоят в пайплайне
Принцип «сдвиг влево» означает: проверки идут как можно раньше, а результат возвращается разработчику в том же merge request. Типичная последовательность этапов:
- build — сборка и разрешение зависимостей (для SCA важны lock-файлы или граф зависимостей);
- test — юнит-тесты и параллельно SAST и SCA;
- quality gate — проверка отчётов по заданным порогам;
- package / deploy — выполняется только если предыдущие этапы пройдены;
- DAST — на тестовом стенде после деплоя (отдельная тема, см. обзор классов инструментов).
SAST и SCA независимы, поэтому их выгодно запускать параллельно — это не увеличивает время пайплайна.
Что есть в GitLab «из коробки»
GitLab предоставляет готовые шаблоны. Для SAST достаточно подключить шаблон Jobs/SAST.gitlab-ci.yml: задания по умолчанию выполняются на этапе test, а каждый анализатор формирует JSON-отчёт как артефакт. По документации GitLab, базовое сканирование с открытыми анализаторами доступно во всех тарифах, а расширенный анализатор GitLab Advanced SAST, отчёты в merge request и управление уязвимостями — в тарифе Ultimate. Для SCA в GitLab есть dependency scanning: оно доступно в тарифе Ultimate, рекомендуемый современный подход основан на SBOM в формате CycloneDX (шаблон Jobs/Dependency-Scanning.v2.gitlab-ci.yml), а прежний анализатор на основе Gemnasium объявлен устаревшим начиная с GitLab 17.9. Если вы используете сторонние решения (например, DerScanner для SAST или Sonatype для SCA), логика интеграции та же: задание запускает сканер, а результат проверяется по порогам.
Пример .gitlab-ci.yml
Ниже — общая схема. Шаблоны GitLab подключаются строками include, а проверка порогов вынесена в отдельный этап. Адаптируйте имена, образы и команды под своё окружение и используемые инструменты.
stages:
- build
- test
- security-gate
- deploy
include:
# SAST: готовый шаблон GitLab, задания выполняются на этапе test
- template: Jobs/SAST.gitlab-ci.yml
# SCA: dependency scanning на основе SBOM (тариф Ultimate)
- template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml
inputs:
job_name: "dependency-scanning"
stage: test
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
build:
stage: build
image: node:20
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
unit-tests:
stage: test
image: node:20
script:
- npm ci
- npm test
# Quality gate: проверка отчётов по порогам
security-gate:
stage: security-gate
image: alpine:3.20
needs:
- job: dependency-scanning
artifacts: true
optional: true
before_script:
- apk add --no-cache jq
script:
- |
# Считаем критичные и высокие находки в отчёте зависимостей (если отчёт есть)
if [ -f gl-dependency-scanning-report.json ]; then
COUNT=$(jq '[.vulnerabilities[] | select(.severity=="Critical" or .severity=="High")] | length' gl-dependency-scanning-report.json)
echo "Critical/High в зависимостях: $COUNT"
if [ "$COUNT" -gt 0 ]; then
echo "Quality gate не пройден"
exit 1
fi
fi
# На первом этапе внедрения разрешите падение, чтобы только информировать
allow_failure: true
deploy:
stage: deploy
script:
- echo "Deploy"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Что важно в этом примере:
workflow:rulesзапускает пайплайн на merge request и на основной ветке. По умолчанию, как отмечает документация GitLab, SAST выполняется только в пайплайнах веток, поэтому для проверок в merge request правила нужно настроить явно.- Параметр
allow_failure: trueу quality gate — это режим «только информирование». После калибровки порогов уберите его, и pipeline начнёт блокировать слияние. - Если ваш репозиторий не хранит lock-файлы, их нужно сформировать на этапе build и передать как артефакты, иначе SCA не увидит полный граф зависимостей.
- Для Windows-раннеров и некоторых архитектур шаблоны GitLab SAST не поддерживаются: нужен Linux-раннер с Docker или Kubernetes executor.
- Команду разбора отчёта (
jq) адаптируйте под реальную структуру отчёта вашей версии GitLab или используйте встроенные политики: в тарифе Ultimate порогами можно управлять через правила одобрения merge request.
Quality gates: как задать пороги
Quality gate — это формализованное правило, при котором сборка не может перейти дальше. Рекомендуемый путь внедрения:
- Неделя-две без блокировок. Собираете статистику находок, обсуждаете с командами.
- Блокировка только новых критичных находок. Старый технический долг не должен останавливать работу; блокируем то, что добавляется в изменении.
- Расширение порога. Затем высокий уровень, затем лицензии и вредоносные пакеты.
- Исключения по процессу. Подавление находки — только с обоснованием и сроком, согласованное с AppSec.
Для SCA отдельный блок правил полезен для политики по компонентам: запрет известных вредоносных пакетов и критичных CVE с эксплойтом, ограничение лицензий. Формирование SBOM описано в статье «Что такое SBOM».
Типичные ошибки
- Сразу включить блокировку. Команды увидят сотни старых находок, пайплайн «красный» у всех, инициатива получает сопротивление. Начинайте с информирования.
- Сканировать только основную ветку. Разработчик узнаёт о проблеме после слияния. Результат нужен в merge request.
- Нет lock-файлов. SCA работает по неточным версиям или пропускает транзитивные зависимости.
- Игнорировать ложные срабатывания. Без настройки правил и процесса подавления шум убивает доверие к инструменту.
- Секреты в конфигурации. Токены сканеров храните в защищённых переменных CI или в менеджере секретов (управление секретами), а не в репозитории.
- Нет владельца. Если за разбор находок никто не отвечает, они копятся. Назначьте AppSec-ответственного и Security Champions в командах.
- Слишком долгий SAST. Полный анализ в каждом коммите замедляет разработку; используйте инкрементальные проверки в merge request и полный анализ по расписанию.
Как проверить, что всё работает
- Добавьте в тестовую ветку заведомо уязвимый пример (например, SQL-инъекцию) и убедитесь, что SAST её находит.
- Подключите зависимость со старой уязвимой версией и проверьте реакцию SCA.
- Убедитесь, что отчёты сохраняются как артефакты и доступны аудиторам.
- Следите за метриками: время прохождения пайплайна, доля блокировок, время устранения. Как обосновать развитие программы, описано в статье «Как обосновать бюджет на AppSec».
Если нужно выстроить процесс целиком — от выбора инструментов до обучения команд, — смотрите нашу услугу внедрения DevSecOps и статью «DevSecOps: с чего начать».
Как организовать работу с находками
Автоматическое сканирование даёт результат только при понятном процессе. Договоритесь о нескольких правилах: кто разбирает новые находки (разработчик автора изменения, AppSec или Security Champion); в какие сроки исправляются критичные и высокие уязвимости; как оформляются исключения и кто их утверждает; как результаты попадают в трекер задач. Результат сканирования в merge request должен быть читаемым: разработчик видит файл, строку, объяснение и рекомендацию. Чем меньше шагов между находкой и исправлением, тем выше отдача от инструмента.
Для крупных организаций с десятками проектов удобно вынести общую конфигурацию безопасности в отдельный репозиторий и подключать её через include во всех проектах. Так правила и пороги меняются в одном месте, а команды не копируют конфигурацию вручную.
Частые вопросы
Нужен ли GitLab Ultimate для SAST и SCA?
Можно ли использовать сторонние сканеры в GitLab CI?
Как не замедлить пайплайн?
Что делать с накопленными старыми уязвимостями?
Нужна помощь встроить SAST и SCA в ваши пайплайны? Эксперты AST Cyber Lab помогут выбрать инструменты, настроить quality gates и обучить команды.
Источники
- GitLab Docs: Static Application Security Testing (SAST)
- GitLab Docs: Dependency scanning
- GitLab Docs: Dependency scanning using SBOM