Реклама
Селектел, перетяжка, 22.06
Селектел, перетяжка, 22.06
Селектел, перетяжка, 22.06

Как Cloudflare строит ИИ-харнесс для охоты на уязвимости

Один кодинг-агент не способен провести аудит всей кодовой базы. Рассказываем, как устроен model-agnostic harness, который фильтрует тысячи сырых кандидатов до очереди проверенных исправлений.

Обложка: Как Cloudflare строит ИИ-харнесс для охоты на уязвимости

ИИ-харнесс (vulnerability harness) — это оркестратор, который запускает сотни независимых ИИ-расследований, сохраняет состояние между запусками и фильтрует сырые находки до очереди проверенных исправлений. Если вы думаете, что один «суперпромпт» в ChatGPT способен найти все уязвимости в монорепозитории, вас ждёт разочарование: агент в одиночку держит в голове одну гипотезу, переполняет контекстное окно за час и теряет результаты при сжатии контекста. Команда Project Glasswing из Cloudflare столкнулась с этим на практике и пришла к выводу: важна не модель, а обвязка вокруг неё.

Харнесс не привязан к одной модели: одна модель ищет уязвимости в VDH, а другая модель в VVS независимо валидирует находки, включая оценку риска в продакшене. Так Model B оценивает вывод Model A с другими весами и другими обучающими данными, словно независимый адвокат дьявола. Это не просто безопасность: провайдеры моделей меняют температуру, кэширование и бюджеты инференса даже в рамках одной версии, а харнесс умеет поглощать эту волатильность, не ломаясь.

Ключевые выводы

Харнесс — это не модель, а оркестрация. Ценность в конвейере с сохранением состояния, а не в очередном промпте.

Две стадии: Vulnerability Discovery Harness (VDH) ищет баги, Vulnerability Validation System (VVS) проверяет, дедуплицирует и чинит их.

Контекст держится под контролем. Каждый агент решает узкую задачу и использует менее 25% окна.

Доверие через adversarial verification. Охотник должен предъявить модель угрозы, рабочий PoC и патч; валидатор обязан опровергнуть находку.

Цифры масштаба: VDH охватывает 128 репозиториев; в общий VVS на момент публикации попало 13 841 находка по 145 репозиториям, из которых 7 245 — находок, по которым можно действовать, отправлены инженерам на исправление.

Почему обычный кодинг-агент не справляется

Cloudflare начинала с 450-строчного скилла security-audit, который проходил семь фаз в одной сессии: три агента-разведчика писали архитектуру, охотники атаковали код по классам угроз, валидаторы пытались опровергнуть находки, а финальный агент перепроверял выжившие баги. Скилл работал, но быстро уперся в потолок.

Один прогон находит примерно половину тех багов, которые выловят несколько прогонов, и склонен к простым, очевидным ошибкам. Как только процесс превращается в «запусти десять раз и сравни руками», пора переходить к настоящей оркестрации.

Три стены, которые ломают односессионный подход

  • Исчерпание контекста. Через час модель начинает «пожирать» собственную память и забывает баги, которые искала утром. Решение — вынести состояние наружу и считать LLM stateless-движком.
  • Отсутствие персистентности. Ошибка API или обрыв соединения обнуляют часы работы. SQLite, ключированная по (run_id, repo, stage), позволяет возобновлять любой этап.
  • Слепота к межрепозиторным связям. Уязвимость в библиотеке проявляется только там, где её используют. Без трассировки зависимостей такие баги остаются незамеченными.
Совет: настоящий минимальный харнесс — это только Recon, Hunt и Validate, записанные в базу, плюс валидатор, который не может заводить собственные находки. Кросс-репозиторную трассировку и дедупликацию можно добавить позже, когда без них станет невыносимо.

Две стадии: открытие и триаж

Вся система разбита на два независимых контура. Первый — Vulnerability Discovery Harness (VDH), движок обнаружения, который сканирует код и выдаёт сырые кандидаты. Второй — Vulnerability Validation System (VVS), куда попадают находки из нескольких харнессов.

