Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
seclab-taskflows-fuzzing — Um pipeline de fuzzing orientado por LLM alimentado pelo GitHub Security Lab Taskflow Agent | Kitploit
Ferramentas/GitHubGitHub/githubsecuritylab/seclab-taskflows-fuzzing
Análise EstáticaScanners de VulnerabilidadesAnálise Dinâmica (Sandboxing)Análise de VulnerabilidadesAnálise de CódigoScripting e AutomaçãoFuzzingAnálise de MalwareUtilitários e Frameworks
Segurança de IA
GitHubgithubsecuritylab/seclab-taskflows-fuzzing

seclab-taskflows-fuzzing

Um pipeline de fuzzing orientado por LLM alimentado pelo GitHub Security Lab Taskflow Agent

Ver Repositório
122há 4 diasAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

Seclab Taskflows Fuzzing

Um pipeline de fuzzing no estilo OSS-Fuzz, orientado por LLM, para projetos nativos em C/C++. AFL++ para execução, clang+lcov para cobertura, um agente LLM para escrita de harness, decisões baseadas em feedback de cobertura, triagem e relatórios.

  • Totalmente autônomo: basta fornecer um repositório do GitHub e ele cuida de tudo, desde a identificação do alvo até os relatórios de vulnerabilidade.
  • Técnicas no estilo OSS-Fuzz: mutadores/dicionários por formato, splicing de tokens ciente da estrutura, melhorias de harness orientadas por cobertura.
  • Produz relatórios de crash legíveis por máquina com veredictos de explorabilidade e patches sugeridos.
  • Painel HTML ao vivo para monitoramento de campanhas em tempo real.
  • Escrito em Python (taskflows/toolboxes/configs) com geração de harness em C para AFL++.
  • Status: Desenvolvimento ativo.

Contexto

Este repositório contém o taskflow de fuzzing para o GitHub Security Lab Taskflow Agent. Ele depende do repositório complementar seclab-taskflows para alguns blocos de construção compartilhados (taskflow fetch_source_code, toolboxes local_file_viewer / gh_file_viewer e o model_config padrão) — esses são instalados automaticamente como uma dependência Python.

Contribuições são bem-vindas! Consulte CONTRIBUTING.md para diretrizes.

Requisitos

  • Python 3.11+
  • Um ambiente Linux (ou Codespace) com acesso ao apt
  • AFL++, clang, lcov, ctags, cscope, graphviz (instalados automaticamente pelo pipeline se ausentes)
  • Git e GitHub CLI (gh)

Instalação```bash

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

root@kitploit:~
Isso traz `seclab-taskflow-agent` e `seclab-taskflows` (pai)
transitivamente, então toda referência pontuada da forma
`seclab_taskflows.taskflows.audit.*`,
`seclab_taskflows.toolboxes.local_file_viewer`,
`seclab_taskflows.toolboxes.gh_file_viewer`, e
`seclab_taskflows.configs.model_config` é resolvida a partir da distribuição
pai em tempo de execução.

---

## Índice

1. [O que é isto](#what-this-is)
2. [Início rápido](#quick-start)
3. [Arquitetura](#architecture)
4. [O pipeline, estágio por estágio](#the-pipeline-stage-by-stage)
5. [O ciclo de feedback de cobertura](#the-coverage-feedback-loop)
6. [Fuzzing ciente de estrutura](#structure-aware-fuzzing)
7. [Corpus persistente entre iterações e campanhas](#persistent-corpus-across-iterations-and-campaigns)
8. [Triagem e relatórios de vulnerabilidade](#triage-and-vulnerability-reports)
9. [Dashboard ao vivo](#live-dashboard)
10. [Arquivos de saída](#output-files)
11. [Esquema do banco de dados](#database-schema)
12. [Ferramentas MCP (o vocabulário do agente)](#mcp-tools-the-agents-vocabulary)
13. [Ajustes configuráveis (variáveis de ambiente)](#tunable-knobs-environment-variables)
14. [Estendendo o pipeline](#extending-the-pipeline)
15. [Projetos de benchmark e resultados](#benchmark-projects-and-results)
16. [Limitações e armadilhas](#limitations-and-gotchas)
17. [Aviso de segurança](#security-warning)
18. [Desenvolvimento: testes, linting, contribuição](#development-testing-linting-contributing)
19. [Glossário](#glossary)

---

## O que é isto

Este taskflow é um pipeline de fuzzing totalmente autônomo. Dado um repositório
GitHub de um projeto nativo em C/C++, ele irá:

1. instalar AFL++ + clang/llvm/lcov + ctags/cscope/graphviz se estiverem ausentes,
2. buscar o código-fonte,
3. identificar alvos de fuzzing candidatos (parsers, decodificadores, validadores, …),
4. analisar o sistema de build,
5. escrever um ou mais candidatos a harness por alvo, compilar cada um tanto como
   um binário `.afl` instrumentado com AFL quanto como um binário `.cov`
   instrumentado para cobertura,
6. (opcionalmente) qualificar candidatos por cobertura de 60 segundos e manter o melhor,
7. executar um ciclo de fuzz/cobertura/melhoria com orçamentos de tempo que dobram,
8. fazer triagem de cada crash, confirmar que crashes previamente conhecidos ainda
   se reproduzem, e escrever relatórios markdown de vulnerabilidade por crash com
   veredictos, explorabilidade, patches sugeridos e esboços de testes de regressão,
9. construir um grafo de chamadas no estilo Fuzz-Introspector + relatório de APIs
   não tocadas para a próxima campanha,
10. publicar tudo em um dashboard HTML ao vivo.

O pipeline é **no estilo OSS-Fuzz**: usa muitas das mesmas
técnicas (mutadores e dicionários por formato, splicing de tokens ciente de
estrutura, melhorias de harness guiadas por cobertura, relatórios legíveis por
máquina, crashes deduplicados por hash de pilha), mas é muito menor e
autocontido.

---

## Início rápido```bash
# Inside the codespace (or a host with python + git available):
./scripts/fuzzing/run_fuzzing.sh tukaani-project/xz

