В сервисе появился фрагмент, который должен пройти CI. Какой процессный контроль качества должен автоматически обнаружить потенциальную инъекцию до интеграционных тестов?
def find_user(user_id):
sql = "SELECT * FROM users WHERE id = " + user_id
return db.execute(sql)
Нужно добавить в CI статический анализ безопасности приложения (SAST) и сделать его обязательным quality gate для соответствующих изменений. Анализатор проверяет исходный код без запуска приложения и может обнаружить формирование SQL-запроса из внешнего ввода до интеграционных тестов.
SAST не доказывает отсутствие уязвимостей. Он дополняет code review, тесты и динамический анализ, а найденные проблемы должны классифицироваться по серьёзности и иметь понятное правило блокировки сборки.
Ручная проверка кода плохо масштабируется: одинаковые опасные конструкции повторяются, а ревьюер может не заметить их в большом изменении. Поэтому в процессах качества появились автоматические проверки исходного кода, выполняемые вскоре после коммита.
Такой подход поддерживает сдвиг проверок влево: дефект или уязвимость обнаруживаются на более раннем и дешёвом этапе, когда исправление обычно не требует изменения уже развернутой системы и расследования инцидента.
В примере значение user_id напрямую объединяется со строкой SQL. Если оно поступает из внешнего запроса, злоумышленник может передать специальное значение, изменяющее смысл запроса.
Обычные модульные тесты могут проверять только корректный идентификатор и не заметить эту проблему. Интеграционные или динамические тесты обнаружат её лишь при наличии подходящего сценария, тестовых данных и настроенного окружения.
SAST строит представление исходного кода и анализирует потоки данных: от источника внешнего ввода до опасной операции, например выполнения SQL. Правило обнаруживает, что значение без безопасной параметризации попадает в запрос.
В CI контроль обычно размещают до долгих интеграционных и сквозных тестов:
Это схематический пример: конкретные названия задания и команды зависят от CI-системы и выбранного анализатора. Существенны два свойства: проверка запускается автоматически, а критичные находки не переводятся в успешный результат через allow_failure.
Нельзя блокировать каждую сборку по любому предупреждению. Сначала задают пороги: например, блокировать новые критичные и высокие уязвимости, а низкоприоритетные находки направлять в backlog с ответственным и сроком. Полезно учитывать только новые нарушения, иначе старый технический долг может сделать проверку непригодной для работы.
У SAST есть ограничения. Анализатор может выдавать ложные срабатывания, не понимать динамически сформированные конструкции или не увидеть уязвимость, проявляющуюся только в конфигурации и реальном окружении. Поэтому результат должен подтверждаться ревью и другими уровнями контроля, включая DAST, тесты безопасности и проверку зависимостей.
Главный компромисс — время обратной связи против полноты анализа. Быстрый анализ можно выполнять на каждом изменении, а более глубокие проверки — по расписанию или перед релизом, не ослабляя обязательный контроль для критичных правил.
Команда обнаружила несколько уязвимостей в обработчиках HTTP-запросов. Рассматривались три варианта. Усилить только code review было быстро, но результат зависел от внимательности конкретного ревьюера. Запустить полный динамический сканер на каждый коммит давал более реалистичную проверку, но существенно увеличивал время обратной связи и требовал подготовленного окружения. Добавить SAST в CI позволяло быстро находить типовые опасные конструкции, но не покрывало ошибки авторизации и настройки инфраструктуры.
Выбрали комбинацию: SAST для каждого изменения, проверку зависимостей в том же pipeline и динамический скан перед релизом. Сборка блокировалась только по новым критичным находкам, а спорные результаты проходили подтверждение владельцем компонента. Это сохранило раннюю обратную связь и не создало ложного ощущения, что один инструмент обеспечивает полную безопасность.
Нет. SAST ищет известные шаблоны и потоки данных, но может пропустить уязвимость из-за особенностей фреймворка, динамического SQL, конфигурации или нераспознанного источника ввода. Нужны параметризованные запросы как техническое исправление, code review и тесты, проверяющие защитные свойства приложения.
Потому что ложные срабатывания и исторический технический долг быстро превратят pipeline в источник постоянного шума. Разработчики начнут игнорировать результаты или обходить проверку. Практичнее разделить находки по риску, блокировать новые критичные нарушения и отдельно управлять подтверждёнными исключениями с владельцем и сроком пересмотра.
Базовый быстрый анализ лучше запускать на каждом изменении, чтобы сократить стоимость исправления и время обратной связи. Полный набор правил или ресурсоёмкие проверки можно запускать по расписанию и перед релизом. Разделение профилей оправдано, если оно не оставляет критичные правила только на позднем этапе.