Главный архитектурный трюк — разные модели на разных стадиях. VDH работает на одной модели, VVS — на другой. Так Model B оценивает вывод Model A с другими весами и другими обучающими данными, словно независимый адвокат дьявола. Это не просто безопасность: провайдеры моделей меняют температуру, кэширование и бюджеты инференса даже в рамках одной версии, а харнесс умеет поглощать эту волатильность, не ломаясь.

VDH: как устроен конвейер обнаружения ИИ-харнесса

VDH состоит из восьми стадий. Первые три — разведка, охота и валидация. Остальные пять работают как конвейер «производитель—потребитель»: пока идёт первичный поиск, Gapfill, Feedback и Trace порождают новые задачи, Dedup сворачивает дубли, и цикл продолжает потреблять очередь.

  • Recon. Три параллельных агента-разведчика строят architecture.md и пишут собственную таксономию атак под конкретный репозиторий.
  • Hunt. Охотники атакуют код по классам угроз. Они компилируют фрагменты, запускают бинарники и используют песочницу на базе unshare.
  • Validate. Детерминированный код проверяет схему и пути, затем изолированный агент пытается опровергнуть находку.
  • Gapfill. Генерирует новые задачи охоты для недостаточно покрытых ячеек «область × класс атаки».
  • Dedup. Детерминированный код + агент кластеризуют находки по корневой причине в реальном времени.
  • Trace. Трассирует граф зависимостей и порождает задачи в потребляющих репозиториях.
  • Feedback. Переписывает промпты в очереди на основе провалов валидации, поверхностных прогонов (shallow runs) и повторных промахов.
  • Report. Рендерит человекочитаемый отчёт; здесь модель не нужна.

Динамическое моделирование угроз

Recon пишет модель угроз самостоятельно, а не получает её сверху. Помимо десяти встроенных классов атак (инъекции, повреждение памяти, парсинг протоколов, тайминговые side-channel и другие), агент может изобрести собственные классы, специфичные для кодовой базы, с собственной методологией. Это делает охоту точнее, чем любой универсальный чек-лист.

Охотники выходят за рамки чтения кода и переходят к активному выполнению. Они компилируют фрагменты, собирают мини-версии и атакуют их. Качество сильно выросло, когда охотникам дали песочницу на базе системного вызова unshare (изолирует пространства имён Linux), в которой можно падать. Если харнесс сам бежит внутри Docker, песочнице нужны флаги seccomp=unconfined (отключает фильтр системных вызовов) и apparmor=unconfined (отключает профиль мандатного доступа), иначе она молча не запустится.

Братские форки и список пожеланий

Два механизма дают охотникам автономию, не позволяя сбиться с курса. Братское форкание: если охотник натыкается на интересный путь вне текущей области, он создаёт «брата» с точным структурным заданием. По флоту это даёт 9–20% задач в зависимости от модели.

Список пожеланий — центральный список запросов на инструменты и ресурсы. Охотник или валидатор может написать: «мне нужна виртуальную машину на FreeBSD, чтобы подтвердить сквозной PoC». Система автоматически перезапускает задачу, когда человек предоставит зависимость. Список пожеланий уже записывался 25 472 раза за 128 репозиториев.

Кросс-репозиторная трассировка

После первичной очистки Tracer проверяет, как компоненты связаны между собой. Он ищет путь: может ли атакующий снаружи доставить вредоносный ввод до уязвимой части системы? Если да — автоматически порождает новые задачи охоты в потребляющем репозитории. Для этого нужен единый кросс-репозиторный индекс символов и точный граф зависимостей.

Масштабный запуск по флоту выявил два урока. Во-первых, дедупликация — отдельная большая задача. Простое сравнение строк или путей не работает: два сложных логических бага могут быть одним корневым багом, и это требует рассуждений, для которых пришлось выделить отдельных Dedup-агентов. Во-вторых, статический анализ вроде Semgrep оказался не востребован: охотники обращались к нему ноль раз за месяц. Зато список пожеланий стал самым используемым инструментом. Стоит следить за тем, что агенты реально используют, а не за тем, что кажется полезным архитектору.