Essa é toda a interface. O script é autônomo; ele instalará o AFL++ na primeira execução e, em seguida, conduzirá o restante do fluxo de tarefas. Os arquivos de saída são gravados em ~/.local/share/seclab-taskflow-agent/seclab-taskflows/.

O dashboard é iniciado automaticamente em segundo plano; em um Codespace, a porta 8765 é redirecionada automaticamente — abra-a em qualquer navegador para acompanhar o progresso ao vivo.

Para um teste rápido de fumaça, use um alvo pequeno:```bash ./scripts/fuzzing/run_fuzzing.sh DaveGamble/cJSON

root@kitploit:~
---

## Arquitetura

Três camadas, de cima para baixo:```
┌────────────────────────────────────────────────────────────────────┐
│  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                           │
└────────────────────────────────────────────────────────────────────┘

Regras de design fundamentais:

  • Sem estado global nas ferramentas MCP. Cada função de ferramenta recebe argumentos explícitos; o estado persistente vive em fuzz_context.db.
  • Os agentes LLM são donos das decisões, as ferramentas MCP são donas da execução. O agente decide o que fuzzar, que harness escrever, que lacuna perseguir a seguir; as ferramentas MCP apenas expõem run_afl_for, compile_harness, store_crash, etc.
  • Idempotência sempre que barato. Reexecutar o pipeline contra o mesmo repositório faz upsert de targets/harnesses/runs em vez de os duplicar. É isto que faz funcionar o corpus persistente e a transferência entre campanhas.
  • Dois binários por harness. A instrumentação de arestas do AFL não é adequada para relatórios de cobertura legíveis por humanos, por isso cada harness é compilado duas vezes: uma com afl-clang-lto -fsanitize=address,undefined (o binário .afl) e outra com clang -fprofile-instr-generate -fcoverage-mapping (o binário .cov). O binário .afl faz fuzzing; o binário .cov reproduz a fila do AFL para produzir cobertura real de linhas de código/funções/ramos.

O pipeline, etapa por etapa

#EtapaTaskflow YAML
1Instalar AFL++ + ferramentasscripts/fuzzing/install_afl.sh
2Obter código-fonteseclab_taskflows.taskflows.audit.fetch_source_code
3Identificar alvos de fuzzingseclab_taskflows_fuzzing.taskflows.fuzzing.identify_fuzz_targets
4Analisar sistema de buildseclab_taskflows_fuzzing.taskflows.fuzzing.analyze_build_system
5aEscrever harnesses iniciais (×N candidatos se solicitado)seclab_taskflows_fuzzing.taskflows.fuzzing.write_initial_harnesses
5bCompilar harnesses (AFL + cobertura)seclab_taskflows_fuzzing.taskflows.fuzzing.build_harnesses
5cQualificar candidatos (quando HARNESS_CANDIDATES > 1)seclab_taskflows_fuzzing.taskflows.fuzzing.qualify_harnesses
6Ciclo de fuzzing/cobertura/melhoria (×N iterações)seclab_taskflows_fuzzing.taskflows.fuzzing.fuzz_iteration
7Triagem de crashesseclab_taskflows_fuzzing.taskflows.fuzzing.triage_crashes
8Confirmar que crashes previamente conhecidos ainda se reproduzemseclab_taskflows_fuzzing.taskflows.fuzzing.confirm_fixed_crashes
9Construir grafo de chamadas + relatório de APIs não tocadasseclab_taskflows_fuzzing.taskflows.fuzzing.analyze_call_graph
10Escrever relatórios de vulnerabilidade por crashseclab_taskflows_fuzzing.taskflows.fuzzing.write_vuln_reports
11Escrever relatório da campanhaseclab_taskflows_fuzzing.taskflows.fuzzing.write_report

