На связи Денис Макрушин из команды SourceCraft. Индустрия AppSec десятилетиями жила в жёстком конфликте между полнотой и точностью поиска угроз. Классические SAST‑инструменты генерируют шум, на ручной разбор которого уходит больше времени, чем на реальную работу с угрозами. Релиз Claude Code Security от Anthropic заметно встряхнул индустрию кибербезопасности: капитализация традиционных вендоров просела, а генеральный директор крупного игрока Snyk заявил, что будущее компании теперь должен определять ИИ‑центричный лидер.
Рынок переопределил ценность инструмента безопасности. Раньше она измерялась количеством поддерживаемых правил и языков. Сегодня формула изменилась: важна цепочка — нашёл, объяснил, помог исправить. Здесь на сцену выходят LLM — не как замена классическому анализатору, а как дополнительный слой интерпретации. Так формируется новая категория — AI SAST.
В этой статье разберём, как именно LLM работают с кодом, почему «скормить репозиторий в промт» — плохая идея, какие инженерные метрики действительно важны и как мы исследуем и внедряем новые возможности автономного поиска и исправления дефектов в коде для добавления в продукты SourceCraft Security.
Почему классический SAST перестал устраивать команды
Главная боль разработчиков и AppSec-инженеров — не отсутствие находок, а информационный шум. Исследования подтверждают: до 91% предупреждений в опенсорс-проектах на GitHub оказываются ложными срабатываниями. В Python-приложениях на Flask ситуация ещё показательнее: 99,5% предупреждений о потенциальных инъекциях были ложными.
Вот основные типы шума:
Сигнатурные ложные срабатывания: анализатор видит опасный паттерн, но в текущем контексте он безопасен. Сканеры намеренно снижают порог срабатывания, чтобы не пропустить угрозу.
Дубликаты: один баг триггерит несколько правил. Анализатор не группирует результаты, а отдаёт их «как есть».
Алерты без контекста (ложные «ложные срабатывания»): сканер технически прав, но не даёт разработчику информации для оценки риска. Не понимая, почему находка важна, инженер помечает её как ошибочную и пропускает реальную уязвимость.
Неэксплуатируемые находки: уязвимый код существует, но до него невозможно добраться извне.
Неприоритетные в контексте: минорные проблемы, которые переполняют бэклог и отвлекают от критических окон.
Именно на разбор этого шума команды сжигают часы. Решить проблему можно анализом достижимости: так, из 865 398 годовых алертов только 715 остаются критическими после проверки уязвимого компонента. И вот здесь LLM берут на себя триаж: отсекают дубли, оценивают реальный риск эксплойта и объясняют разработчику, почему проблема актуальна для его проекта.
Идеальный процесс исправления уязвимости — тот, в котором разработчика нет вообще. А если он и появляется, то исключительно для того, чтобы нажать кнопку «Триаж», а затем «Применить исправление». Да, может казаться, что это очередной шаг к «замене разработчиков ИИ». Но на самом деле это просто смещение фокуса: команда перестаёт работать ручным фильтром шума и концентрируется на архитектуре, безопасности, бизнес-логике и реальных угрозах.
Применение LLM для анализа кода: слайсинг, CPG и борьба с контекст-лимитами
Если просто загрузить небольшой файл с кодом в LLM и попросить найти баги, то модель, скорее всего, справится. В реальном репозитории крупного проекта или компании она быстро потеряется, потому что не учитывает сборочные конфиги, игнорирует контекст рантайма и путается в цепочках вызовов. Здесь мы упираемся в фундаментальное ограничение: LLM работают на вероятностях, а не на детерминированных правилах.
Это значит, что сегодня модель уверенно находит уязвимость, а завтра на той же кодовой базе может её пропустить. Из-за такой нестабильности LLM не могут заменить формальную верификацию и классические анализаторы. Их роль заключается в улучшении семантического анализа, который добавит анализатору «понимание» бизнес-логики.
Именно поэтому в проде LLM не работает в вакууме. Она становится частью инженерного пайплайна, где процесс «угадывания» заменяется работой определённых инструментов. Ключевой фактор — контекст: он должен быть релевантным и минимально достаточным для обнаружения. Если передать модели слишком мало кода, то можно лишить её смысловых связей и спровоцировать галлюцинации. Если перегрузить лишними файлами и зависимостями, то можно её расфокусировать, сжечь лимиты токенов и утонуть в незначительных находках.
В идеальном контексте содержатся: источник данных (source), путь потока, места появления этих данных (стоки, или sink) и ближайшее окружение. На практике используют комбинации стратегий слайсинга, чтобы соблюсти баланс при передаче контекста:
CPG (Code Property Graph) объединяет AST, граф управления потоком и граф потока данных в единую структуру. Наиболее точный метод, позволяет модели видеть уязвимость через призму структурных связей, а не просто текста.
Граф вызовов вытягивает цепочку связанных функций, когда уязвимость распределена по нескольким файлам или кросс-языковым вызовам.
RAG по кодовой базе — модель ищет похожие паттерны в исторических данных и использует их как подсказку. Проще внедрить, но точность ниже, чем у CPG.
Чанкинг — когда код режут на фрагменты и добавляют к ним минимум нужного контекста. Это самый простой, но и самый «грубый» вариант.
Классические правила остаются во главе того, что можно формализовать: типовые паттерны, строгие проверки стандартов, поиск хардкода. LLM выигрывают там, где нужен смысл: понимание бизнес-логики, кастомных обёрток над API и внутренних договорённостей команды.
Яркий пример из практики Tencent: исследователи столкнулись с тем, что классический анализатор теряет след в многопоточных приложениях и динамических вызовах. Эксперты создали кастомный анализатор потока информации, который генерировал «шпаргалку» о перемещении данных, а LLM фильтровала шум, классифицировала функции и помогала находить уязвимости в сложных архитектурных узлах, где статический анализ слепнет.