Как не превратиться в генератор мусора

Без жёстких контролей агенты будут читать собственные находки. Они могут подправить исходник, чтобы эксплойт сработал, написать тавтологический тест вроде «exec() выполняет код, значит критическая уязвимость» или построить эксплойт, который работает, но не доказывает ничего из-за неверной модели угроз.

В Cloudflare ввели жёсткие правила. Охотник обязан сформулировать модель угрозы до того, как завести находку: кто атакующий, какую границу доверия пересекает уязвимость, какое допущение ломает. Порядок полей в выходной схеме принудительно требует этого и отсекает пустые находки вроде «если у пользователя есть право записи в БД, он может записать в БД».

  • Каждая подтверждённая находка сопровождается рабочим PoC в виде теста против неизменённой кодовой базы.
  • Каждая находка должна включать предложенный патч в виде рабочего git diff.
  • Детерминированный валидатор проверяет, что указанные файлы и пути существуют, а патч и тест парсятся.
  • Валидатор не может заводить собственные находки; его единственная работа — агрессивно опровергать теорию охотника.

Cloudflare не заявляет о доле ложноотрицательных срабатываний: невозможно знать все баги в кодовой базе. Вместо этого они отслеживают, находят ли повторные прогоны новые баги и растёт ли покрытие областей атак (area × attack-class). Это прокси-метрика, но она достаточно хороша для измерения эффективности.

VVS: триаж, который превращает шум в работу

Находка из харнесса — только начало. В общий VVS вливаются находки из разных источников; на момент публикации там было 13 841 находка по 145 репозиториям. Триаж разбит на три работы: Dedup, Judgment и Fixing.

  • Dedup. Детерминированный код строит инвертированные индексы по файлам, функциям, границам доверия и редким токенам, чтобы сократить список кандидатов. Затем Dedup-агент решает, не закрывается ли несколько находок одним патчем. Стабильные межпрогоновые ключи возобновляют старые записи вместо создания новых.
  • Judgment. Агент собирает контекст из продакшена: wiki, Jira, git, конфиги. Он проверяет, воспроизводится ли баг на последнем main, доступен ли путь извне, и кто владелец репозитория. Результат — разделение на «эксплуатируется сейчас», «реальный, но латентный» и «заведён не в тот компонент».
  • Fixing. Fixer переписывает патч и тесты в стиле репозитория, накладывает diff и запускает таргетированные тесты. Чистый переход fail→pass — единственный случай автоматического cleanup. Если пост-патч тест падает или находит регрессию, коммит блокируется. Fixer никогда не мержит сам: всегда нужен человек.

Человек в контуре — не декорация. Именно он проводит сухой прогон (предварительный запуск без применения изменений) и подписывает изменение, создавая прозрачный аудиторский след для соответствия требованиям. Без этого модель охотно починит баг и тихо сломает соседнюю фичу или добавит десяток новых.

Сколько это стоит и как понять, что работает

Большая часть бюджета уходит на стадию Hunt. Поэтому Gapfill становится рычагом соотношения цена/покрытие: каждый дополнительный проход стоит примерно вдвое меньше первичной охоты. Cloudflare бюджетирует не на прогон, а на репозиторий, с жёстким лимитом задач на репо и пулом из 50–200 воркеров. Так деньги тратятся там, где находятся баги, а не на «чистые» репозитории.

Полное сканирование сложного репозитория может занять несколько часов; худший прогон длился чуть более 14 часов. Поэтому большие сканы — это периодическая зачистка бэклога, а не проверка на каждый PR. Для CI/CD подходят более дешёвые и маленькие харнессы.