Cada etapa é um taskflow YAML autocontido que o agente executa de ponta a ponta. As etapas comunicam exclusivamente através da base de dados SQLite em fuzz_context.db — não há transferência em memória.


O ciclo de feedback de cobertura

Este é o coração do pipeline. Os orçamentos de tempo duplicam a cada iteração:``` 30s → 60s → 120s → 240s → 480s → 960s (≈ 32 min/target)

root@kitploit:~
A cada iteração, a cada harness, o agente:

1. Solicita `get_persistent_corpus_dir(harness_id)` para obter o diretório
   de corpus estável deste harness.
2. Chama `run_afl_for(afl_binary_path, seed_dir=<persistent corpus>,
   output_dir=<run dir>, seconds=<budget>, dictionary=<auto.dict>)`.
3. Chama `run_coverage(cov_binary_path, inputs_dir=<run>/default/queue,
   output_dir=<run>/coverage)` para produzir um tracefile LCOV e um relatório HTML.
4. Chama `store_coverage_from_lcov(run_id, lcov_path, html_path)` para persistir
   uma linha `coverage_report` + linhas `coverage_gap` por item não coberto.
5. Chama `fold_queue_into_persistent_corpus(...)` para fundir a fila de iteração
   do AFL no corpus persistente e executar `cmin` para manter o tamanho limitado.
6. Lê `get_coverage_summary` + `get_coverage_gaps`, e então ou:
   - adiciona uma nova seed (marcada com `coverage_feedback`) para alcançar um
     branch não coberto,
   - edita o código-fonte do harness para chamar uma API adicional,
   - chama `enrich_dictionary_from_uncovered(...)` para adicionar automaticamente
     entradas de dicionário para as constantes mágicas que o AFL precisa para
     satisfazer um guard, ou
   - ignora a lacuna (caminho de erro frio / código do fornecedor).
7. Chama `store_iteration_note(repo, iteration_number, harness_id, note=<resumo
   de uma linha>)` para que a linha do tempo de iterações do dashboard acompanhe o que
   mudou.

**Detecção de platô.** O loop termina antecipadamente assim que duas iterações consecutivas
tiverem ambas ganhado < `FUZZ_PLATEAU_THRESHOLD_PCT` (padrão `1.0`) pontos percentuais
absolutos de cobertura de linhas.

---

## Fuzzing ciente da estrutura

Três mecanismos complementares produzem entradas mais fortes do que a mutação bruta de bytes.

### 1. Dicionários por formato + mutadores personalizados

Para alvos cujo `input_kind` corresponde a um formato conhecido, o taskflow inclui
dicionários pré-construídos e arquivos-fonte C `LLVMFuzzerCustomMutator`:

| Formato | Dicionário | Mutador | Notas |
|--------|------------|---------|-------|
| `json` | `json.dict` | `json_mutator.c` | Emenda de tokens, dup/drop de colchetes balanceados, inversão de tipo |
| `xml` | `xml.dict` | `xml_mutator.c` | Tags, entidades, DTDs, tokens billion-laughs |
| `regex` | `regex.dict` | `regex_mutator.c` | Âncoras, classes, quantificadores, padrões ReDoS reais |
| `binary_tlv` | _(nenhum)_ | `binary_tlv_mutator.c` | Registros com prefixo de comprimento: estouro de comprimento / dup / drop |
| `png` | `png.dict` | _(reutiliza binary_tlv)_ | Dicionário PNG + mutador binary_tlv |

Estes são capturados automaticamente por `write_initial_harnesses` (dicionário
copiado ao lado das seeds) e `build_harnesses` (mutador vinculado ao binário
AFL). Cada mutador delega 50% das mutações ao mutador de bytes padrão do AFL
para não perdermos a randomização do motor.

Para adicionar um novo formato: coloque um `<name>.dict` e/ou um `<name>_mutator.c` em
`src/seclab_taskflows/dictionaries/`, depois registre-o no
mapa `_FORMAT_ASSETS` na parte inferior de `fuzz_runner.py`.

### 2. Mutador inteligente ciente do código-fonte (específico do projeto)

Para formatos desconhecidos, ou sempre que você quiser tokens mais fortes e específicos do projeto,
`generate_smart_mutator` escaneia os próprios arquivos `.c`/`.h` do repositório alvo
e emite um arquivo C `LLVMFuzzerCustomMutator` cujos dicionários de emenda
são extraídos de:

- literais de string com ≥3 caracteres alfabéticos (após filtrar ruído de compilador/licença,
  caminhos, cabeçalhos, restrições asm, especificadores de formato),
- constantes numéricas de 32 bits de `#define`, `case` e `enum` (após
  filtrar ruído genérico de inteiros pequenos como 0, 1, 256, 0xff…).