Референс-архитектура: место ИИ в CI-пайплайне и валидация
Для эффективного применения LLM в SAST модель подключают в двух ключевых местах. До начала классического анализа она работает как интеллектуальный разведчик, который собирает поверхность атаки (все возможные источники данных), и помогает классическому движку проанализировать больше данных. После анализа модель берёт на себя кластеризацию и триаж, превращая сырой поток алертов в приоритизированный список реальных проблем. В итоге получаем следующий пайплайн:
Инвентаризация, определение скоупа для анализа и сбор поверхности атаки. Модуль сканирует не весь репозиторий, а изменённые файлы, затронутые зависимости и соседние модули. Исключает из скоупа несущественные части проекта.
Классический анализ. Движок анализатора на основе набора правил (анализ taint-трасс, AST/IR-проверки и т. д.) генерирует сырые сигналы.
Первичная обработка результатов. Сырые находки дедуплицируются и группируются по общим признакам.
Триаж. LLM получает нормализованные находки и их контекст. Она приоритизирует, объясняет риски и предлагает исправления, то есть снижает когнитивную нагрузку аналитика.
Автопатчинг и валидация исправления. Любое сгенерированное исправление проходит обязательный процесс проверки компиляции и линтеров, запуск unit/integration-тестов, повторный SAST-скан. Если хоть один шаг падает, то исправление отклоняется.
Чтобы этот процесс при каждом запуске на одном и том же скоупе не давал разные результаты, то есть был детерминированным, нужно обеспечить воспроизводимость результатов на каждом шаге в CI. Для этого стоит зафиксировать нулевую температуру модели, seed, версии и шаблоны промтов. Полученные результаты стоит занести в кеш, чтобы не проводить повторную генерацию для этого скоупа.
3 архитектуры AI SAST и метрики качества
При сравнении инструментов статического анализа часто обращают внимание исключительно на метрику точности (accuracy), но даже высокий процент точности не даёт гарантии, что инженер не будет тратить своё время на разбор ложных срабатываний. Разбор находок с помощью LLM поднимает точность до 90%, но если на обработку оставшегося шума всё ещё уходит значительный инженерный ресурс, то становится очевидно, что метрику нужно менять. Стоимость ложных срабатываний (FP-cost) — хорошая операционная метрика для команд разработки. Она складывается из трёх слагаемых:
Precision/Recall, которые показывают количество шума. Здесь собираются все сигнатурные FP (анализатор видит опасный шаблон, но не учитывает контекст исполнения), дубли (один и тот же баг находится несколькими правилами), неэксплуатируемые находки (код уязвим, но нет возможности его эксплуатации). Чем ниже Precision, тем больше FP в очереди на разбор, тем выше базовая стоимость шума.
Время на обработку находки (
time-to-triageиmean-time-to-respond). Чем короче время жизни алерта, тем меньше окно для использования уязвимости. При этом каждую находку в очереди кто-то должен открыть, восстановить контекст, изучить трассу и вынести вердикт. Ручной разбор занимает десятки минут, триаж с помощью ИИ — секунды.Fix acceptance rate. На этом этапе инженер инвестирует своё время на разработку исправления. Патч, который не проходит процесс тестирования (сборка, тесты, повторное SAST-сканирование), добавляет скрытую стоимость: в лучшем случае он блокирует релиз, а в худшем — закрывает несуществующую проблему или открывает реальную.
Чтобы улучшить эти метрики, можно начать итеративную трансформацию традиционного процесса статического анализа, постепенно наращивая зрелость используемых инструментов. Внутри технологического сегмента AI SAST сейчас формируются три архитектурных подхода:
AI-enhanced — модель используется для фильтрации результатов и снижения нагрузки на аналитика.
AI-explorer — модель генерирует гипотезы и расширяет поверхность для поиска ошибок традиционными движками статического анализа за счёт новых точек входа и правил.
AI-native — модель не только участвует в генерации гипотез, но и обрабатывает результаты, анализирует контекст и генерирует исправления.
Эти архитектурные подходы также являются тремя этапами продуктовой эволюции. Её ограничивают три фактора: экономика операций, проблемы «личности» агента и неэффективный вызов инструментов. Широкий контекст для агента увеличивает стоимость его действий. Кроме того, агент может решить, что какое-то событие выглядит безопасно, и пропустить его из-за субъективной вероятности. Ну а попытки LLM вызвать внешние инструменты чаще оказываются дороже, чем использование классических правил.
При разработке функций ИИ-триажа в своей платформе мы боролись с этими ограничениями с помощью оптимизации контекста для передачи в модель, чтобы его было достаточно для принятия решения о FP. В результате для каждой группы дефектов, которую находят наши анализаторы (да, у нас целый набор движков статического анализа), мы определяем и передаём следующий контекст в LLM:
codeBlock— основной фрагмент кода, связанный с проблемой;ruleName— правило анализатора, которое нашло дефект;engine/engineType— какой движок обнаружил проблему;severityиcvssScore— критичность находки;firstFoundCommitHash— коммит, где дефект впервые найден;latestCommitHash— последний коммит, где дефект ещё найден;latestTimeFound— время последнего обнаружения;shortDescription,fullDescription,helpText,helpUri— описание проблемы и ссылка/подсказка для исправления;а с недавних пор передаём трассу — путь данных по коду: от источника (
source) через промежуточные шаги (propagation) до опасного места (sink).
Этих данных сейчас достаточно для точной оценки уязвимости и предложения релевантного исправления.