Цифры фильтрации

  • VDH выпустил 20 799 сырых кандидатов.
  • После независимой валидации осталось около 12 057 находок.
  • В VVS, объединившись с находками из другого харнесса, общий пул вырос до 13 841.
  • Dedup-агент свернул 5 442 дубля.
  • 1 154 были отмечены как «не тот репозиторий» или «низкий риск» и возвращены в систему для повторной обработки там, где это уместно.
  • В итоге 7 245 находок, по которым можно действовать, ушли инженерным командам.

Ещё один пример: для стандартного репозитория примерно на 30 000 строк кода система выдаёт около 100 начальных находок за 3–4 часа, затем в течение 3 часов сжимает их до 80 уникальных багов, а Fixer обрабатывает их со средней скоростью 5 минут на баг. Весь цикл «найти → валидировать → дедуплицировать → открыть PR» занимает примерно 14 часов.

Распространение патчей

80 патчей за раз в прод не выкатить. Cloudflare использует многоуровневый выкат: критические, высокие и эксплуатируемые извне баги (в среднем 10 из 80) уходят на ускоренное ревью и закрываются в продакшене за 5 дней. Оставшиеся латентные риски и мелкие аномалии конфигурации раскатываются в течение 15–20 дней, чтобы не ломать платформу.

По мнению команды Project Glasswing, будущее агентных рабочих процессов не в отдельных моделях, промптах или односессионных запусках. Модели стоит рассматривать как взаимозаменяемые компоненты, а архитектура должна поглощать их волатильность.
Команда Project GlasswingCloudflare

Часто задаваемые вопросы

Часто задаваемые вопросы
1
Чем харнесс отличается от кодинг-агента?

Агент держит одну гипотезу в одной сессии. Харнесс запускает сотни независимых расследований, сохраняет состояние в базе, убирает дубли и связывает находки между репозиториями. Это оркестрация, а не замена модели.

2
Почему важно использовать разные модели на VDH и VVS?

Разные модели имеют разные веса и обучающие данные. Когда Model B оценивает вывод Model A, это эквивалент независимого адвоката дьявола. Кроме того, такая схема не привязывает вас к одному провайдеру.

3
Что такое Братское форкание и Список пожеланий?

Братское форкание позволяет охотнику отделить интересный, но не по теме путь в отдельного «брата» с точным заданием. Список пожеланий — центральный список запросов на ресурсы и инструменты, например виртуальную машину на FreeBSD для проверки PoC.

4
Как Cloudflare борется с ложными находками?

Охотник обязан сформулировать модель угрозы, предъявить рабочий PoC в виде теста против неизменённого кода и приложить патч. Валидатор агрессивно пытается опровергнуть находку и не может заводить собственные.

5
Сколько стоит такая система?

Основные затраты — стадия Hunt. Cloudflare бюджетирует на репозиторий, а не на прогон, с лимитом задач и пулом 50–200 воркеров. Полное сканирование сложного репозитория может занять более 14 часов, поэтому большие прогоны делают периодически, а не на каждый PR.

Выводы

Cloudflare показывает, что выигрыш не в том, чтобы натравить самую большую модель на код, а в том, чтобы построить модельно-независимую оркестрацию, которая не привязана к конкретному провайдеру. VDH ищет, VVS проверяет, валидаторы опровергают, люди подписывают.

Для российских команд это означает: не нужно ждать доступа к конкретной западной модели. Идея ИИ-харнесса переживёт смену лидеров рынка и ограничительные меры, потому что главное — выстроить конвейер с чёткими границами доверия, человеком в контуре и метриками фильтрации, а не метриками «нашли столько-то багов». Этот подход близок к концепции DevSecOps: безопасность встраивается в процесс разработки, а не навешивается в конце.

Компания выложила исходный security-audit skill на GitHub: cloudflare/security-audit. Это не сам харнесс, но рабочая отправная точка. Если хотите развивать тему дальше, полезно почитать про автоматизацию безопасности с помощью DevSecOps и ИИ и про SCA-анализаторы, которые решают смежную задачу в сторонних зависимостях.

Источники

Build your own vulnerability harness — Cloudflare Blog, 18 июня 2026.