Três focos estão disponíveis:

| Foco | O que emenda | Quando usar |
|-------|-----------------|-------------|
| `strings` | Apenas literais de string do projeto | Formatos de texto (JSON, XML, YAML, CSV) |
| `constants` | Apenas valores mágicos numéricos de 32 bits | Protocolos binários, cabeçalhos com números mágicos |
| `combined` | Ambos | Padrão; geralmente o melhor |

Combine `generate_smart_mutators(...)` (plural) com `HARNESS_CANDIDATES >= 3`
para que cada foco se torne um harness candidato na rodada de qualificação.

### 3. Dicionário AFL ciente do projeto + enriquecimento orientado por cobertura

Duas ferramentas complementares constroem e expandem um dicionário AFL `-x` à medida que
a campanha avança:

- **`generate_project_dictionary(source_root, output_path)`** — executa uma vez
  antes da iteração 1, extrai estaticamente o mesmo conjunto de tokens de código-fonte usado pelo
  mutador inteligente e o escreve como um dicionário AFL. Constantes numéricas
  são emitidas em AMBAS as endiannesses para que o fuzzer possa satisfazer
  `memcmp(x, &magic, 4)` independentemente da ordem de bytes do host.

- **`enrich_dictionary_from_uncovered(source_root, dictionary_path,
  uncovered_locations)`** — executa após a etapa de cobertura de cada iteração,
  escaneia o código-fonte ao redor em busca de guards condicionais
  (`strncmp/memcmp/strstr`, `case 0xN:`, `== 0xN`, `== 'X'`) próximos às
  linhas não cobertas, e ANEXA quaisquer novos tokens ao dicionário. Idempotente:
  nunca readiciona uma entrada que já está presente.

### 4. Operação de emenda de corpus

Quando `corpus_dir` é passado para `generate_smart_mutator`, o C gerado
também recebe um operador de emenda de corpus: na primeira chamada ele carrega até 64 arquivos
desse diretório (limitados a 4 KiB cada), e a partir daí pode emendar
sub-regiões aleatórias desses arquivos na entrada mutada. Isso dá ao
mutador um operador no estilo de recombinação que o havoc padrão do AFL não faz
bem. Combine com `get_persistent_corpus_dir(...)` para que a biblioteca de emenda
seja "remixar o que o AFL já descobriu".

---

## Corpus persistente entre iterações e campanhas

