// Engineering Log
Безопасная разработка: Часть 3 — SAST: статический анализ кода
Опубликовано 22.09.2026
// Быстрый маршрут
Эта статья относится к теме Безопасность и защита.
Опытный разработчик находит уязвимости в чужом коде по знакомым признакам: данные пользователя попадают прямо в SQL-запрос, пароль сравнивается обычным ==, путь к файлу собирается из параметра запроса. Но просмотреть так сто тысяч строк и ничего не упустить человек не может. Эту работу берёт на себя SAST.
Что такое SAST
SAST (Static Application Security Testing, статический анализ безопасности) — проверка исходного кода без запуска приложения. Анализатор разбирает код в синтаксическое дерево и ищет в нём опасные конструкции.
Главный приём — анализ потока данных (taint analysis). Анализатор отмечает «источники» — места, откуда приходят недоверенные данные: параметры запроса, заголовки, тело формы. Затем он прослеживает, дойдут ли эти данные до «стока» — опасной функции вроде выполнения SQL, запуска команды оболочки или записи в HTML, — не пройдя по пути через очистку или экранирование. Если дойдут, появляется предупреждение.
Тесты такой работы не заменяют. Тест проверяет, что при вводе имени Ivan в базу записывается Ivan. SAST проверяет, что произойдёт, если вместо имени придёт ' OR 1=1 --, хотя функционально код работает правильно.
Пример: SQL-инъекция
@app.route("/user")
def get_user():
user_id = request.args.get("id")
# опасно: значение из запроса подставляется в текст запроса
query = "SELECT * FROM users WHERE id = %s" % user_id
db.execute(query)Правило анализатора описывает ровно эту ситуацию: значение из request через форматирование строки попадает в execute(). Исправление — параметризованный запрос: db.execute("SELECT * FROM users WHERE id = %s", (user_id,)). Драйвер базы передаёт значение отдельно от текста запроса, и инъекция становится невозможной.
Инструменты
Semgrep
Semgrep — самый распространённый лёгкий анализатор. Правила пишутся в YAML почти на языке самого кода, поэтому своё правило для проекта можно составить за несколько минут.
Важно понимать, как устроена его лицензия. Движок Semgrep Community Edition распространяется под LGPL-2.1 и бесплатен. Но возможности у него ограничены: по документации Semgrep, открытая версия анализирует взаимодействия только внутри одной функции. Анализ между функциями и между файлами есть в платном продукте Semgrep Code. Правила, которые поддерживает сама компания, распространяются под собственной лицензией: их можно использовать для внутренних задач, но нельзя встраивать в конкурирующие продукты и сервисы.
Opengrep
Когда Semgrep перенёс часть возможностей под коммерческую лицензию, группа компаний создала форк Opengrep. Он распространяется под LGPL-2.1, совместим с правилами Semgrep и развивает анализ потока данных в открытом виде. Если вам важно, чтобы инструмент оставался полностью открытым, Opengrep — естественная замена.
SonarQube Community Build
SonarQube — платформа, которая совмещает поиск уязвимостей с проверкой качества кода: дублирование, сложность, покрытие тестами. Бесплатная редакция Community Build распространяется под LGPL-3.0 и ставится на свой сервер. Для небольшой команды это удобный вариант, если нужен общий отчёт по проекту, а не только сканер в CI.
CodeQL
CodeQL от GitHub описывает код как базу данных, к которой пишутся запросы. Это один из самых глубоких анализаторов. Для публичных репозиториев на GitHub сканирование кода включено бесплатно. Для закрытых репозиториев нужен платный продукт GitHub Code Security, и его доступность и оплату для российской компании нужно проверять отдельно.
Как запустить локально
Semgrep ставится через pip или Homebrew:
pip install semgrep
semgrep scan --config p/pythonp/python — готовый набор правил для Python из реестра Semgrep. Для JavaScript есть p/javascript, для общих проверок — p/default. Opengrep устанавливается скриптом из репозитория проекта и принимает те же правила.
SAST в CI
Проверку имеет смысл запускать на каждом запросе на слияние: уязвимость, найденная до слияния, обходится дешевле всего. Пример задания для GitHub Actions на официальном образе Semgrep:
name: sast
on: [pull_request]
jobs:
semgrep:
runs-on: ubuntu-latest
container:
image: semgrep/semgrep
steps:
- uses: actions/checkout@v4
- run: semgrep scan --config p/python --errorКлюч --error завершает команду с ошибкой, если найдены проблемы, и CI не даёт влить код. Старая обёртка semgrep-action объявлена устаревшей, поэтому Semgrep запускается напрямую, как в примере. В GitLab CI то же самое делается заданием с тем же образом.
Чтобы не утонуть в старых находках, начните с режима, в котором проверяется только изменённый код, либо сначала соберите базовый отчёт и договоритесь, что новые предупреждения запрещены, а старые разбираются постепенно.
Ложные срабатывания
Ни один анализатор не точен до конца: иногда безопасный код помечается как опасный.
- Настройка правил. Слишком строгое правило можно отключить или уточнить под проект.
- Подавление на месте. Комментарий
# nosemgrepнад строкой отключает проверку для неё. Рядом стоит объяснить, почему код безопасен, иначе через полгода никто этого не вспомнит. - Разбор. В команде кто-то отвечает за отчёты и помечает находки как «исправить» или «ложное».
Если подавлений становится много, это сигнал пересмотреть набор правил, а не привыкать к шуму.
С чего начать
- Запустите Semgrep или Opengrep на своём проекте один раз и разберите находки уровня ERROR.
- Добавьте проверку в CI на запросах на слияние, сначала только для новых предупреждений.
- Напишите одно-два собственных правила для типичных ошибок вашего проекта: это самый быстрый способ получить пользу, которую не дадут общие наборы.
// Похожая задача
Если у вас похожая ситуация
Эта статья относится к одной из рабочих тем. Можно продолжить чтение по теме, перейти на главную, чтобы понять, чем я занимаюсь, или сразу открыть услуги.
Тема статьи
Безопасность и защита
SSL, hardening, доступы, защита сервисов и безопасные конфигурации.
Часто с этим приходят
- Настроить SSL, сертификаты и безопасные подключения
- Ограничить доступы и закрыть лишние точки входа
- Усилить конфигурацию сервера и сервисов
// Следующий шаг
Если вам нужна не только статья, а помощь по этой теме, удобнее сразу перейти в услугу. Главная и подборка материалов остаются рядом.
Открыть услуги// Contact
Нужна помощь?
Свяжись со мной и я помогу решить проблему
Написать в TelegramОтвечаю в течение рабочего дня (03:00–13:00 GMT)
Или оставьте заявку здесь:
// Related