Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
seclab-taskflows-fuzzing — Управляемый LLM конвейер фаззинга на базе GitHub Security Lab Taskflow Agent | Kitploit
Инструменты/GitHubGitHub/githubsecuritylab/seclab-taskflows-fuzzing
Статический анализСканеры уязвимостейДинамический анализ (песочница)Анализ уязвимостейАнализ КодаСкриптинг и автоматизацияФаззингАнализ вредоносных программУтилиты и фреймворки
Безопасность ИИ
GitHubgithubsecuritylab/seclab-taskflows-fuzzing

seclab-taskflows-fuzzing

Управляемый LLM конвейер фаззинга на базе GitHub Security Lab Taskflow Agent

Репозиторий
1294 дней назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

Seclab Taskflows Fuzzing

Управляемый LLM конвейер фаззинга в стиле OSS-Fuzz для нативных проектов на C/C++. AFL++ для выполнения, clang+lcov для покрытия, LLM-агент для написания харнессов, решений на основе обратной связи по покрытию, триажа и отчётности.

  • Полностью автономный: дайте ему репозиторий GitHub, и он сделает всё — от определения цели до отчётов об уязвимостях.
  • Техники в стиле OSS-Fuzz: мутаторы/словари для каждого формата, структурно-осознанное сращивание токенов, улучшение харнессов на основе покрытия.
  • Формирует машиночитаемые отчёты о крашах с вердиктами об эксплуатируемости и предлагаемыми патчами.
  • Живая HTML-панель для мониторинга кампании в реальном времени.
  • Написан на Python (taskflows/toolboxes/configs) с генерацией харнессов на C для AFL++.
  • Статус: Активная разработка.

Предыстория

Этот репозиторий содержит таскфлоу фаззинга для GitHub Security Lab Taskflow Agent. Он зависит от сопутствующего репозитория seclab-taskflows для нескольких общих строительных блоков (таскфлоу fetch_source_code, тулбоксы local_file_viewer / gh_file_viewer и стандартный model_config) — они устанавливаются автоматически как зависимость Python.

Вклад приветствуется! См. CONTRIBUTING.md для рекомендаций.

Требования

  • Python 3.11+
  • Окружение Linux (или Codespace) с доступом к apt
  • AFL++, clang, lcov, ctags, cscope, graphviz (автоматически устанавливаются конвейером при отсутствии)
  • Git и GitHub CLI (gh)

Установка```bash

pip install git+https://github.com/GitHubSecurityLab/seclab-taskflows-fuzzing

root@kitploit:~
Это подтягивает `seclab-taskflow-agent` и `seclab-taskflows` (родительский)
транзитивно, поэтому каждая точечная ссылка вида
`seclab_taskflows.taskflows.audit.*`,
`seclab_taskflows.toolboxes.local_file_viewer`,
`seclab_taskflows.toolboxes.gh_file_viewer` и
`seclab_taskflows.configs.model_config` разрешается из родительского
дистрибутива во время выполнения.

---

## Содержание

1. [Что это такое](#what-this-is)
2. [Быстрый старт](#quick-start)
3. [Архитектура](#architecture)
4. [Пайплайн, этап за этапом](#the-pipeline-stage-by-stage)
5. [Цикл обратной связи по покрытию](#the-coverage-feedback-loop)
6. [Структурно-осведомлённый фаззинг](#structure-aware-fuzzing)
7. [Постоянный корпус между итерациями и кампаниями](#persistent-corpus-across-iterations-and-campaigns)
8. [Триаж и отчёты об уязвимостях](#triage-and-vulnerability-reports)
9. [Живая панель мониторинга](#live-dashboard)
10. [Выходные файлы](#output-files)
11. [Схема базы данных](#database-schema)
12. [Инструменты MCP (словарь агента)](#mcp-tools-the-agents-vocabulary)
13. [Настраиваемые параметры (переменные окружения)](#tunable-knobs-environment-variables)
14. [Расширение пайплайна](#extending-the-pipeline)
15. [Бенчмарк-проекты и результаты](#benchmark-projects-and-results)
16. [Ограничения и подводные камни](#limitations-and-gotchas)
17. [Предупреждение о безопасности](#security-warning)
18. [Разработка: тестирование, линтинг, участие](#development-testing-linting-contributing)
19. [Глоссарий](#glossary)

---

## Что это такое

Этот taskflow представляет собой полностью автономный пайплайн фаззинга. Получив GitHub-репозиторий
нативного проекта на C/C++, он:

1. установит AFL++ + clang/llvm/lcov + ctags/cscope/graphviz, если их нет,
2. получит исходный код,
3. определит кандидатов в цели фаззинга (парсеры, декодеры, валидаторы, …),
4. проанализирует систему сборки,
5. напишет одного или нескольких кандидатов в harness'ы на каждую цель, соберёт каждого как
   AFL-инструментированный `.afl` бинарник и как coverage-инструментированный `.cov` бинарник,
6. (опционально) отберёт кандидатов по 60-секундному покрытию и оставит лучших,
7. запустит цикл фаззинг/покрытие/улучшение с удвоением временных бюджетов,
8. проведёт триаж каждого краша, подтвердит, что ранее известные краши всё ещё воспроизводятся, и
   напишет по каждому крашу markdown-отчёт об уязвимости с вердиктами, эксплуатируемостью,
   предлагаемыми патчами и набросками регрессионных тестов,
9. построит граф вызовов в стиле Fuzz-Introspector + отчёт о нетронутых API для
   следующей кампании,
10. опубликует всё на живой HTML-панели мониторинга.

Пайплайн **в духе OSS-Fuzz**: он использует многие из тех же
техник (мутаторы и словари для каждого формата, структурно-осведомлённое сращивание токенов, улучшения harness'ов на основе покрытия, машиночитаемые отчёты,
дедуплицированные краши с хешированием стеков), но он гораздо меньше и самодостаточен.

---

## Быстрый старт```bash
# Inside the codespace (or a host with python + git available):
./scripts/fuzzing/run_fuzzing.sh tukaani-project/xz