Cada harness tem um diretório de corpus estável em:```
<workspace>/corpus/harness_<id>/

É isto que fuzz_iteration usa como seed_dir para run_afl_for (em vez de <harness>/seeds). No final de cada iteração, fold_queue_into_persistent_corpus(...) funde a fila de iteração do AFL neste diretório e executa afl-cmin para o manter limitado.

O resultado: a fila de ontem transita para a execução de hoje E entre re-execuções do mesmo projeto. Uma paragem e reinício da campanha não perde progresso.


Triagem e relatórios de vulnerabilidades

Depois de o ciclo fuzz/coverage/improve terminar, três fases são executadas automaticamente:

1. triage_crashes

Para cada ficheiro de crash em <run>/default/crashes/:

  • afl-tmin para minimizar a entrada,
  • replay_under_asan para capturar um stack trace e stack_top_hash (top-N frames normalizados; templates, namespaces inline do libcxx, namespaces anónimos e sufixos numéricos de LTO são removidos para que crashes semanticamente idênticos tenham o mesmo hash),
  • deduplicação por hash, persistindo uma linha crash com classificação de bug-class + nota de confiança (high / medium / low).

2. confirm_fixed_crashes

Reexecuta cada crash previamente classificado (cujo veredicto ainda não seja fixed/duplicate/non_reproducible) através do binário AFL+ASan atual. Se já não provocar crash, marca verdict="fixed". Útil ao reexecutar uma campanha contra um projeto que teve correções upstream aplicadas desde a última campanha.

3. write_vuln_reports

Para cada crash único, o agente lê o código-fonte do harness + o código-fonte da função que provoca o crash, percorre a cadeia de chamadas a partir da API pública e depois atribui um de dez veredictos no estilo OSS-Fuzz e escreve um relatório de vulnerabilidade em markdown:

VeredictoSignificado
vulnerabilityReal, explorável através de uma API pública
library_hardeningBug real mas sem caminho realista pela API pública; a biblioteca deve ainda assim defender-se
harness_bugO bug está no nosso harness, não na biblioteca
non_reproducibleA reexecução não reproduz o crash na entrada minimizada
oomOut-of-memory; vulnerabilidade apenas se o tamanho controlável pelo atacante for ilimitado
timeoutDoS por explosão algorítmica
assertion_failureassert() acionado; relevância de segurança varia
fixedDefinido por confirm_fixed_crashes: a entrada já não reproduz
duplicateMesma causa raiz que outro crash com um stack hash diferente
needs_investigationNão foi possível determinar; sinalizado para revisão humana

Cada relatório de vulnerabilidade inclui:

  • Veredicto + bug class + CWE + severidade + confiança
  • Análise de causa raiz com referências file:line
  • Alcançabilidade a partir da API pública (cadeia de chamadas concreta)
  • Avaliação de explorabilidade (leitura vs. escrita, controlo do atacante, mitigações)
  • Correção sugerida como diff unificado (marcada como "review required")
  • Esboço de teste de regressão

Dashboard em tempo real

O dashboard é iniciado automaticamente em segundo plano por run_fuzzing.sh. Desative com FUZZ_NO_DASHBOARD=1; substitua a porta com FUZZ_DASHBOARD_PORT (predefinição 8765).

Num Codespace, a porta 8765 é reencaminhada automaticamente — abra o URL reencaminhado em qualquer navegador. A página atualiza-se automaticamente a cada 5 s e mostra:

  • Chips de resumo de veredictos — contagens por categoria de veredicto, total de execuções, paths, contagem total de execuções, crashes
  • Indicador de pulso "running" em tempo real — por repo e por harness com um fuzz_run em curso
  • Tabela de tendência de cobertura com sparklines SVG inline e uma coluna de delta por iteração
  • Grafo de chamadas e superfície de API não tocada — o snapshot Fuzz-Introspector-lite
  • Tabela de crashes — ordenada por veredicto (vulnerability primeiro), com ligações para cada relatório de vulnerabilidade e entrada minimizada
  • Heatmap de crashes — grelha por (harness × iteração) de contagens de crashes, opacidade escala com a contagem
  • Linha temporal de iterações — feed cronológico de notas de uma linha escritas pelo agente a descrever o que mudou em cada iteração
  • Funções não cobertas principais — recolhidas por predefinição

API JSON

O dashboard também expõe uma pequena API JSON apenas de leitura para scripts:```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:~
---

## Arquivos de saída

Todos em `~/.local/share/seclab-taskflow-agent/seclab-taskflows/`.

| Caminho | Conteúdo |
|------|----------|
| `fuzz_context/fuzz_context.db` | SQLite — alvos, harnesses, execuções, cobertura, crashes, veredictos, grafos de chamadas, sugestões de harness, notas de iteração |
| `fuzz_runner/builds/` | Binários `.afl` e `.cov` compilados |
| `fuzz_runner/runs/` | Diretórios de saída do AFL + arquivos LCOV + relatórios de cobertura HTML |
| `fuzz_runner/corpus/harness_<id>/` | Corpus persistente por harness (mantém-se entre iterações e campanhas) |
| `fuzz_runner/repo/<owner>__<repo>/REPORT.md` | Resumo da campanha em Markdown, crashes agrupados por veredicto |
| `fuzz_runner/repo/<owner>__<repo>/vuln_<crash_id>.md` | Relatório de vulnerabilidade em Markdown por crash |
| `fuzz_runner/repo/<owner>__<repo>/call_graph.{dot,svg,md}` | Grafo de chamadas estático + sobreposição de alcançadas/não alcançadas |

---

## Esquema da base de dados

Tabelas em `fuzz_context.db` (SQLite via SQLAlchemy):

| Tabela | Colunas de interesse |
|-------|--------------------|
| `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` |

As migrações de esquema residem em `_migrate()` em `fuzz_context.py`. Novas TABELAS são
criadas automaticamente por `Base.metadata.create_all()`; apenas novas COLUNAS precisam
de `ALTER TABLE` baseado em PRAGMA.

