Security7 мин чтения2026-03-06

GitLab SAST: как автоматизировать поиск уязвимостей в коде

Когда я работал в одном стартапе, мы два месяца искали SQL-injection в production. Нашли случайно. Если бы тогда у нас была нормальная автоматизация безопасност

Когда я работал в одном стартапе, мы два месяца искали SQL-injection в production. Нашли случайно. Если бы тогда у нас была нормальная автоматизация безопасности, потратили бы пару часов, а не две смены отладки под продакшеном. Вот тогда я понял: SAST в pipeline — это не опция, а необходимость.

GitLab SAST (Static Application Security Testing) — это встроенный в CI/CD механизм, который сканирует код и ловит уязвимости ещё до того, как код попадёт в production. Не нужно никаких внешних сервисов, не нужно доплачивать за облако. Всё работает внутри твоего GitLab.

Давайте разберёмся, как это реально работает и почему это экономит кучу времени.

Что такое SAST и почему это важнее, чем кажется

SAST — это статический анализ кода. Робот читает твой исходник, ищет паттерны, которые потенциально опасны, и говорит: "Стоп, здесь может быть проблема". Ключевое слово — "может быть". SAST часто даёт ложные срабатывания, и это нормально.

Противоположность SAST — это DAST (Dynamic Application Security Testing). DAST запускает приложение и пытается его взломать: отправляет вредоносные данные, проверяет заголовки, смотрит, что будет. SAST быстрее, DAST точнее, но дороже в смысле вычислений.

В GitLab SAST работает прямо в pipeline. Ты коммитишь код, запускается merge request, и автоматически:

  1. Код сканируется на известные паттерны уязвимостей
  2. Результаты выводятся в UI GitLab
  3. Блокируется merge, если нашлись критичные проблемы (если ты так настроил)

По моему опыту, 70% команд, которые внедрили SAST, за первый месяц находят по 3-5 серьёзных проблем, о которых раньше не знали.

Как включить SAST в GitLab CI

Самый простой способ — добавить в .gitlab-ci.yml одну строку:

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

Вот и всё. При следующем push GitLab автоматически подключит сканеры для всех языков, которые ты используешь в проекте.

Полный минимальный .gitlab-ci.yml:

stages:
  - test
  - security

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

test:
  stage: test
  script:
    - npm test

sast:
  stage: security

GitLab сам определит, какой язык ты пишешь, и запустит подходящие сканеры. Поддерживает Python, JavaScript, Java, Go, C#, PHP, Ruby и ещё с десяток.

Но если ты хочешь больше контроля — можешь настроить детальнее:

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

variables:
  SAST_EXCLUDED_PATHS: "spec, test, tests, tmp"
  SAST_BANDIT_LEVEL: 2

sast:
  stage: security
  allow_failure: false

Здесь:

Какие уязвимости ловит GitLab SAST

Честно? Большинство разработчиков думают, что SAST ловит только очевидные баги. На самом деле спектр шире.

SQL-injection — классика жанра:

# Плохо
user_id = request.args.get('id')
query = f"SELECT * FROM users WHERE id = {user_id}"
result = db.execute(query)

# SAST это поймает

SAST видит, что в SQL-запрос вставляется пользовательский ввод напрямую. Это красный флаг.

Command injection — когда передаёшь параметры в системные команды:

# Плохо
filename = request.args.get('file')
os.system(f"cat {filename}")

# SAST это видит

Если злоумышленник передаст file=secret.txt; rm -rf /, будет беда. SAST ловит такие паттерны.

Использование небезопасных функций:

# Плохо — eval() опасен
code = request.args.get('code')
result = eval(code)

# SAST это поймает и скажет: используй ast.literal_eval() или другой способ

Жёсткие пароли в коде:

# Плохо
DB_PASSWORD = "super_secret_123"
API_KEY = "sk-1234567890abcdef"

# SAST это поймает

SAST ловит регулярные выражения, которые похожи на секреты. Очень полезно, потому что люди часто забывают, что залили пароль в git.

Unsafe deserialization — десериализация JSON/pickle из ненадёжных источников:

# Плохо
import pickle
data = request.data
obj = pickle.loads(data)  # SAST: опасно!

# Плохо
import json
user_input = request.args.get('data')
obj = json.loads(user_input)
eval(obj)  # Если дальше это обрабатывается опасно

XXE (XML External Entity) — когда парсишь XML без защиты:

# Плохо
import xml.etree.ElementTree as ET
xml_data = request.data
tree = ET.fromstring(xml_data)  # Без защиты от XXE

Weak cryptography — использование старых алгоритмов:

# Плохо
import hashlib
password_hash = hashlib.md5(password).hexdigest()

# Нужно использовать bcrypt или argon2

По-хорошему, за первый запуск SAST на среднем проекте можно найти 5-15 таких проблем. Большинство из них вполне реальные уязвимости.

Интеграция с GitLab UI и результаты

После того как SAST отработает, результаты видны в нескольких местах:

В merge request — инлайн-комментарии прямо на коде:

На строке 42:
⚠️ SQL Injection - User input directly concatenated in SQL query
Severity: High
CWE: CWE-89

В Security tab проекта — полный список всех найденных уязвимостей с историей:

Critical: 2
High: 5
Medium: 12
Low: 8

В artifacts — JSON с подробными отчётами (если нужно обработать программно).

Можешь настроить, чтобы pipeline блокировался, если нашлись уязвимости выше определённого уровня. Например:

sast:
  stage: security
  allow_failure: false  # Pipeline падает, если есть High или выше

Или с более тонкой настройкой через Policy:

sast:
  stage: security
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      allow_failure: false
    - allow_failure: true

Здесь: в main branch блокируем, в feature branch только предупреждаем.

Практические примеры настройки

Вот реальный конфиг, который я использую на проектах:

stages:
  - build
  - test
  - security

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

variables:
  SAST_EXCLUDED_PATHS: "tests,spec,node_modules,vendor"
  SAST_EXCLUDED_ANALYZERS: "eslint"  # Используем свой linter
  SECURE_LOG_LEVEL: "debug"

sast:
  stage: security
  artifacts:
    reports:
      sast: gl-sast-report.json
    expire_in: 30 days
  allow_failure: false
  only:
    - merge_requests
    - main
    - develop

dependency_scanning:
  stage: security
  allow_failure: true  # Только предупреждаем о уязвимостях в зависимостях

Что здесь:

GitLab CI SAST vs. другие инструменты

Часто спрашивают: "А может быть, лучше использовать SonarQube или Checkmarx?"

По-хорошему, GitLab SAST — это не замена, это база. Вот сравнение:

GitLab SAST:

SonarQube:

Checkmarx:

На практике: начни с GitLab SAST, если её недостаточно — добавь SonarQube. Checkmarx берут только крупные компании с бюджетом.

Типичные ошибки при внедрении SAST

Ошибка 1: Включил SAST и заблокировал все merge requests

Правильно: сначала запусти в режиме allow_failure: true неделю-две, дай команде разобраться с существующими проблемами, потом включи блокировку.

Ошибка 2: Исключил слишком много путей

Видел проект, где исключили src, потому что "там слишком много ложных срабатываний". Вместо этого нужно настроить правила конкретнее или обновить версию сканера.

Ошибка 3: Игнорируешь все warnings

Если в SAST появляются жалобы, которые ты помечаешь как "false positive" — не просто игнорируй, добавь их в whitelist:

sast:
  variables:
    SAST_EXCLUDED_PATHS: "..."

Это поможет избежать спама в следующих запусках.

Ошибка 4: Не обновляешь версии сканеров

GitLab регулярно выпускает обновления для SAST-сканеров. Новые версии ловят новые уязвимости. Обновляй хотя бы раз в квартал.

Как интегрировать SAST с другими инструментами

Если у тебя уже есть система управления уязвимостями (например, Jira или Linear для трекинга), можешь автоматизировать создание задач:

sast:
  artifacts:
    reports:
      sast: gl-sast-report.json

create_issues:
  stage: security
  image: alpine:latest
  script:
    - |
      # Парсим JSON отчёта
      cat gl-sast-report.json | jq '.vulnerabilities[] | 
      "curl -X POST https://jira.company.com/rest/api/2/issue 
      -d {\"fields\": {\"project\": \"SEC\", \"summary\": .name}}"'
  dependencies:
    - sast
  only:
    - merge_requests

Это уже более специфичный пример, но идея понятна: можешь захватить результаты SAST и отправить их в свою систему.

Что дальше после SAST

SAST — это только первый слой защиты. По-хорошему, нужна комбо:

  1. SAST (статический анализ) — ловит очевидные проблемы в коде
  2. Dependency scanning — проверяет, не используешь ли ты библиотеки с известными уязвимостями
  3. DAST (динамический анализ) — запускает приложение и тестирует его
  4. Container scanning — сканирует Docker-образы на уязвимости
  5. License scanning — проверяет, что используемые библиотеки имеют совместимые лицензии

В GitLab всё это встроено. Просто добавляй шаблоны в .gitlab-ci.yml:

include:
  - template: Security/SAST.gitlab-ci.yml
  - template: Security/Dependency-Scanning.gitlab-ci.yml
  - template: Security/DAST.gitlab-ci.yml
  - template: Security/Container-Scanning.gitlab-ci.yml

И у тебя появится полная защита.


Если SAST в GitLab кажется тебе недостаточным или ты хочешь добавить слой code review поверх автоматизации — попробуй Distiq. Это AI-бот для code review, который работает в GitLab, GitHub и GitVerse. Он ловит не только уязвимости, но и архитектурные проблемы, проблемы с производительностью, нарушения стиля кода. Настраивается за пару минут, интегрируется через webhook. Российский сервис, данные остаются в стране.

Начни с встроенного SAST — это база. Добавь Distiq, если н

Попробуйте Distiq для автоматического code review

AI-бот анализирует каждый MR/PR и оставляет комментарии с замечаниями. Интеграция за 2 минуты.

Попробовать бесплатно

Похожие статьи