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

SAST решений обзор: как найти уязвимости до того, как их найдёт кто-то другой

Лет пять назад я был на code review. Обычный MR, казалось бы — добавили фичу авторизации через SMS. Я глянул, одобрил. Через месяц у нас украли базу клиентов че

Лет пять назад я был на code review. Обычный MR, казалось бы — добавили фичу авторизации через SMS. Я глянул, одобрил. Через месяц у нас украли базу клиентов через SQL-инъекцию в том самом месте. Стыдно? Очень.

С тех пор я не полагаюсь только на свои глаза. И на глаза коллег тоже. Человеческий фактор — это не оправдание, это реальность. Люди устают, отвлекаются, пропускают очевидное. Поэтому SAST — статический анализ безопасности кода — теперь обязательная часть моего пайплайна.

Что вообще такое SAST и чем отличается от DAST

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

Аналогия простая. SAST — это когда строитель проверяет чертежи до стройки. DAST — когда пожарный инспектор приходит в готовое здание и ищет, где горит.

Оба подхода нужны. Но у SAST решений есть критическое преимущество: они находят проблемы на раннем этапе. Чем раньше найдена уязвимость, тем дешевле её исправить. Исправить баг на этапе разработки стоит копейки. На проде — тысячи долларов, репутационные потери и ночные деплои.

Хорошие SAST-инструменты умеют:

Но есть нюанс. SAST не понимает, как код будет выполняться. Он видит текст. Поэтому бывают false positives — ложные срабатывания. Много их.

Типичные уязвимости, которые ловит SAST

SQL-инъекции

Классика. Пример на Python:

# Плохо — конкатенация строк
def get_user(user_id):
    query = f"SELECT * FROM users WHERE id = {user_id}"
    return db.execute(query)

# Хорошо — параметризованный запрос
def get_user(user_id):
    query = "SELECT * FROM users WHERE id = ?"
    return db.execute(query, (user_id,))

Любой SAST найдёт первый вариант и покажет на него пальцем. И правильно сделает.

XSS — межсайтовый скриптинг

Тоже боль. Особенно в SPA-приложениях.

// Плохо — вставка без санитизации
element.innerHTML = userInput;

// Хорошо — textContent или санитизация
element.textContent = userInput;
// или
element.innerHTML = DOMPurify.sanitize(userInput);

Хардкоденные секреты

Я видел это десятки раз. Коммитят AWS-ключи, API-токены, пароли от баз данных.

# Так делать нельзя, но все делают
API_KEY = "sk-live-51234567890abcdefghijklmnop"
DB_PASSWORD = "admin123"  # да, реально такое было

SAST-сканеры умеют искать паттерны секретов. Regex по типичным форматам ключей — и готово. Но надёжнее использовать pre-commit хуки, которые блокируют такие коммиты локально.

Небезопасная десериализация

Это уже посложнее. Но критично.

# Опасно — pickle может выполнить произвольный код
import pickle
data = pickle.loads(user_input)

# Безопаснее — json для простых данных
import json
data = json.loads(user_input)

Pickle в Python — это бомба замедленного действия. Если нагрузить в него данные от пользователя, можно получить удалённое выполнение кода. SAST это знает.

Как выбрать SAST-инструмент

Рынок SAST решений сейчас огромен. Есть бесплатные open-source инструменты. Есть дорогие Enterprise-платформы за десятки тысяч долларов в год. Что выбрать?

Сразу скажу: бесплатное — не значит плохое. SonarQube Community Edition покрывает базовые потребности. Bandit для Python — отличный инструмент. ESLint с плагинами безопасности для JavaScript — must have.

Но есть проблема. Инструментов много, и все они разные. Каждый нужно настраивать, интегрировать, поддерживать. На одном проекте у нас было три разных сканера. Bandit для Python, ESLint для фронтенда, SpotBugs для Java. Конфигурация рассыпалась, результаты дублировались, разработчики ненавидели пайплайн.

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

Интеграция SAST в CI/CD pipeline

Вот тут многие ошибаются. Поднимают SonarQube, запускают сканирование раз в неделю руками. Это не работает. SAST должен быть частью каждого pull request.

Пример для GitLab CI:

stages:
  - test
  - security

sast:
  stage: security
  image: docker:stable
  services:
    - docker:dind
  variables:
    SAST_ANALYZER_IMAGE_TAG: latest
  script:
    - /analyzer run
  artifacts:
    reports:
      sast: gl-sast-report.json
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

GitHub Actions — аналогично:

name: Security Scan
on: [pull_request]

jobs:
  sast:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run SAST
        uses: github/super-linter@v4
        env:
          VALIDATE_ALL_CODEBASE: false
          DEFAULT_BRANCH: main

Но просто запустить — мало. Нужно ещё и реагировать на результаты. Если сканер нашёл критическую уязвимость, MR не должен мёржиться автоматически. Guard rails — обязательная штука.

False positives — главная боль SAST

Вот честно: большая часть предупреждений SAST — шум. Особенно на легаси-проектах. Тысячи предупреждений, из которых реальных уязвимостей — единицы.

Что с этим делать?

Первое — настроить правила под свой стек. Если проект на Django, зачем проверять Spring-специфику? Отключить ненужное.

Второе — baseline. При первом запуске SAST найдёт сотни проблем. Не пытайтесь исправить всё сразу. Зафиксируйте baseline, и новые предупреждения показывайте только на новом коде.

Третье — приоритизация. Не все уязвимости одинаково важны. SQL-инъекция в публичном API — критично. Но хардкоднутый ключ от тестовой базы в закомментированном коде — low priority.

SAST vs Code Review — нужны оба

Есть мнение, что автоматизация заменит ревью. Нет. SAST решений много, а понимания бизнес-логики у них нет.

Сканер найдёт SQL-инъекцию. Но он не заметит, что вы разрешаете удалять чужие заказы, потому что проверка user_id стоит после запроса к базе. Это логическая ошибка, не паттерн уязвимости.

Поэтому идеальный сценарий: SAST работает как первый фильтр. Ловит очевидное, экономит время ревьюеров. А люди смотрят на архитектуру, бизнес-логику, неочевидные баги.

На одном проекте мы внедрили связку: SonarQube для SAST + обязательное ревью. Sonar находил 80% глупых ошибок. Ревьюеры сфокусировались на важном. Количество багов на проде упало втрое за квартал.

Что насчёт AI?

Современные AI-инструменты для code review умеют находить уязвимости лучше традиционных SAST. Они понимают контекст, видят паттерны, которые regex не заметит.

Я сейчас тестирую Distiq — российский AI-бот для code review. Он интегрируется в GitLab и GitHub, анализирует каждый MR, оставляет инлайн-комментарии. В отличие от классических SAST-сканеров, он меньше шумит и лучше понимает смысл кода. Для команд, которые не хотят тратить время на настройку SonarQube и борьбу с false positives — нормальный вариант. Внедряется за пару минут через webhook, серверы в РФ.

В общем, SAST — это база. Без него в 2024 году стыдно деплоить. Выбирайте инструмент, интегрируйте в пайплайн, не забывайте про ревью. И не повторяйте моих ошибок с SQL-инъекциями.

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

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

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

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