---

## Ferramentas MCP (o vocabulário do agente)

O agente nunca chama AFL ou clang diretamente — compõe o pipeline
chamando ferramentas MCP. O conjunto completo, agrupado por finalidade:

### Persistência (`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`

### Build / fuzz / cobertura (`fuzz_runner.py`)

- `check_tooling`, `workspace_paths`
- `compile_harness` — compila os binários `.afl` e `.cov`
- `run_afl_for`, `cmin`, `tmin`, `replay_under_asan`, `reproduce_crash`
- `run_coverage` — reproduz a fila do AFL contra o binário `.cov`, exporta LCOV
- `extract_dictionary` — extrai strings imprimíveis de um binário
- `package_reproducer` — empacota um `.tgz` de crash único

### Corpus persistente (v8)

- `get_persistent_corpus_dir`, `fold_queue_into_persistent_corpus`

### Recursos de formato (C5)

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

### Mutador inteligente + dicionário ciente do projeto

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

As funções de ferramenta são decoradas com `@mcp.tool()` (FastMCP). Dentro dos testes,
invocam-se através do atributo `.fn`, por exemplo
`fr.run_afl_for.fn(afl_binary_path=..., ...)`.

---

## Parâmetros ajustáveis (variáveis de ambiente)

| Variável | Padrão | Finalidade |
|----------|---------|---------|
| `HARNESS_CANDIDATES` | `1` | Número de harnesses candidatos escritos por alvo. Defina como 2 ou 3 para competição ao estilo OSS-Fuzz-Gen. A fase de qualificação executa cada um durante `QUALIFIER_SECONDS` e mantém o melhor por % de linhas. |
| `QUALIFIER_SECONDS` | `60` | Orçamento de tempo real por candidato na fase de qualificação. |
| `FUZZ_PLATEAU_THRESHOLD_PCT` | `1.0` | Ganho de cobertura de linhas (em pp absolutos) abaixo do qual duas iterações consecutivas são consideradas um plateau e o ciclo termina antecipadamente. |
| `FUZZ_DASHBOARD_PORT` | `8765` | Porta para o dashboard em tempo real. |
| `FUZZ_NO_DASHBOARD` | (não definido) | Defina como `1` para ignorar o arranque do dashboard. |
| `FUZZ_RUNNER_TIMEOUT` | `1200` | Timeout do subprocesso por ferramenta em `fuzz_runner` (segundos). |
| `LOCAL_SHELL_TIMEOUT` | `180` | Timeout por comando em `local_shell` (segundos). |

Mais as variáveis padrão do agente (`COPILOT_TOKEN`, `LOG_DIR`,
`FUZZ_CONTEXT_DIR`, …). Consulte o README na raiz do projeto para a lista completa.

---

## Estender o pipeline

### Adicionar um novo formato (mutador + dicionário)

1. Coloque `dictionaries/<name>.dict` (formato `-x` do AFL) e/ou
   `dictionaries/<name>_mutator.c` (mutador personalizado libFuzzer).
