SAST и DAST в конвейере сборки: как встроить безопасность без срыва сроков релиза

изображение: recraft
Чаще всего безопасность начинает тормозить релиз не из-за самих проверок, а из-за момента, когда их запускают. Если SAST или DAST впервые появляются перед выпуском версии, серьезная находка означает возврат уже практически законченной работы в разработку.
В DevSecOps проверки идут вместе с изменением по всему SDLC. Код проверяется во время разработки, зависимости и артефакты во время сборки, работающее приложение после развертывания на тестовом стенде. Результаты этих проверок используются в том же процессе, в котором команда принимает код и готовит релиз.

Проблема начинается, когда анализаторы существуют отдельно: SAST работает в одной системе, DAST в другой, результаты получает ИБ, а разработчик узнает о найденной уязвимости через несколько дней. Формально проверки есть, но на скорость исправления это почти не влияет.
Как проверки встраиваются в SDLC
Не все проверки можно и нужно запускать одновременно. Код имеет смысл анализировать еще до сборки, артефакты — после нее, а DAST запускать уже на развернутом приложении.
При работе с merge request можно проверить новый код, секреты и изменения в зависимостях. После сборки появляются артефакты и контейнерные образы. После развертывания приложения можно запускать проверки тестового окружения. Дальше результаты учитываются при принятии изменения и подготовке релиза.
В итоге команда видит историю конкретного изменения: кто его внес, какие проверки оно прошло, что было обнаружено и на каком основании изменение допустили к выпуску. Именно отсутствие таких связей между этапами часто оказывается большей проблемой, чем отсутствие очередного сканера.
Где нужны quality gates
Если результат сканирования ни на что не влияет, проверка быстро превращается в отчет, требующий ручной обработки. Поэтому вместе с анализаторами в CI/CD нужны заранее настроенные quality gates.
Они определяют, какие проверки обязательны и при каких результатах код можно слить в защищенную ветку. Например, если в новом изменении обнаружена блокирующая уязвимость, конвейер завершается с ошибкой и merge request нельзя принять. Разработчик исправляет код, запускает проверку повторно и только после этого изменение проходит дальше.
При этом правило «блокировать любую находку» обычно приносит больше вреда, чем пользы. Реакция зависит от критичности находки и принятой политики: одна блокирует слияние, для другой достаточно создать задачу со сроком исправления, третью можно принять как исключение.
Эти правила лучше определить заранее, а не обсуждать заново перед каждым релизом. Тогда команда заранее понимает, какие находки блокируют слияние и что нужно исправить, чтобы изменение прошло дальше.
Кто должен исправлять находки
Если уязвимость появилась вместе с новым кодом, первым ее должен увидеть разработчик, который этот код написал. В этот момент он еще помнит контекст задачи и обычно может исправить проблему быстрее, чем через неделю после завершения работы.
На практике именно здесь часто возникает узкое место: AppSec делают диспетчером всех результатов сканирования. Анализаторы формируют отчеты, специалисты ИБ вручную их разбирают и только потом распределяют находки по командам. На нескольких проектах такая схема еще работает, но с ростом числа команд AppSec быстро превращается в бутылочное горлышко.
Задача AppSec здесь — настраивать политики, критерии допуска и правила исключений, а также подключаться к разбору сложных случаев. Разработчики при этом исправляют проблемы в своем коде, а платформенная команда обеспечивает работу проверок и quality gates в CI/CD.
Так обратная связь остается внутри разработки, а команда безопасности не занимается ручной маршрутизацией каждого предупреждения.
Где в этом процессе SOC
SOC тоже не должен впервые узнавать о проблемах после подготовки релиза. Его основные задачи остаются связанными с мониторингом, триажем и расследованиями, но часть нужного контекста появляется гораздо раньше.
Результаты проверок можно передавать в корпоративные системы управления уязвимостями, события CI/CD и аудита в SIEM, а информацию об исправлении сохранять вместе с конкретным изменением и версией продукта.
Это особенно полезно при расследовании. Вместо поиска информации по нескольким системам видно, когда появилось изменение, какие проверки оно проходило и что происходило с найденной уязвимостью.
Какие проверки запускать в CI/CD
Попытка запускать полный набор анализаторов после каждого коммита почти гарантированно увеличит время конвейера. Поэтому быстрые и глубокие проверки лучше разделять.
Например, быстрый анализ нового кода и поиск секретов имеет смысл запускать на merge request. Полный анализ проекта можно выполнять ночью, после значительных изменений или перед подготовкой версии. DAST логично запускать после развертывания приложения на тестовом стенде, а глубокий прогон оставлять для выделенных окружений.
Независимые проверки также стоит выполнять параллельно. Если анализ кода и автоматические тесты никак друг от друга не зависят, последовательный запуск просто добавляет ожидание разработчику.
В результате проверки остаются обязательными, но не увеличивают время конвейера без необходимости.
Что делать с накопленными уязвимостями
Старый проект после первого полного анализа может показать сотни находок. Если сразу сделать их частью блокирующего quality gate, команда просто перестанет принимать новые изменения.
Обычно разумнее сначала зафиксировать текущее состояние. Старые проблемы остаются в отдельном плане устранения, а для нового кода вводится правило не добавлять уязвимости определенных категорий.
Это позволяет начать контролировать качество новых изменений сразу, не заставляя автора небольшой доработки исправлять весь технический долг проекта за предыдущие годы.
По мере разбора старых находок baseline можно ужесточать. Такой подход менее эффектно выглядит на презентации, зато реально работает в живом проекте.
Как работать с исключениями
Иногда анализатор ошибается, иногда конкретная находка неприменима, а иногда организация осознанно принимает риск. Значит, механизм исключений нужен в любом случае.
Но исключение должно оставлять след: кто его согласовал, почему, на какой срок и к какому изменению оно относится. Просто отключить проверку или добавить очередное глобальное ignore правило проще, но через некоторое время никто уже не вспомнит, зачем это было сделано.
Особенно это важно для блокирующих quality gates. Если обойти их можно только полным отключением проверки, команда рано или поздно начнет именно так и делать.
Как собрать результаты в одном процессе
SAST, DAST и SCA вполне могут выполняться разными продуктами. Проблема появляется только тогда, когда их результаты остаются в разных системах и разработчику приходится собирать картину вручную.
Результаты лучше возвращать в платформу, где команда уже работает с кодом и CI/CD. В GitFlic внешние анализаторы можно запускать из конвейера, а результаты использовать вместе с остальными проверками изменения. Успешный конвейер при этом можно сделать обязательным условием слияния в защищенную ветку.
При такой схеме смена конкретного SAST или DAST не требует перестраивать весь процесс. Для одного проекта можно использовать один набор инструментов, для другого другой, но схема работы не меняется: проверка запускается в нужной точке SDLC, разработчик получает результат, а quality gate решает, может ли изменение идти дальше.
При этом сохраняется история проверок и принятых решений, которую потом можно использовать при аудите или расследовании.
В итоге
Хороший DevSecOps-процесс должен дать разработчику результат проверки тогда, когда изменение еще находится у него в работе. Если найденная уязвимость нарушает установленный quality gate, код нельзя слить, пока проблема не исправлена или не оформлено согласованное исключение.
Зрелый процесс видно не по количеству подключенных сканеров. Важно, что происходит после их запуска: насколько быстро разработчик получает результат и может ли критичная находка реально остановить изменение.

Кирилл Довгаль, руководитель продукта GitFlic (входит в «Группу Астра»)