Это весь интерфейс. Скрипт автономен; при первом запуске он установит AFL++, а затем будет управлять остальным рабочим процессом. Выходные файлы записываются в ~/.local/share/seclab-taskflow-agent/seclab-taskflows/.

Панель управления автоматически запускается в фоновом режиме; в Codespace порт 8765 автоматически перенаправляется — откройте его в любом браузере, чтобы наблюдать за ходом выполнения в реальном времени.

Для быстрой проверки используйте небольшую цель:```bash ./scripts/fuzzing/run_fuzzing.sh DaveGamble/cJSON

root@kitploit:~
## Архитектура

Три слоя, сверху вниз:```
┌────────────────────────────────────────────────────────────────────┐
│  scripts/fuzzing/run_fuzzing.sh                                    │
│      shell driver; chains the taskflow stages with `set +e`        │
└────────────────────┬───────────────────────────────────────────────┘
                     │
                     ▼
┌────────────────────────────────────────────────────────────────────┐
│  src/seclab_taskflows/taskflows/fuzzing/*.yaml                     │
│      LLM agent prompts; one YAML per pipeline stage                │
└────────────────────┬───────────────────────────────────────────────┘
                     │  (calls MCP tools)
                     ▼
┌────────────────────────────────────────────────────────────────────┐
│  src/seclab_taskflows/mcp_servers/                                 │
│   ├ fuzz_context.py    persistence (SQLite via SQLAlchemy)         │
│   └ fuzz_runner.py     subprocess wrappers (AFL, clang, lcov, ...) │
│                                                                    │
│  scripts/fuzzing/dashboard.py                                      │
│   read-only HTML view of fuzz_context.db                           │
└────────────────────────────────────────────────────────────────────┘

Ключевые правила проектирования:

  • Никакого глобального состояния в инструментах MCP. Каждая функция инструмента принимает явные аргументы; постоянное состояние хранится в fuzz_context.db.
  • Решения принимают LLM-агенты, выполнение — инструменты MCP. Агент решает, что фаззить, какой harness писать, какой пробел искать дальше; инструменты MCP лишь предоставляют run_afl_for, compile_harness, store_crash и т. д.
  • Идемпотентность везде, где это дёшево. Повторный запуск пайплайна для того же репозитория выполняет upsert целей/harness-ов/запусков, а не дублирует их. Именно это обеспечивает работу постоянного корпуса и переноса между кампаниями.
  • Два бинарника на каждый harness. Инструментация рёбер AFL не подходит для человекочитаемых отчётов о покрытии, поэтому каждый harness собирается дважды: один раз с afl-clang-lto -fsanitize=address,undefined (бинарник .afl) и один раз с clang -fprofile-instr-generate -fcoverage-mapping (бинарник .cov). Бинарник .afl фаззит; бинарник .cov воспроизводит очередь AFL, чтобы получить реальное покрытие строк/функций/ветвей исходного кода.

Пайплайн, этап за этапом

#ЭтапTaskflow YAML
1Установка AFL++ + инструментарияscripts/fuzzing/install_afl.sh
2Получение исходного кодаseclab_taskflows.taskflows.audit.fetch_source_code
3Определение целей фаззингаseclab_taskflows_fuzzing.taskflows.fuzzing.identify_fuzz_targets
4Анализ системы сборкиseclab_taskflows_fuzzing.taskflows.fuzzing.analyze_build_system
5aНаписание начальных harness-ов (×N кандидатов, если запрошено)seclab_taskflows_fuzzing.taskflows.fuzzing.write_initial_harnesses
5bСборка harness-ов (AFL + покрытие)seclab_taskflows_fuzzing.taskflows.fuzzing.build_harnesses
5cОтбор кандидатов (когда HARNESS_CANDIDATES > 1)seclab_taskflows_fuzzing.taskflows.fuzzing.qualify_harnesses
6Цикл фаззинга/покрытия/улучшения (×N итераций)seclab_taskflows_fuzzing.taskflows.fuzzing.fuzz_iteration
7Триаж крашейseclab_taskflows_fuzzing.taskflows.fuzzing.triage_crashes
8Подтверждение, что ранее известные краши всё ещё воспроизводятсяseclab_taskflows_fuzzing.taskflows.fuzzing.confirm_fixed_crashes
9Построение графа вызовов + отчёт о незатронутых APIseclab_taskflows_fuzzing.taskflows.fuzzing.analyze_call_graph
10Написание отчётов об уязвимостях по каждому крашуseclab_taskflows_fuzzing.taskflows.fuzzing.write_vuln_reports
11Написание отчёта о кампанииseclab_taskflows_fuzzing.taskflows.fuzzing.write_report

Каждый этап — это самодостаточный taskflow YAML, который агент выполняет от начала до конца. Этапы взаимодействуют исключительно через базу данных SQLite в fuzz_context.db — никакой передачи данных в памяти нет.


Цикл обратной связи по покрытию

Это сердце пайплайна. Бюджеты времени удваиваются на каждой итерации:``` 30s → 60s → 120s → 240s → 480s → 960s (≈ 32 min/target)

root@kitploit:~
На каждой итерации, для каждого харнесса агент:

1. Запрашивает `get_persistent_corpus_dir(harness_id)` для получения стабильного
   каталога корпуса этого харнесса.
2. Вызывает `run_afl_for(afl_binary_path, seed_dir=<persistent corpus>,
   output_dir=<run dir>, seconds=<budget>, dictionary=<auto.dict>)`.
3. Вызывает `run_coverage(cov_binary_path, inputs_dir=<run>/default/queue,
   output_dir=<run>/coverage)` для создания LCOV-трейсфайла и HTML-отчёта.
4. Вызывает `store_coverage_from_lcov(run_id, lcov_path, html_path)` для сохранения
   строки `coverage_report` + строк `coverage_gap` для каждого непокрытого элемента.
5. Вызывает `fold_queue_into_persistent_corpus(...)` для слияния очереди итерации
   AFL в постоянный корпус и запускает `cmin` для ограничения размера.
6. Читает `get_coverage_summary` + `get_coverage_gaps`, затем либо:
   - добавляет новое зерно (с тегом `coverage_feedback`) для достижения непокрытой
     ветви,
   - редактирует исходный код харнесса для вызова дополнительного API,
   - вызывает `enrich_dictionary_from_uncovered(...)` для автоматического добавления
     словарных записей для магических констант, необходимых AFL для прохождения
     проверки, либо
   - пропускает пробел (холодный путь ошибки / код вендора).
7. Вызывает `store_iteration_note(repo, iteration_number, harness_id, note=<одна
   строка с итогом>)`, чтобы временная шкала итераций на дашборде отслеживала, что
   изменилось.

**Обнаружение плато.** Цикл завершается досрочно, как только две последовательные
итерации обе дали прирост < `FUZZ_PLATEAU_THRESHOLD_PCT` (по умолчанию `1.0`)
абсолютных процентных пунктов покрытия строк.

---

## Структурно-осведомлённый фаззинг

Три взаимодополняющих механизма позволяют получать более сильные входные данные,
чем чистая побайтовая мутация.

### 1. Словари для каждого формата + пользовательские мутаторы

Для целей, чей `input_kind` соответствует известному формату, taskflow поставляет
готовые словари и исходные файлы `LLVMFuzzerCustomMutator` на C:

| Формат | Словарь | Мутатор | Примечания |
|--------|------------|---------|-------|
| `json` | `json.dict` | `json_mutator.c` | Сплайсинг токенов, дублирование/удаление сбалансированных скобок, смена типа |
| `xml` | `xml.dict` | `xml_mutator.c` | Теги, сущности, DTD, токены billion-laughs |
| `regex` | `regex.dict` | `regex_mutator.c` | Якоря, классы, квантификаторы, реальные ReDoS-паттерны |
| `binary_tlv` | _(нет)_ | `binary_tlv_mutator.c` | Записи с префиксом длины: переполнение длины / дублирование / удаление |
| `png` | `png.dict` | _(переиспользует binary_tlv)_ | Словарь PNG + мутатор binary_tlv |

Они подхватываются автоматически функциями `write_initial_harnesses` (словарь
копируется рядом с зёрнами) и `build_harnesses` (мутатор линкуется в бинарник AFL).
Каждый мутатор делегирует 50% мутаций стандартному побайтовому мутатору AFL, чтобы
не потерять рандомизацию движка.

Чтобы добавить новый формат: поместите `<name>.dict` и/или `<name>_mutator.c` в
`src/seclab_taskflows/dictionaries/`, затем зарегистрируйте его в карте
`_FORMAT_ASSETS` в конце `fuzz_runner.py`.

### 2. Осведомлённый об исходниках (проектно-специфичный) умный мутатор

Для незнакомых форматов или когда нужны более сильные проектно-специфичные токены,
`generate_smart_mutator` сканирует собственные файлы `.c`/`.h` целевого репозитория
и генерирует C-файл `LLVMFuzzerCustomMutator`, чьи словари сплайсинга извлекаются из:

- строковых литералов с ≥3 буквенными символами (после фильтрации шума
  компилятора/лицензий, путей, заголовков, asm-ограничений, спецификаторов формата),
- 32-битных числовых констант из `#define`, `case` и `enum` (после фильтрации
  общего шума малых целых, такого как 0, 1, 256, 0xff…).

Доступны три фокуса:

| Фокус | Что сплайсится | Когда использовать |
|-------|-----------------|-------------|
| `strings` | Только строковые литералы проекта | Текстовые форматы (JSON, XML, YAML, CSV) |
| `constants` | Только 32-битные числовые магические значения | Бинарные протоколы, заголовки с магическими числами |
| `combined` | Оба | По умолчанию; обычно лучший |

Сочетайте `generate_smart_mutators(...)` (во множественном числе) с
`HARNESS_CANDIDATES >= 3`, чтобы каждый фокус стал кандидатом-харнессом в
квалификационном раунде.

### 3. Проектно-осведомлённый словарь AFL + обогащение на основе покрытия

Два взаимодополняющих инструмента создают и развивают словарь AFL `-x` по мере
продвижения кампании:

- **`generate_project_dictionary(source_root, output_path)`** — запускается один раз
  перед итерацией 1, статически извлекает тот же набор исходных токенов, что
  используется умным мутатором, и записывает его как словарь AFL. Числовые константы
  выводятся в ОБОИХ порядках байтов, чтобы фаззер мог удовлетворить
  `memcmp(x, &magic, 4)` независимо от порядка байтов хоста.

- **`enrich_dictionary_from_uncovered(source_root, dictionary_path,
  uncovered_locations)`** — запускается после шага покрытия каждой итерации,
  сканирует окружающий исходный код на предмет условных проверок
  (`strncmp/memcmp/strstr`, `case 0xN:`, `== 0xN`, `== 'X'`) рядом с
  непокрытыми строками и ДОБАВЛЯЕТ любые новые токены в словарь. Идемпотентен:
  никогда не добавляет повторно уже присутствующую запись.

### 4. Операция сплайсинга корпуса

Когда в `generate_smart_mutator` передаётся `corpus_dir`, сгенерированный C также
получает оператор сплайсинга корпуса: при первом вызове он загружает до 64 файлов
из этого каталога (с ограничением 4 КиБ каждый), и с этого момента может
сплайсить случайные подобласти этих файлов в мутируемый вход. Это даёт мутатору
оператор в стиле рекомбинации, который стандартный havoc AFL выполняет плохо.
Сочетайте с `get_persistent_corpus_dir(...)`, чтобы библиотека сплайсинга
представляла собой «ремикс того, что AFL уже обнаружил».

---

## Постоянный корпус между итерациями и кампаниями

У каждого харнесса есть стабильный каталог корпуса по пути:```
<workspace>/corpus/harness_<id>/

Это то, что fuzz_iteration использует как seed_dir для run_afl_for (а не <harness>/seeds). В конце каждой итерации fold_queue_into_persistent_corpus(...) объединяет очередь итерации AFL в этот каталог и запускает afl-cmin, чтобы держать его в разумных пределах.

Результат: вчерашняя очередь переносится в сегодняшний запуск И между повторными запусками одного и того же проекта. Остановка и перезапуск кампании не теряет прогресс.


Триаж и отчёты об уязвимостях

После завершения цикла fuzz/coverage/improve автоматически запускаются три этапа:

1. triage_crashes

Для каждого файла краша в <run>/default/crashes/:

  • afl-tmin для минимизации входных данных,
  • replay_under_asan для захвата трассировки стека и stack_top_hash (top-N нормализованных кадров; шаблоны, встроенные пространства имён libcxx, анонимные пространства имён и числовые суффиксы LTO удаляются, чтобы семантически идентичные краши хешировались одинаково),
  • дедупликация по хешу, сохранение строки crash с классификацией класса бага + примечанием об уверенности (high / medium / low).

2. confirm_fixed_crashes

Повторно воспроизводит каждый ранее классифицированный краш (чей вердикт ещё не fixed/duplicate/non_reproducible) через текущий бинарник AFL+ASan. Если он больше не крашится, помечает verdict="fixed". Полезно при повторном запуске кампании против проекта, в который с момента прошлой кампании были внесены исправления в upstream.

3. write_vuln_reports

Для каждого уникального краша агент читает исходный код харнесса + исходный код функции, вызывающей краш, проходит по цепочке вызовов от публичного API, затем присваивает один из десяти вердиктов в стиле OSS-Fuzz и пишет markdown-отчёт об уязвимости:

ВердиктЗначение
vulnerabilityРеальная, эксплуатируемая через публичный API
library_hardeningРеальный баг, но нет реалистичного пути через публичный API; библиотека всё равно должна защищаться
harness_bugБаг в нашем харнессе, а не в библиотеке
non_reproducibleВоспроизведение не воспроизводит краш на минимизированных входных данных
oomOut-of-memory; уязвимость только если контролируемый атакующим размер неограничен
timeoutDoS через алгоритмический взрыв
assertion_failureСработал assert(); значимость для безопасности варьируется
fixedУстанавливается confirm_fixed_crashes: входные данные больше не воспроизводят краш
duplicateТа же первопричина, что и у другого краша с другим хешем стека
needs_investigationНе удалось определить; помечено для ручной проверки

Каждый отчёт об уязвимости включает:

  • Вердикт + класс бага + CWE + серьёзность + уверенность
  • Анализ первопричины со ссылками file:line
  • Достижимость из публичного API (конкретная цепочка вызовов)
  • Оценка эксплуатируемости (чтение vs. запись, контроль атакующего, меры защиты)
  • Предлагаемое исправление в виде unified diff (помечено "review required")
  • Набросок регрессионного теста

Живой дашборд

Дашборд запускается автоматически в фоне скриптом run_fuzzing.sh. Отключается через FUZZ_NO_DASHBOARD=1; порт переопределяется через FUZZ_DASHBOARD_PORT (по умолчанию 8765).

В Codespace порт 8765 автоматически перенаправляется — откройте перенаправленный URL в любом браузере. Страница автообновляется каждые 5 с и показывает:

  • Чипы сводки вердиктов — количество по каждой категории вердиктов, всего запусков, путей, общее число выполнений, крашей
  • Живой индикатор пульса "running" — по репозиторию и по харнессу с активным fuzz_run
  • Таблица тренда покрытия с встроенными SVG-спарклайнами и столбцом дельты по итерациям
  • Граф вызовов и незатронутая поверхность API — снимок Fuzz-Introspector-lite
  • Таблица крашей — отсортирована по вердикту (vulnerability первым), со ссылками на каждый отчёт об уязвимости и минимизированные входные данные
  • Тепловая карта крашей — сетка количества крашей по (харнесс × итерация), непрозрачность масштабируется с количеством
  • Хронология итераций — хронологическая лента однострочных заметок, написанных агентом, описывающих, что изменилось на каждой итерации
  • Топ непокрытых функций — по умолчанию свёрнуто

JSON API

Дашборд также предоставляет крошечный JSON API только для чтения для скриптов:```bash

All known repos

curl http://127.0.0.1:8765/api/json

Per-repo: harnesses, per-iteration coverage, crashes with verdicts

curl 'http://127.0.0.1:8765/api/json?repo=kkos/oniguruma' | jq .

root@kitploit:~
---

## Выходные файлы

Все находятся в `~/.local/share/seclab-taskflow-agent/seclab-taskflows/`.

| Путь | Содержимое |
|------|----------|
| `fuzz_context/fuzz_context.db` | SQLite — цели, харнессы, запуски, покрытие, краши, вердикты, графы вызовов, предложения по харнессам, заметки об итерациях |
| `fuzz_runner/builds/` | Собранные бинарники `.afl` и `.cov` |
| `fuzz_runner/runs/` | Выходные каталоги AFL + файлы LCOV + HTML-отчёты о покрытии |
| `fuzz_runner/corpus/harness_<id>/` | Постоянный корпус для каждого харнесса (переносится между итерациями и кампаниями) |
| `fuzz_runner/repo/<owner>__<repo>/REPORT.md` | Markdown-сводка кампании, краши сгруппированы по вердикту |
| `fuzz_runner/repo/<owner>__<repo>/vuln_<crash_id>.md` | Markdown-отчёт об уязвимости для каждого краша |
| `fuzz_runner/repo/<owner>__<repo>/call_graph.{dot,svg,md}` | Статический граф вызовов + наложение достигнутых/недостигнутых |

---

## Схема базы данных

Таблицы в `fuzz_context.db` (SQLite через SQLAlchemy):

| Таблица | Интересующие столбцы |
|-------|--------------------|
| `fuzz_target` | `repo, file, function, signature, input_kind` |
| `harness` | `target_id, repo, harness_path, afl_binary_path, cov_binary_path, build_status, version, sanitizers` |
| `seed_corpus` | `target_id, source, path, bytes_count, added_in_iteration` |
| `fuzz_run` | `harness_id, iteration_number, exec_per_sec, paths_total, crashes_count, status, output_dir, started_at, ended_at` |
| `coverage_report` | `run_id, lines_total, lines_hit, line_pct, fns_*, branches_*, lcov_path, html_path` |
| `coverage_gap` | `report_id, file, function, line, kind, reason_hint` |
| `crash` | `run_id, input_blob_path, minimized_path, stack_top_hash, sanitizer_output, verdict, bug_class, cwe, severity, vuln_report_path, reproducer_path, classification, notes` |
| `call_graph` | `repo, target_id, dot_path, svg_path, functions_total, functions_in_graph, functions_reached, functions_unreached, untouched_surface_json` |
| `harness_suggestion` | `repo, function_name, file, rationale, input_kind, priority` |
| `iteration_note` | `repo, harness_id, iteration_number, note, created_at` |

Миграции схемы находятся в `_migrate()` в `fuzz_context.py`. Новые ТАБЛИЦЫ
автоматически создаются через `Base.metadata.create_all()`; только для новых
СТОЛБЦОВ требуется `ALTER TABLE` на основе PRAGMA.

---

## Инструменты MCP (словарь агента)

Агент никогда не вызывает AFL или clang напрямую — он собирает конвейер,
вызывая инструменты MCP. Полный набор, сгруппированный по назначению:

### Персистентность (`fuzz_context.py`)

- `store_fuzz_target`, `get_fuzz_targets`
- `store_harness`, `update_harness_build`, `get_harnesses`
- `store_seed`, `start_fuzz_run`, `finish_fuzz_run`, `get_fuzz_runs`
- `store_coverage_from_lcov`, `get_coverage_summary`, `get_coverage_gaps`,
  `coverage_plateau_reached`
- `store_crash`, `update_crash_verdict`, `get_crashes`,
  `get_crashes_grouped`, `suggest_severity`
- `store_call_graph`, `get_call_graphs`, `get_repo_reached_functions`
- `store_harness_suggestion`, `get_harness_suggestions`
- `store_iteration_note`, `get_iteration_notes`

### Сборка / фаззинг / покрытие (`fuzz_runner.py`)

- `check_tooling`, `workspace_paths`
- `compile_harness` — собирает бинарники `.afl` и `.cov`
- `run_afl_for`, `cmin`, `tmin`, `replay_under_asan`, `reproduce_crash`
- `run_coverage` — воспроизводит очередь AFL против бинарника `.cov`, экспортирует LCOV
- `extract_dictionary` — извлекает печатаемые строки из бинарника
- `package_reproducer` — упаковывает `.tgz` для одного краша

### Постоянный корпус (v8)

- `get_persistent_corpus_dir`, `fold_queue_into_persistent_corpus`

### Ресурсы форматов (C5)

- `list_format_assets`, `get_format_dictionary`, `write_format_mutator`

### Умный мутатор + словарь с учётом проекта

- `generate_smart_mutator`, `generate_smart_mutators`
- `generate_project_dictionary`, `enrich_dictionary_from_uncovered`

Функции инструментов декорированы `@mcp.tool()` (FastMCP). В тестах
вызывайте их через атрибут `.fn`, например
`fr.run_afl_for.fn(afl_binary_path=..., ...)`.

---

## Настраиваемые параметры (переменные окружения)

| Переменная | По умолчанию | Назначение |
|----------|---------|---------|
| `HARNESS_CANDIDATES` | `1` | Количество кандидатных харнессов, создаваемых для каждой цели. Установите 2 или 3 для конкуренции в стиле OSS-Fuzz-Gen. Этап квалификации запускает каждый в течение `QUALIFIER_SECONDS` и оставляет лучший по проценту строк. |
| `QUALIFIER_SECONDS` | `60` | Бюджет реального времени на каждого кандидата на этапе квалификации. |
| `FUZZ_PLATEAU_THRESHOLD_PCT` | `1.0` | Прирост покрытия строк (в абсолютных п.п.), ниже которого две последовательные итерации считаются плато и цикл останавливается досрочно. |
| `FUZZ_DASHBOARD_PORT` | `8765` | Порт для живого дашборда. |
| `FUZZ_NO_DASHBOARD` | (не задано) | Установите `1`, чтобы пропустить запуск дашборда. |
| `FUZZ_RUNNER_TIMEOUT` | `1200` | Таймаут подпроцесса на инструмент в `fuzz_runner` (секунды). |
| `LOCAL_SHELL_TIMEOUT` | `180` | Таймаут на команду в `local_shell` (секунды). |

Плюс стандартные переменные агента (`COPILOT_TOKEN`, `LOG_DIR`,
`FUZZ_CONTEXT_DIR`, …). Полный список см. в README в корне проекта.

---

## Расширение конвейера

### Добавление нового формата (мутатор + словарь)

1. Поместите `dictionaries/<name>.dict` (формат AFL `-x`) и/или
   `dictionaries/<name>_mutator.c` (пользовательский мутатор libFuzzer).
2. Зарегистрируйте в `_FORMAT_ASSETS` в конце `fuzz_runner.py`:   ```python
   "<name>": {
       "dictionary": "<name>.dict",
       "mutator": "<name>_mutator.c",
       "description": "Short one-liner about the format",
   },
  1. Агент подхватит его автоматически через list_format_assets().

Добавление нового инструмента MCP

  1. Добавьте функцию с декоратором @mcp.tool() в fuzz_context.py (для персистентности) или fuzz_runner.py (для работы с подпроцессами).
  2. Используйте Annotated[type, Field(description=...)] для каждого аргумента — именно описание видит LLM.
  3. Добавьте модульный тест в tests/test_fuzz_context.py / tests/test_fuzz_runner.py. Вызывайте инструмент через его атрибут .fn (соглашение FastMCP).
  4. Укажите новый инструмент в user_prompt соответствующего taskflow YAML.

Добавление нового этапа конвейера

  1. Создайте новый YAML в src/seclab_taskflows/taskflows/fuzzing/. Используйте один из существующих файлов (например, triage_crashes.yaml) как шаблон.
  2. Подключите его в scripts/fuzzing/run_fuzzing.sh между нужными двумя существующими этапами.
  3. (Необязательно) добавьте раздел дашборда для конкретного этапа в scripts/fuzzing/dashboard.py.

Миграция схемы

При добавлении новой таблицы SQL:

  • Добавьте модель SQLAlchemy в fuzz_context_models.py.
  • Больше ничего не нужно — Base.metadata.create_all() вызывается при инициализации движка и автоматически создаёт новые таблицы.

При добавлении нового СТОЛБЦА в существующую таблицу:

  • Обновите модель SQLAlchemy.
  • Добавьте блок PRAGMA table_info + ALTER TABLE ADD COLUMN в _migrate() в fuzz_context.py, чтобы старые БД обновлялись прозрачно.
  • Если столбец читается дашбордом, также обновите _migrate_if_writable() в scripts/fuzzing/dashboard.py.

Эталонные проекты и результаты

benchmark/projects.yaml содержит список эталонных проектов. Они выбраны так, чтобы полный конвейер v4+ мог выполняться от начала до конца на dev-образе codespace без вмешательства человека.

#РепозиторийЧем интересенПримечания
1tukaani-project/xzРеальная библиотека с интенсивным парсингом (liblzma); богатая цепочка фильтров + поверхность парсинга integer/VLIБазовый
2DaveGamble/cJSONНебольшой однофайловый парсер JSON на C; тривиальный CMakeБыстрая проверка конвейера
3akheron/janssonКомпактная библиотека JSON на C с документированной точкой входа json_loadb() для байтового буфераCMake; очень высокая скорость exec/sec
4libexpat/libexpatЗрелый потоковый парсер XML; множество исторических CVECMake или autotools
5kkos/onigurumaДвижок регулярных выражений; принимает шаблон атакующего + subjectAutotools; компиляция шаблона — горячий путь

Эталонные показатели полного запуска конвейера v4 на dev-образе codespace (≈32 мин на цель):

РепозиторийЦелиХарнессыЗапуски AFLКрэшиВердикты
tukaani-project/xz88480—
DaveGamble/cJSON66360—
akheron/jansson773510harness_bug, library_hardening, duplicate, needs_investigation
libexpat/libexpat33180—
kkos/oniguruma10106013vulnerability (×2 OOB read в regerror.c), library_hardening, harness_bug, non_reproducible

Нулевые результаты по крэшам для xz / cJSON / libexpat ожидаемы: эти проекты интенсивно фаззятся в upstream. Две находки, классифицированные как vulnerability, в oniguruma — это реальные чтения за границами буфера в пути кода форматирования предупреждений onig_snprintf_with_pattern (чтение одного байта за pat_end, когда шаблон заканчивается обратной косой чертой); отчёты markdown по каждому крэшу включают предлагаемые патчи.

Чтобы добавить новый эталонный проект, добавьте запись в benchmark/projects.yaml и (необязательно) задокументируйте причину в benchmark/README.md. Всё, что существующий этап analyze_build_system может собрать с флагами clang + AFL++, является разумным кандидатом. Чистые парсеры, декодеры и сериализаторы на C обычно работают лучше всего.


Ограничения и подводные камни

  • Только C / C++. AFL++ — фаззер с нативной инструментацией.
  • Зависимость от системы сборки. Проекты с нетривиальными системами сборки (кастомные правила Bazel, вендоренный libc, проприетарные инструменты сборки) могут не собраться с флагами clang/AFL. Агент помечает такие цели как BUILD_FAILED: и пропускает их.
  • Предупреждения AFL в Codespace. AFL++ требует kernel.core_pattern=core и настройки CPU governor. В Codespace они недоступны, поэтому taskflow по умолчанию экспортирует AFL_SKIP_CPUFREQ=1 и AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1. AFL печатает предупреждения, но всё равно находит крэши через обработку abort в стиле libFuzzer.
  • Ограничение моделью. Качество написания харнессов агентом ограничено пониманием целевого кода базовой моделью.
  • Склейка корпуса умного мутатора только для POSIX. Операция склейки корпуса использует <dirent.h>. Подходит для Linux/macOS; не скомпилируется на Windows.
  • Оговорка о режиме stdin. Бинарники AFL, собранные через compile_harness, используют libAFLDriver в режиме argv. Поэтому replay_under_asan и tmin по умолчанию используют stdin_input=False, так как libAFLDriver зацикливается навсегда при управлении через stdin.
  • generate_smart_mutator + generate_smart_mutators используют Python .format() — каждый литеральный { / } в шаблоне C должен быть удвоен ({{ / }}). Если вы отредактируете шаблон и начнёте видеть KeyError, вот почему.

Предупреждение о безопасности

Этот taskflow запускает afl-fuzz, clang, llvm-cov, а также произвольные команды сборки, выбранные LLM, напрямую на хосте (без контейнера). Агент, подверженный prompt injection, в принципе может делать всё, что может ваш пользователь. Запускайте только:

  • внутри одноразовых сред (GitHub Codespaces, временные ВМ и т. п.),
  • без повышенных привилегий,
  • с сетевым доступом, ограниченным тем, что нужно git, apt и системе сборки.

Инструментарий local_shell НЕ защищён запросом подтверждения — taskflow автономен и работает без участия человека, поэтому интерактивное подтверждение просто зависло бы навсегда. Каждая команда оболочки логируется в $LOG_DIR/mcp_local_shell.log для последующего анализа.


Разработка: тестирование, линтинг, участие```bash

Run the test suite (Python 3.11+ required by hatch-test envs)

hatch test

Run the linter

hatch fmt --linter --check

Auto-fix lint issues

hatch fmt --linter

Lint a single file

hatch fmt --linter --check -- src/seclab_taskflows/mcp_servers/fuzz_runner.py

root@kitploit:~
Соглашения кодовой базы (см. также `benchmark/improvements.md` для
версии этих соглашений в контексте истории кампаний):

- Используйте `os.environ.get(NAME) or "default"` вместо
  `os.environ.get(NAME, "default")`. Иначе пустые строки из подстановки
  шаблона YAML будут возвращены.
- Используйте `X | None` (PEP 604) в новых аннотациях, а не `Optional[X]`.
- Тесты вызывают MCP-инструменты через `.fn(...)`, а не через
  декорированное имя напрямую.
- Избегайте литералов `/tmp/...` в тестах — используйте pytest-фикстуру
  `tmp_path` (правило линтера `S108`).
- Все inline-импорты внутри методов тестов нуждаются в `# noqa: PLC0415`,
  если вы не можете переместить их в начало файла (например, при
  условном импорте после `pytest.skip`).
- Одно утверждение на строку для составных проверок истинности (правило
  линтера `PT018`).

Трекер улучшений (`benchmark/improvements.md`) — это постоянный
журнал того, что было добавлено в пайплайн across версий. Когда вы
добавляете существенную функцию, добавьте туда раздел с описанием того,
что изменилось, где это находится и какие тесты это защищают.

---

## Глоссарий

- **AFL++** — Грейбокс-фаззер с покрытием; здесь — движок исполнения.
- **libAFLDriver** — Статическая библиотека, позволяющая харнессам AFL++
  использовать соглашение о точке входа libFuzzer
  (`LLVMFuzzerTestOneInput`).
- **LCOV** — Отраслевой стандартный формат файла трассировки покрытия.
  Мы экспортируем в него через `llvm-cov export -format=lcov` и
  разбираем его сами.
- **`stack_top_hash`** — 16-символьный хеш верхних N нормализованных
  кадров трассировки стека ASan/UBSan. Используется для дедупликации
  крашей.
- **Постоянный корпус** — Директория для каждого харнесса по пути
  `<workspace>/corpus/harness_<id>/`, которая переносит интересные
  входные данные AFL между итерациями и повторными запусками одной и
  той же кампании.
- **Умный мутатор** — `LLVMFuzzerCustomMutator`, чьи токены для
  сплайсинга извлекаются из исходного кода самой цели
  (`generate_smart_mutator`).
- **Пользовательский мутатор (libFuzzer)** — Предоставляемая
  пользователем C-функция, вызываемая движком с полной свободой в
  отношении того, как мутировать буфер; AFL++ поддерживает тот же ABI.
- **MCP-инструмент** — Функция, декорированная FastMCP, которую может
  вызывать LLM-агент.
- **OSS-Fuzz / Fuzz-Introspector** — Инфраструктура Google для
  открытого фаззинга и сопутствующий инструмент анализа графа вызовов
  и покрытия. Некоторые функции этого taskflow (мутаторы для каждого
  формата, дедупликация по стеку, отчёт по графу вызовов и
  нетронутым API, многокандидатные харнессы) вдохновлены ими.

---

## Лицензия

Этот проект лицензирован на условиях открытой лицензии MIT. Полные
условия см. в файле [LICENSE](https://github.com/githubsecuritylab/seclab-taskflows-fuzzing/blob/main/LICENSE.txt).

## Сопровождающие

См. [CODEOWNERS](https://github.com/githubsecuritylab/seclab-taskflows-fuzzing/blob/main/CODEOWNERS) или свяжитесь с командой GitHub
Security Lab.

## Поддержка

См. [SUPPORT.md](https://github.com/githubsecuritylab/seclab-taskflows-fuzzing/blob/main/SUPPORT.md) для получения подробной информации о
том, как получить помощь по этому проекту.

## Благодарности

Этот проект построен на основе концепций и техник
[AFL++](https://github.com/AFLplusplus/AFLplusplus),
[OSS-Fuzz](https://github.com/google/oss-fuzz) и
[Fuzz-Introspector](https://github.com/ossf/fuzz-introspector).
Скачать инструмент