GitHub представил Fuzzing Taskflow — автономный конвейер для фаззинга C/C++‑проектов, построенный на базе фреймворка GitHub Security Lab Taskflow Agent. Инструмент использует агента на основе большой языковой модели, который берет на себя значительную часть ручной работы по настройке и сопровождению фаззинга.
Достаточно указать адрес репозитория на GitHub. Далее агент сам определяет точки входа, анализирует систему сборки, пишет тестовые обвязки (harnesses), запускает AFL++, читает отчёты по покрытию, улучшает обвязки, разбирает падения и формирует отчёт по каждой уязвимости — без постоянного участия разработчика.
Fuzzing Taskflow реализован как набор taskflow‑сценариев GitHub Security Lab Taskflow Agent, где LLM‑агент управляет логикой, а инструменты MCP выполняют конкретные действия. Агент решает, что фаззить, какую обвязку писать и какие пробелы в покрытии закрывать дальше, а инструменты предоставляют примитивы вроде run_afl_for или compile_harness. Вся информация хранится в SQLite‑базе fuzz_context.db, без передачи состояния между этапами в памяти.
Каждая обвязка собирается в двух вариантах: .afl‑бинарник с afl-clang-lto и санитайзерами для работы фаззера и .cov‑бинарник с флагами clang для профилирования и карт покрытия. Первый используется для фаззинга, второй — для повторного прогона очереди AFL и получения покрытия по строкам исходников и ветвлениям.
Центральная часть конвейера — автоматизация классического итеративного процесса расширения покрытия. Для каждой обвязки агент в каждом цикле запускает AFL с заданным лимитом времени, затем прогоняет очередь через .cov‑бинарник, получает отчёт по покрытию и анализирует список непокрытых ветвей. На основе этого агент выбирает одно из нескольких действий по улучшению обвязки или входных данных.
Время фаззинга на одну обвязку увеличивается по ступенчатой схеме: 30, 60, 120, 240, 480 и 960 секунд (примерно до 32 минут на цель). Короткие раунды используются в начале, когда легко быстро поднять покрытие, более длинные — позже, когда фаззеру требуется больше времени для обхода сложных проверок.
Для остановки процесса используется детекция плато: если две последовательные итерации приносят прирост меньше порога (по умолчанию 1% абсолютного строкового покрытия), цикл считается исчерпанным и переходит к следующей цели. Это ограничивает затраты вычислительных ресурсов при попытках добрать последние доли процента покрытия.
Чтобы эффективнее работать со структурированными входами (JSON, XML и другие текстовые форматы), конвейер оснащён четырьмя механизмами для подготовки «структурно осмысленных» входных данных и расширения словарей мутаций, дополняющих стандартные побайтные мутации AFL.
Во‑первых, для известных форматов предусмотрены специализированные словари и custom mutators. Для JSON, XML, регулярных выражений, PNG и бинарных TLV‑форматов есть готовые словари AFL и реализации LLVMFuzzerCustomMutator на C. Например, JSON‑мутатор занимается вставкой токенов и работой с парными скобками, XML‑мутатор учитывает теги, сущности и шаблоны billion-laughs, а мутатор для регулярок включает реальные ReDoS‑паттерны. При этом часть мутаций всё равно отдаётся стандартным байтовым операторам AFL.
Во‑вторых, для неизвестных форматов конвейер строит словарь на уровне исходного кода. Он сканирует .c и .h‑файлы цели, извлекает строковые литералы и 32‑битные числовые константы (#define, case, enum), отфильтровывает шум и использует оставшиеся значения как токены для сплайсинга. Предполагается, что значимые «магические» значения для парсера чаще всего явно заданы в исходниках.
В‑третьих, тот же набор токенов используется для генерации словаря AFL с динамическим обогащением по покрытию. Словарь создаётся до первой итерации (включая 4‑байтные константы в обеих порядках байтов). После каждого шага анализа покрытия конвейер просматривает проверки возле непокрытых строк (strncmp, memcmp, case 0xN, сравнения с символами) и добавляет новые найденные значения в словарь, направляя его к участкам кода, куда фаззер пока не добрался.
В‑четвёртых, реализован оператор corpus-splice: «умный» мутатор может подгружать файлы из корпуса и встраивать случайные подотрезки этих файлов в генерируемые входы, что даёт вид рекомбинационных мутаций, которых стандартный режим havoc у AFL выполняет хуже.
Чтобы не терять прогресс между запусками, для каждой обвязки создаётся стабильный каталог корпуса. В конце каждой итерации туда сливается очередь AFL, после чего корпус оптимизируется через afl-cmin для ограничения размера. Это позволяет использовать найденные ранее интересные входы в последующих итерациях и кампаниях без утраты накопленных результатов.
Отдельный блок посвящён разбору сбоев. После завершения цикла фаззинга запускаются три стадии. Сначала каждое падение минимизируется с помощью afl-tmin, воспроизводится под ASan для получения стека и дедуплицируется по хэшу верхней части стека (с нормализацией шаблонов, inline‑пространств имён и LTO‑суффиксов). Затем ранее известные падения прогоняются на текущих бинарниках, чтобы проверить, исправлены ли они в исходном коде.
На третьем шаге агент анализирует исходники обвязки и функции, в которых сработало падение, проходит по цепочке вызовов от публичного API и формирует отчёт в формате Markdown по каждому типу сбоя. В отчёте указывается корневая причина с привязкой к файлам и строкам, аргументация достижимости через публичный интерфейс, оценка эксплуатационности, предлагаемое исправление в виде diff и эскиз регрессионного теста.
Агент старается различать реальные уязвимости (достижимые извне через публичный API) и ошибки самих обвязок (harness_bug). При этом рекомендуемые патчи помечены как требующие обязательной проверки человеком: анализ ограничен возможностями модели и может содержать ошибки, поэтому выводы нужно рассматривать как подготовленную основу для ручного аудита.
Для наблюдения за ходом кампании конвейер публикует результаты в живой HTML‑дашборд, который автоматически поднимается на порту 8765 при запуске. В GitHub Codespaces этот порт пробрасывается автоматически, что позволяет следить за прогрессом через браузер в реальном времени.
По умолчанию Fuzzing Taskflow использует модель Claude Sonnet 5 — она прошла внутренние проверки GitHub Security Lab. При желании модель можно сменить, отредактировав файл src/seclab_taskflows_fuzzing/configs/model_config.yaml.
Важное ограничение: taskflow запускает afl-fuzz, clang и произвольные команды сборки, которые выбирает LLM‑агент, на хостовой системе без контейнера. В случае успешной атакующей подсказки агент теоретически может выполнить любые команды от имени пользователя. Разработчики GitHub рекомендуют запускать конвейер только в изолированной среде, такой как Codespaces или одноразовая виртуальная машина без повышенных привилегий.
Инициатор проекта объясняет, что цель Fuzzing Taskflow — снять узкое место в виде ручного труда эксперта, без которого фаззинг плохо масштабируется. Автоматизация рутинных задач (написание обвязок, чтение отчётов по покрытию, поиск пробелов, разбор падений) передаётся LLM‑агенту, при этом сохраняется чёткое разделение между решениями агента и инструментами, выполняющими реальные действия.
Разработчики C/C++‑проектов могут использовать Fuzzing Taskflow для первичного запуска фаззинга, если ранее его не было, или для расширения существующего покрытия и поиска новых ошибок в уже фаззенных кодовых базах. Код инструмента открыт, авторы приглашают сообщать о ошибках через issues и присылать pull‑requests.
Источник: блог GitHub Security Lab.






