2. Registe em `_FORMAT_ASSETS` no final de `fuzz_runner.py`:   ```python
   "<name>": {
       "dictionary": "<name>.dict",
       "mutator": "<name>_mutator.c",
       "description": "Short one-liner about the format",
   },
  1. O agente irá capturá-lo automaticamente através de list_format_assets().

Adicionar uma nova ferramenta MCP

  1. Adicione uma função decorada com @mcp.tool() em fuzz_context.py (para persistência) ou fuzz_runner.py (para trabalho em subprocesso).
  2. Use Annotated[type, Field(description=...)] para cada argumento — a descrição é o que o LLM vê.
  3. Adicione um teste unitário em tests/test_fuzz_context.py / tests/test_fuzz_runner.py. Invoque a ferramenta através do seu atributo .fn (convenção do FastMCP).
  4. Referencie a nova ferramenta no user_prompt do YAML do taskflow relevante.

Adicionar um novo estágio de pipeline

  1. Crie um novo YAML em src/seclab_taskflows/taskflows/fuzzing/. Use um dos arquivos existentes (por exemplo, triage_crashes.yaml) como modelo.
  2. Ligue-o em scripts/fuzzing/run_fuzzing.sh entre os dois estágios existentes corretos.
  3. (Opcional) adicione uma seção de dashboard específica do estágio em scripts/fuzzing/dashboard.py.

Migração de schema

Ao adicionar uma nova tabela SQL:

  • Adicione o modelo SQLAlchemy em fuzz_context_models.py.
  • Nada mais é necessário — Base.metadata.create_all() é chamado na inicialização do engine e cria novas tabelas automaticamente.

Ao adicionar uma nova COLUNA a uma tabela existente:

  • Atualize o modelo SQLAlchemy.
  • Adicione um bloco PRAGMA table_info + ALTER TABLE ADD COLUMN em _migrate() em fuzz_context.py para que bancos de dados antigos sejam atualizados de forma transparente.
  • Se a coluna for lida pelo dashboard, atualize também _migrate_if_writable() em scripts/fuzzing/dashboard.py.

Projetos de benchmark e resultados

benchmark/projects.yaml lista os projetos de referência. Eles são escolhidos para que o pipeline completo v4+ possa rodar de ponta a ponta em uma imagem de desenvolvimento do codespace sem intervenção humana.

#RepoPor que é interessanteNotas
1tukaani-project/xzBiblioteca real com muito parsing (liblzma); cadeia de filtros rica + superfície de parsing de inteiros/VLIBaseline
2DaveGamble/cJSONParser JSON em C de arquivo único pequeno; CMake trivialSmoke rápido para o pipeline
3akheron/janssonBiblioteca JSON em C compacta com ponto de entrada documentado json_loadb() para buffer de bytesCMake; exec/sec muito rápido
4libexpat/libexpatParser XML de streaming maduro; muitos CVEs históricosCMake ou autotools
5kkos/onigurumaMotor de regex; recebe padrão do atacante + sujeitoAutotools; a compilação do padrão é o caminho crítico

Números de referência de uma execução completa do pipeline v4 na imagem de desenvolvimento do codespace (≈32 min/alvo):

RepoAlvosHarnessesExecuções AFLCrashesVeredictos
tukaani-project/xz88480—
DaveGamble/cJSON66360—
akheron/jansson773510harness_bug, library_hardening, duplicate, needs_investigation
libexpat/libexpat33180—
kkos/oniguruma10106013vulnerability (×2 leitura fora dos limites em regerror.c), library_hardening, harness_bug, non_reproducible

Os resultados de zero crashes do xz / cJSON / libexpat são esperados: esses projetos são intensamente fuzzed upstream. Os dois achados classificados como vulnerability no oniguruma são leituras reais fora dos limites no caminho de código de formatação de avisos de onig_snprintf_with_pattern (leitura de um byte além de pat_end quando o padrão termina com uma barra invertida); os relatórios markdown por crash incluem patches sugeridos.

Para adicionar um novo projeto de benchmark, adicione uma entrada em benchmark/projects.yaml e (opcionalmente) documente o motivo em benchmark/README.md. Qualquer coisa que o estágio existente analyze_build_system consiga compilar com clang + flags do AFL++ é um candidato razoável. Parsers, decodificadores e serializadores em C puro tendem a funcionar melhor.


Limitações e armadilhas

  • Apenas C / C++. O AFL++ é um fuzzer de instrumentação nativa.
  • Dependente do sistema de build. Projetos com sistemas de build não triviais (regras Bazel personalizadas, libc vendorizada, ferramentas de build proprietárias) podem falhar ao compilar com flags do clang/AFL. O agente marca esses alvos como BUILD_FAILED: e os ignora.
  • Avisos do AFL no Codespace. O AFL++ quer kernel.core_pattern=core e um ajuste no governor da CPU. Em um Codespace isso não está disponível, então o taskflow exporta AFL_SKIP_CPUFREQ=1 e AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 por padrão. O AFL imprime avisos, mas ainda encontra crashes através do tratamento de abort no estilo libFuzzer.
  • Limitado pelo modelo. A qualidade de escrita de harness do agente é limitada pela compreensão do modelo subjacente sobre o código alvo.
  • Splice de corpus do mutador inteligente apenas em POSIX. A operação de splice de corpus usa <dirent.h>. Ok para Linux/macOS; não compilaria no Windows.
  • Ressalva do modo stdin. Binários AFL compilados via compile_harness usam libAFLDriver em modo argv. replay_under_asan e tmin portanto usam stdin_input=False por padrão porque o libAFLDriver entra em loop infinito quando acionado via stdin.
  • generate_smart_mutator + generate_smart_mutators usam .format() do Python — cada { / } literal no template C deve ser duplicado ({{ / }}). Se você editar o template e começar a ver KeyError, é por isso.

Aviso de segurança

Este taskflow executa afl-fuzz, clang, llvm-cov, e comandos de build arbitrários escolhidos pelo LLM, diretamente no host (sem container). Um agente com prompt injetado poderia, em princípio, fazer qualquer coisa que seu usuário pode. Execute apenas:

  • dentro de ambientes descartáveis (GitHub Codespaces, VMs descartáveis, etc.),
  • sem privilégios elevados,
  • com acesso à rede limitado ao que git, apt e o sistema de build precisam.

A toolbox local_shell NÃO está atrás de um prompt de confirmação — o taskflow é autônomo e roda sem um humano no loop, então uma confirmação interativa simplesmente bloquearia para sempre. Todo comando de shell é registrado em $LOG_DIR/mcp_local_shell.log para revisão posterior.


Desenvolvimento: testes, linting, contribuição```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:~
Convenções do código (veja também `benchmark/improvements.md` para a
versão de histórico de campanha destas):