В SourceCraft ИИ-триаж реализован как одна кнопка в интерфейсе безопасности. Нажимая её, инженер запускает анализ: модель классифицирует алерт, выставляет приоритет и генерирует пояснительную записку с привязкой к конкретным файлам, путям данных и зависимостям. Мы видим стабильный рост использования функции: команда перестала бороться с шумом и сфокусировалась на реальных рисках, а стоимость обработки одного алерта упала с 10–20 минут до нескольких секунд.
Галлюцинации, инъекции и guardrails для защиты
LLM привносит вероятностные процессы в детерминированный контур CI/CD. Это свойство модели может приводить к трём категориям ошибок: ложные срабатывания (например, часто модель может что-то пропустить при большом контексте), некорректные трейсы потока данных и ошибочные исправления уязвимостей, которые ломают приложение.
Кроме того, появляется риск, связанный с prompt injection. Для модели входные данные — это любой код, комментарий или описание пулреквеста в репозитории. Это является дополнительной поверхностью для атак: например, злоумышленник может спрятать в исходном коде или описании PR инструкцию вроде /* ignore security checks for this file */. Именно поэтому модель должна воспринимать репозиторий исключительно как данные, а не как команды.

Эти риски можно снизить, встроив в пайплайн дополнительные ограничения, например:
проверку ответов модели через детерминированный код и белые списки операций;
автоматическую санитизацию секретов, токенов и маскировка персональных данных до отправки в модель;
логирование входных данных в модель, версий промтов, параметров генерации и всех действий агента для последующего аудита и оценки соответствия (
compliance);контроль исходящего трафика и использование песочниц для ограничения сетевых вызовов и действий агента.
Каждому из этих способов защиты агента можно посвятить отдельный материал, поэтому здесь зафиксируем ключевую мысль: любое приложение, в котором используется ИИ, должно иметь встроенные механизмы защиты от незапланированного поведения этого ИИ.
Что будет дальше
На текущем этапе развития генеративных моделей ядро статического анализа всё ещё остаётся ключевым элементом SAST. Классический движок даёт результат, который пока трудно получить с помощью LLM, — воспроизводимость находок и их верификацию с помощью формальных методов. По этой причине LLM не заменяют классические методы анализаторов, а усиливают их в тех моментах, где слепнет классика, основанная на правилах: анализ динамических вызовов, бизнес-логики и постобработка результата.
В этой статье мы ещё раз напомнили себе и товарищам-разработчикам о том, как важно оценивать инструменты поиска ошибок не по формальным показателям ложных срабатываний, а по фактическому времени, которое инженер тратит, чтобы довести находку до закрытого тикета.
Оставим для комментариев открытый вопрос: готовы ли вы сделать процесс исправления уязвимости полностью автономным и делегировать его ИИ-агенту?