- Use `os.environ.get(NAME) or "default"` em vez de
  `os.environ.get(NAME, "default")`. Strings vazias provenientes da
  substituição de template YAML seriam retornadas de outra forma.
- Use `X | None` (PEP 604) em novas anotações, não `Optional[X]`.
- Os testes invocam ferramentas MCP via `.fn(...)`, não o nome decorado
  diretamente.
- Evite literais `/tmp/...` nos testes — use a fixture `tmp_path` do pytest
  (regra de lint `S108`).
- Todos os imports inline dentro de métodos de teste precisam de
  `# noqa: PLC0415` se você não puder movê-los para o topo do arquivo
  (por exemplo, quando importados condicionalmente após um `pytest.skip`).
- Uma asserção por linha para testes de verdade compostos (regra de lint
  `PT018`).

O rastreador de melhorias (`benchmark/improvements.md`) é o log
persistente do que foi adicionado ao pipeline ao longo das versões. Quando
você adicionar uma funcionalidade substancial, adicione uma seção lá
descrevendo o que mudou, onde ela vive e quais testes a protegem.

---

## Glossário

- **AFL++** — Fuzzer greybox guiado por cobertura; o motor de execução aqui.
- **libAFLDriver** — Biblioteca estática que permite que harnesses do
  AFL++ usem a convenção de ponto de entrada do libFuzzer
  (`LLVMFuzzerTestOneInput`).
- **LCOV** — Formato padrão da indústria para arquivos de rastreamento de
  cobertura. Exportamos para ele via `llvm-cov export -format=lcov` e o
  analisamos nós mesmos.
- **`stack_top_hash`** — Um hash de 16 caracteres dos N frames superiores
  normalizados de um stack trace do ASan/UBSan. Usado para deduplicação de
  crashes.
- **Corpus persistente** — Diretório por harness em
  `<workspace>/corpus/harness_<id>/` que carrega as entradas interessantes
  do AFL entre iterações e reexecuções da mesma campanha.
- **Mutador inteligente** — Um `LLVMFuzzerCustomMutator` cujos tokens de
  splice são extraídos do próprio código-fonte do alvo
  (`generate_smart_mutator`).
- **Mutador customizado (libFuzzer)** — Uma função C fornecida pelo
  usuário, chamada pelo motor com total liberdade sobre como mutar um
  buffer; o AFL++ suporta a mesma ABI.
- **Ferramenta MCP** — Uma função decorada com FastMCP que o agente LLM
  pode chamar.
- **OSS-Fuzz / Fuzz-Introspector** — A infraestrutura de fuzzing de
  código aberto do Google e sua ferramenta companheira de análise de
  call-graph/cobertura. Várias funcionalidades deste taskflow (mutadores
  por formato, dedup por stack, relatório de call-graph + APIs não
  tocadas, harnesses multi-candidatos) são inspiradas nelas.

---

## Licença

Este projeto está licenciado sob os termos da licença de código aberto
MIT. Consulte o arquivo [LICENSE](https://github.com/githubsecuritylab/seclab-taskflows-fuzzing/blob/main/LICENSE.txt) para os termos completos.

## Mantenedores

Veja [CODEOWNERS](https://github.com/githubsecuritylab/seclab-taskflows-fuzzing/blob/main/CODEOWNERS) ou entre em contato com a equipe do GitHub
Security Lab.

## Suporte

Veja [SUPPORT.md](https://github.com/githubsecuritylab/seclab-taskflows-fuzzing/blob/main/SUPPORT.md) para detalhes sobre como obter ajuda com
este projeto.

## Agradecimentos

Este projeto é construído sobre os conceitos e técnicas do
[AFL++](https://github.com/AFLplusplus/AFLplusplus),
[OSS-Fuzz](https://github.com/google/oss-fuzz) e
[Fuzz-Introspector](https://github.com/ossf/fuzz-introspector).
Baixar ferramenta