Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
seclab-taskflows-fuzzing — Una pipeline di fuzzing basata su LLM alimentata dal GitHub Security Lab Taskflow Agent | Kitploit
Strumenti/GitHubGitHub/githubsecuritylab/seclab-taskflows-fuzzing
Analisi StaticaScanner di VulnerabilitàAnalisi Dinamica (Sandboxing)Analisi delle VulnerabilitàAnalisi del CodiceScripting e AutomazioneFuzzingAnalisi MalwareUtilità e Framework
Sicurezza dell'IA
GitHubgithubsecuritylab/seclab-taskflows-fuzzing

seclab-taskflows-fuzzing

Una pipeline di fuzzing basata su LLM alimentata dal GitHub Security Lab Taskflow Agent

Vedi Repository
1224 giorni faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

Seclab Taskflows Fuzzing

Una pipeline di fuzzing in stile OSS-Fuzz, guidata da LLM, per progetti nativi C/C++. AFL++ per l'esecuzione, clang+lcov per la copertura, un agente LLM per la scrittura degli harness, le decisioni basate sul feedback di copertura, il triage e il reporting.

  • Completamente autonomo: basta fornire un repository GitHub e gestisce tutto, dall'identificazione del target ai report sulle vulnerabilità.
  • Tecniche in stile OSS-Fuzz: mutatori/dizionari per formato, splicing di token consapevole della struttura, miglioramenti degli harness guidati dalla copertura.
  • Produce report di crash leggibili dalla macchina con verdetti di sfruttabilità e patch suggerite.
  • Dashboard HTML live per il monitoraggio della campagna in tempo reale.
  • Scritto in Python (taskflows/toolboxes/configs) con generazione di harness C per AFL++.
  • Stato: Sviluppo attivo.

Contesto

Questo repository contiene il taskflow di fuzzing per il GitHub Security Lab Taskflow Agent. Dipende dal repository complementare seclab-taskflows per alcuni blocchi di costruzione condivisi (taskflow fetch_source_code, toolbox local_file_viewer / gh_file_viewer e il model_config predefinito) — questi vengono installati automaticamente come dipendenza Python.

I contributi sono benvenuti! Consulta CONTRIBUTING.md per le linee guida.

Requisiti

  • Python 3.11+
  • Un ambiente Linux (o Codespace) con accesso ad apt
  • AFL++, clang, lcov, ctags, cscope, graphviz (installati automaticamente dalla pipeline se mancanti)
  • Git e GitHub CLI (gh)

Installazione```bash

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

root@kitploit:~
Questo include transitivamente `seclab-taskflow-agent` e `seclab-taskflows` (parent),
quindi ogni riferimento puntato nella forma
`seclab_taskflows.taskflows.audit.*`,
`seclab_taskflows.toolboxes.local_file_viewer`,
`seclab_taskflows.toolboxes.gh_file_viewer`, e
`seclab_taskflows.configs.model_config` viene risolto dalla distribuzione
parent a runtime.

---

## Indice

1. [Cos'è questo](#what-this-is)
2. [Avvio rapido](#quick-start)
3. [Architettura](#architecture)
4. [La pipeline, fase per fase](#the-pipeline-stage-by-stage)
5. [Il ciclo di feedback sulla copertura](#the-coverage-feedback-loop)
6. [Fuzzing structure-aware](#structure-aware-fuzzing)
7. [Corpus persistente tra iterazioni e campagne](#persistent-corpus-across-iterations-and-campaigns)
8. [Triage e report di vulnerabilità](#triage-and-vulnerability-reports)
9. [Dashboard live](#live-dashboard)
10. [File di output](#output-files)
11. [Schema del database](#database-schema)
12. [Strumenti MCP (il vocabolario dell'agente)](#mcp-tools-the-agents-vocabulary)
13. [Parametri regolabili (variabili d'ambiente)](#tunable-knobs-environment-variables)
14. [Estendere la pipeline](#extending-the-pipeline)
15. [Progetti di benchmark e risultati](#benchmark-projects-and-results)
16. [Limitazioni e insidie](#limitations-and-gotchas)
17. [Avviso di sicurezza](#security-warning)
18. [Sviluppo: testing, linting, contribuire](#development-testing-linting-contributing)
19. [Glossario](#glossary)

---

## Cos'è questo

Questo taskflow è una pipeline di fuzzing completamente autonoma. Dato un repository GitHub
di un progetto nativo C/C++, esso:

1. installa AFL++ + clang/llvm/lcov + ctags/cscope/graphviz se mancanti,
2. recupera il codice sorgente,
3. identifica i candidati target di fuzzing (parser, decoder, validatori, …),
4. analizza il sistema di build,
5. scrive uno o più candidati harness per target, compilando ciascuno sia come
   binario `.afl` instrumentato con AFL sia come binario `.cov` instrumentato per la copertura,
6. (opzionalmente) qualifica i candidati tramite copertura di 60 secondi e mantiene il migliore,
7. esegue un ciclo fuzz/copertura/miglioramento con budget temporali raddoppianti,
8. effettua il triage di ogni crash, conferma che i crash precedentemente noti si riproducono ancora, e
   scrive report markdown di vulnerabilità per ogni crash con verdetti, sfruttabilità,
   patch suggerite e bozze di test di regressione,
9. costruisce un call graph in stile Fuzz-Introspector + report delle API non toccate per la
   campagna successiva,
10. pubblica tutto su una dashboard HTML live.

La pipeline è **in stile OSS-Fuzz**: utilizza molte delle stesse
tecniche (mutatori e dizionari per formato, token splicing structure-aware, miglioramenti degli harness guidati dalla copertura, report machine-readable,
crash deduplicati con hash dello stack) ma è molto più piccola e autosufficiente.

---

## Avvio rapido```bash
# Inside the codespace (or a host with python + git available):
./scripts/fuzzing/run_fuzzing.sh tukaani-project/xz

È tutta l'interfaccia. Lo script è autonomo; installerà AFL++ alla prima esecuzione, poi guiderà il resto del taskflow. I file di output vengono scritti in ~/.local/share/seclab-taskflow-agent/seclab-taskflows/.

La dashboard si avvia automaticamente in background; in un Codespace, la porta 8765 viene inoltrata automaticamente — aprila in qualsiasi browser per seguire i progressi in tempo reale.

Per un rapido smoke-test, usa un target di piccole dimensioni:```bash ./scripts/fuzzing/run_fuzzing.sh DaveGamble/cJSON

root@kitploit:~
## Architettura

Tre livelli, dall'alto verso il basso:```
┌────────────────────────────────────────────────────────────────────┐
│  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                           │
└────────────────────────────────────────────────────────────────────┘

Regole di progettazione chiave:

  • Nessuno stato globale negli strumenti MCP. Ogni funzione di strumento accetta argomenti espliciti; lo stato persistente risiede in fuzz_context.db.
  • Gli agenti LLM possiedono le decisioni, gli strumenti MCP possiedono l'esecuzione. L'agente decide cosa fuzzare, quale harness scrivere, quale lacuna inseguire successivamente; gli strumenti MCP espongono semplicemente run_afl_for, compile_harness, store_crash, ecc.
  • Idempotenza ovunque sia economica. Rieseguire la pipeline sullo stesso repo esegue upsert di target/harness/run invece di duplicarli. Questo è ciò che fa funzionare il corpus persistente e il carryover tra campagne.
  • Due binari per harness. La strumentazione edge di AFL non è adatta per report di copertura leggibili dall'uomo, quindi ogni harness viene compilato due volte: una con afl-clang-lto -fsanitize=address,undefined (il binario .afl) e una con clang -fprofile-instr-generate -fcoverage-mapping (il binario .cov). Il binario .afl esegue il fuzzing; il binario .cov riproduce la coda AFL per produrre una copertura reale di righe sorgente/funzioni/branch.

La pipeline, fase per fase

#FaseTaskflow YAML
1Installare AFL++ + toolingscripts/fuzzing/install_afl.sh
2Recuperare il sorgenteseclab_taskflows.taskflows.audit.fetch_source_code
3Identificare i target di fuzzingseclab_taskflows_fuzzing.taskflows.fuzzing.identify_fuzz_targets
4Analizzare il sistema di buildseclab_taskflows_fuzzing.taskflows.fuzzing.analyze_build_system
5aScrivere gli harness iniziali (×N candidati se richiesto)seclab_taskflows_fuzzing.taskflows.fuzzing.write_initial_harnesses
5bCompilare gli harness (AFL + copertura)seclab_taskflows_fuzzing.taskflows.fuzzing.build_harnesses
5cQualificare i candidati (quando HARNESS_CANDIDATES > 1)seclab_taskflows_fuzzing.taskflows.fuzzing.qualify_harnesses
6Ciclo fuzz/copertura/miglioramento (×N iterazioni)seclab_taskflows_fuzzing.taskflows.fuzzing.fuzz_iteration
7Triage dei crashseclab_taskflows_fuzzing.taskflows.fuzzing.triage_crashes
8Confermare che i crash precedentemente noti si riproducono ancoraseclab_taskflows_fuzzing.taskflows.fuzzing.confirm_fixed_crashes
9Costruire il call graph + report delle API non toccateseclab_taskflows_fuzzing.taskflows.fuzzing.analyze_call_graph
10Scrivere report di vulnerabilità per ogni crashseclab_taskflows_fuzzing.taskflows.fuzzing.write_vuln_reports
11Scrivere il report della campagnaseclab_taskflows_fuzzing.taskflows.fuzzing.write_report

Ogni fase è un taskflow YAML autonomo che l'agente esegue end-to-end. Le fasi comunicano esclusivamente attraverso il database SQLite in fuzz_context.db — non c'è alcun passaggio di consegne in memoria.


Il ciclo di feedback sulla copertura

Questo è il cuore della pipeline. I budget di tempo raddoppiano a ogni iterazione:``` 30s → 60s → 120s → 240s → 480s → 960s (≈ 32 min/target)

root@kitploit:~
Ad ogni iterazione, per ogni harness, l'agente:

1. Chiama `get_persistent_corpus_dir(harness_id)` per ottenere la directory
   del corpus stabile di questo harness.
2. Chiama `run_afl_for(afl_binary_path, seed_dir=<persistent corpus>,
   output_dir=<run dir>, seconds=<budget>, dictionary=<auto.dict>)`.
3. Chiama `run_coverage(cov_binary_path, inputs_dir=<run>/default/queue,
   output_dir=<run>/coverage)` per produrre un tracefile LCOV e un report HTML.
4. Chiama `store_coverage_from_lcov(run_id, lcov_path, html_path)` per persistere
   una riga `coverage_report` + righe `coverage_gap` per ogni elemento non coperto.
5. Chiama `fold_queue_into_persistent_corpus(...)` per unire la coda di iterazione
   di AFL nel corpus persistente ed eseguire `cmin` per mantenere la dimensione limitata.
6. Legge `get_coverage_summary` + `get_coverage_gaps`, poi alternativamente:
   - aggiunge un nuovo seed (etichettato `coverage_feedback`) per raggiungere un
     branch non coperto,
   - modifica il sorgente dell'harness per chiamare un'API aggiuntiva,
   - chiama `enrich_dictionary_from_uncovered(...)` per aggiungere automaticamente
     voci al dizionario per le costanti magiche di cui AFL ha bisogno per soddisfare
     un guard, oppure
   - salta il gap (percorso di errore freddo / codice del vendor).
7. Chiama `store_iteration_note(repo, iteration_number, harness_id, note=<riepilogo
   su una riga>)` in modo che la timeline delle iterazioni della dashboard tracci cosa
   è cambiato.

**Rilevamento del plateau.** Il loop termina anticipatamente quando due iterazioni
consecutive hanno entrambe guadagnato < `FUZZ_PLATEAU_THRESHOLD_PCT` (default `1.0`)
punti percentuali assoluti di copertura delle righe.

---

## Fuzzing structure-aware

Tre meccanismi complementari producono input più forti della semplice mutazione di byte.

### 1. Dizionari per formato + mutatori personalizzati

Per i target il cui `input_kind` corrisponde a un formato noto, il taskflow include
dizionari pre-costruiti e file sorgente C `LLVMFuzzerCustomMutator`:

| Formato | Dizionario | Mutatore | Note |
|--------|------------|---------|-------|
| `json` | `json.dict` | `json_mutator.c` | Splice di token, dup/drop di parentesi bilanciate, type flip |
| `xml` | `xml.dict` | `xml_mutator.c` | Tag, entità, DTD, token billion-laughs |
| `regex` | `regex.dict` | `regex_mutator.c` | Ancore, classi, quantificatori, pattern ReDoS reali |
| `binary_tlv` | _(nessuno)_ | `binary_tlv_mutator.c` | Record con prefisso di lunghezza: length-overflow / dup / drop |
| `png` | `png.dict` | _(riusa binary_tlv)_ | Dizionario PNG + mutatore binary_tlv |

Questi vengono raccolti automaticamente da `write_initial_harnesses` (dizionario
copiato accanto ai seed) e `build_harnesses` (mutatore linkato nel binario AFL).
Ogni mutatore delega il 50% delle mutazioni al mutatore di byte predefinito di AFL
per non perdere la randomizzazione del motore.

Per aggiungere un nuovo formato: inserisci un `<name>.dict` e/o un `<name>_mutator.c`
in `src/seclab_taskflows/dictionaries/`, poi registralo nella mappa `_FORMAT_ASSETS`
in fondo a `fuzz_runner.py`.

### 2. Mutatore smart source-aware (specifico del progetto)

Per formati sconosciuti, o ogni volta che vuoi token più forti specifici del progetto,
`generate_smart_mutator` analizza i file `.c`/`.h` del repository target ed emette un
file C `LLVMFuzzerCustomMutator` i cui dizionari di splice sono estratti da:

- stringhe letterali con ≥3 caratteri alfabetici (dopo aver filtrato rumore di
  compilatore/licenza, percorsi, header, vincoli asm, specificatori di formato),
- costanti numeriche a 32 bit da `#define`, `case` ed `enum` (dopo aver filtrato
  rumore generico di piccoli interi come 0, 1, 256, 0xff…).

Sono disponibili tre focus:

| Focus | Cosa fa il splice | Quando usarlo |
|-------|-----------------|-------------|
| `strings` | Solo stringhe letterali del progetto | Formati testuali (JSON, XML, YAML, CSV) |
| `constants` | Solo valori magici numerici a 32 bit | Protocolli binari, header con numeri magici |
| `combined` | Entrambi | Default; di solito il migliore |

Abbina `generate_smart_mutators(...)` (plurale) con `HARNESS_CANDIDATES >= 3`
così ogni focus diventa un harness candidato nel round di qualificazione.

### 3. Dizionario AFL project-aware + arricchimento guidato dalla copertura

Due strumenti complementari costruiscono e fanno crescere un dizionario AFL `-x`
man mano che la campagna progredisce:

- **`generate_project_dictionary(source_root, output_path)`** — eseguito una volta
  prima dell'iterazione 1, estrae staticamente lo stesso insieme di token sorgente
  usato dal mutatore smart e lo scrive come dizionario AFL. Le costanti numeriche
  sono emesse in ENTRAMBI gli endianness così il fuzzer può soddisfare
  `memcmp(x, &magic, 4)` indipendentemente dall'ordine dei byte dell'host.

- **`enrich_dictionary_from_uncovered(source_root, dictionary_path,
  uncovered_locations)`** — eseguito dopo la fase di copertura di ogni iterazione,
  analizza il sorgente circostante per guard condizionali
  (`strncmp/memcmp/strstr`, `case 0xN:`, `== 0xN`, `== 'X'`) vicino alle righe
  non coperte, e APPENDE qualsiasi nuovo token al dizionario. Idempotente:
  non riaggiunge mai una voce già presente.

### 4. Operazione di corpus-splice

Quando `corpus_dir` viene passato a `generate_smart_mutator`, il C generato
ottiene anche un operatore di corpus-splice: alla prima chiamata carica fino a 64 file
da quella directory (limitati a 4 KiB ciascuno), e da quel momento può fare splice
di sotto-regioni casuali di quei file nell'input mutato. Questo dà al mutatore un
operatore in stile ricombinazione che l'havoc standard di AFL non esegue bene.
Abbinalo con `get_persistent_corpus_dir(...)` così la libreria di splice
è "remix di ciò che AFL ha già scoperto".

---

## Corpus persistente tra iterazioni e campagne

Ogni harness ha una directory del corpus stabile in:```
<workspace>/corpus/harness_<id>/

Questo è ciò che fuzz_iteration usa come seed_dir per run_afl_for (invece di <harness>/seeds). Alla fine di ogni iterazione, fold_queue_into_persistent_corpus(...) unisce la coda di iterazione di AFL in questa directory ed esegue afl-cmin per mantenerla limitata.

Il risultato: la coda di ieri si trasferisce nell'esecuzione di oggi E attraverso le riesecuzioni dello stesso progetto. Un arresto e riavvio della campagna non perde alcun progresso.


Triage e report delle vulnerabilità

Dopo che il ciclo fuzz/coverage/improve termina, tre fasi vengono eseguite automaticamente:

1. triage_crashes

Per ogni file di crash in <run>/default/crashes/:

  • afl-tmin per minimizzare l'input,
  • replay_under_asan per catturare uno stack trace e stack_top_hash (top-N frame normalizzati; template, namespace inline di libcxx, namespace anonimi e suffissi numerici LTO vengono rimossi così che crash semanticamente identici abbiano lo stesso hash),
  • deduplica per hash, persiste una riga crash con classificazione della bug-class + nota di confidenza (alta / media / bassa).

2. confirm_fixed_crashes

Riproduce ogni crash precedentemente classificato (il cui verdetto non sia già fixed/duplicate/non_reproducible) attraverso il binario AFL+ASan corrente. Se non causa più crash, imposta verdict="fixed". Utile quando si riesegue una campagna contro un progetto che ha ricevuto correzioni upstream dall'ultima campagna.

3. write_vuln_reports

Per ogni crash unico, l'agente legge il sorgente dell'harness + il sorgente della funzione che causa il crash, percorre la catena di chiamate dall'API pubblica, quindi assegna uno tra dieci verdetti in stile OSS-Fuzz e scrive un report di vulnerabilità in markdown:

VerdettoSignificato
vulnerabilityReale, sfruttabile attraverso un'API pubblica
library_hardeningBug reale ma nessun percorso realistico tramite API pubblica; la libreria dovrebbe comunque difendersi
harness_bugIl bug è nel nostro harness, non nella libreria
non_reproducibleIl replay non riproduce il crash sull'input minimizzato
oomOut-of-memory; vulnerabilità solo se la dimensione controllabile dall'attaccante è illimitata
timeoutDoS tramite esplosione algoritmica
assertion_failureassert() attivato; la rilevanza per la sicurezza varia
fixedImpostato da confirm_fixed_crashes: l'input non riproduce più
duplicateStessa causa radice di un altro crash con un hash dello stack diverso
needs_investigationImpossibile determinare; segnalato per revisione umana

Ogni report di vulnerabilità include:

  • Verdetto + bug class + CWE + severità + confidenza
  • Analisi della causa radice con riferimenti file:line
  • Raggiungibilità dall'API pubblica (catena di chiamate concreta)
  • Valutazione della sfruttabilità (lettura vs. scrittura, controllo dell'attaccante, mitigazioni)
  • Correzione suggerita come diff unificato (contrassegnata "review required")
  • Bozza di test di regressione

Dashboard live

La dashboard viene avviata automaticamente in background da run_fuzzing.sh. Disabilitare con FUZZ_NO_DASHBOARD=1; sovrascrivere la porta con FUZZ_DASHBOARD_PORT (predefinita 8765).

In un Codespace, la porta 8765 viene inoltrata automaticamente — aprire l'URL inoltrato in qualsiasi browser. La pagina si aggiorna automaticamente ogni 5 s e mostra:

  • Chip di riepilogo dei verdetti — conteggi per categoria di verdetto, esecuzioni totali, percorsi, conteggio exec totale, crash
  • Indicatore pulse "running" live — per repo e per harness con un fuzz_run in corso
  • Tabella di tendenza della copertura con sparkline SVG inline e una colonna delta per iterazione
  • Call graph e superficie API non toccata — lo snapshot Fuzz-Introspector-lite
  • Tabella dei crash — ordinata per verdetto (vulnerability per primo), con link a ciascun report di vulnerabilità e all'input minimizzato
  • Heatmap dei crash — griglia per-(harness × iterazione) dei conteggi di crash, l'opacità scala con il conteggio
  • Timeline delle iterazioni — feed cronologico di note di una riga scritte dall'agente che descrivono cosa è cambiato in ogni iterazione
  • Funzioni principali non coperte — compresse per impostazione predefinita

API JSON

La dashboard espone anche una piccola API JSON di sola lettura per gli script:```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:~
---

## File di output

Tutti sotto `~/.local/share/seclab-taskflow-agent/seclab-taskflows/`.

| Percorso | Contenuto |
|------|----------|
| `fuzz_context/fuzz_context.db` | SQLite — target, harness, esecuzioni, copertura, crash, verdetti, call graph, suggerimenti di harness, note di iterazione |
| `fuzz_runner/builds/` | Binari `.afl` e `.cov` compilati |
| `fuzz_runner/runs/` | Directory di output AFL + file LCOV + report di copertura HTML |
| `fuzz_runner/corpus/harness_<id>/` | Corpus persistente per harness (persiste tra iterazioni e campagne) |
| `fuzz_runner/repo/<owner>__<repo>/REPORT.md` | Riepilogo della campagna in Markdown, crash raggruppati per verdetto |
| `fuzz_runner/repo/<owner>__<repo>/vuln_<crash_id>.md` | Report di vulnerabilità in Markdown per singolo crash |
| `fuzz_runner/repo/<owner>__<repo>/call_graph.{dot,svg,md}` | Call graph statico + overlay raggiunto/non raggiunto |

---

## Schema del database

Tabelle in `fuzz_context.db` (SQLite tramite SQLAlchemy):

| Tabella | Colonne di 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` |

Le migrazioni dello schema risiedono in `_migrate()` in `fuzz_context.py`. Le nuove TABELLE vengono
create automaticamente da `Base.metadata.create_all()`; solo le nuove COLONNE necessitano
di `ALTER TABLE` basato su PRAGMA.

---

## Strumenti MCP (il vocabolario dell'agente)

L'agente non chiama mai AFL o clang direttamente — compone la pipeline
chiamando gli strumenti MCP. L'insieme completo, raggruppato per scopo:

### Persistenza (`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 / copertura (`fuzz_runner.py`)

- `check_tooling`, `workspace_paths`
- `compile_harness` — compila i binari `.afl` e `.cov`
- `run_afl_for`, `cmin`, `tmin`, `replay_under_asan`, `reproduce_crash`
- `run_coverage` — riproduce la coda AFL contro il binario `.cov`, esporta LCOV
- `extract_dictionary` — estrae stringhe stampabili da un binario
- `package_reproducer` — raggruppa un singolo crash in un `.tgz`

### Corpus persistente (v8)

- `get_persistent_corpus_dir`, `fold_queue_into_persistent_corpus`

### Asset di formato (C5)

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

### Mutator intelligente + dizionario consapevole del progetto

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

Le funzioni degli strumenti sono decorate con `@mcp.tool()` (FastMCP). Nei test,
invocale tramite l'attributo `.fn`, ad es.
`fr.run_afl_for.fn(afl_binary_path=..., ...)`.

---

## Parametri configurabili (variabili d'ambiente)

| Variabile | Predefinito | Scopo |
|----------|---------|---------|
| `HARNESS_CANDIDATES` | `1` | Numero di harness candidati scritti per target. Imposta a 2 o 3 per una competizione in stile OSS-Fuzz-Gen. La fase di qualificazione esegue ciascuno per `QUALIFIER_SECONDS` e mantiene il migliore per % di righe. |
| `QUALIFIER_SECONDS` | `60` | Budget di tempo reale per candidato nella fase di qualificazione. |
| `FUZZ_PLATEAU_THRESHOLD_PCT` | `1.0` | Guadagno di copertura delle righe (in pp assoluti) al di sotto del quale due iterazioni consecutive sono considerate un plateau e il ciclo si interrompe anticipatamente. |
| `FUZZ_DASHBOARD_PORT` | `8765` | Porta per la dashboard live. |
| `FUZZ_NO_DASHBOARD` | (non impostata) | Imposta a `1` per saltare l'avvio della dashboard. |
| `FUZZ_RUNNER_TIMEOUT` | `1200` | Timeout del sottoprocesso per strumento in `fuzz_runner` (secondi). |
| `LOCAL_SHELL_TIMEOUT` | `180` | Timeout per comando in `local_shell` (secondi). |

Più le variabili standard dell'agente (`COPILOT_TOKEN`, `LOG_DIR`,
`FUZZ_CONTEXT_DIR`, …). Vedi il README nella radice del progetto per l'elenco completo.

---

## Estendere la pipeline

### Aggiungere un nuovo formato (mutator + dizionario)

1. Inserisci `dictionaries/<name>.dict` (formato AFL `-x`) e/o
   `dictionaries/<name>_mutator.c` (mutator personalizzato libFuzzer).
2. Registra in `_FORMAT_ASSETS` in fondo a `fuzz_runner.py`:   ```python
   "<name>": {
       "dictionary": "<name>.dict",
       "mutator": "<name>_mutator.c",
       "description": "Short one-liner about the format",
   },
  1. L'agente lo rileverà automaticamente tramite list_format_assets().

Aggiungere un nuovo strumento MCP

  1. Aggiungi una funzione decorata con @mcp.tool() in fuzz_context.py (per la persistenza) o fuzz_runner.py (per il lavoro in subprocess).
  2. Usa Annotated[type, Field(description=...)] per ogni argomento — la descrizione è ciò che vede l'LLM.
  3. Aggiungi uno unit test in tests/test_fuzz_context.py / tests/test_fuzz_runner.py. Invoca lo strumento tramite il suo attributo .fn (convenzione FastMCP).
  4. Fai riferimento al nuovo strumento nel user_prompt del taskflow YAML pertinente.

Aggiungere una nuova fase della pipeline

  1. Crea un nuovo YAML in src/seclab_taskflows/taskflows/fuzzing/. Usa uno dei file esistenti (ad es. triage_crashes.yaml) come modello.
  2. Collegalo in scripts/fuzzing/run_fuzzing.sh tra le due fasi esistenti appropriate.
  3. (Opzionale) aggiungi una sezione della dashboard specifica per la fase in scripts/fuzzing/dashboard.py.

Migrazione dello schema

Quando aggiungi una nuova tabella SQL:

  • Aggiungi il modello SQLAlchemy in fuzz_context_models.py.
  • Nient'altro è necessario — Base.metadata.create_all() viene chiamato all'inizializzazione dell'engine e crea automaticamente le nuove tabelle.

Quando aggiungi una nuova COLONNA a una tabella esistente:

  • Aggiorna il modello SQLAlchemy.
  • Aggiungi un blocco PRAGMA table_info + ALTER TABLE ADD COLUMN in _migrate() in fuzz_context.py in modo che i vecchi DB vengano aggiornati in modo trasparente.
  • Se la colonna viene letta dalla dashboard, aggiorna anche _migrate_if_writable() in scripts/fuzzing/dashboard.py.

Progetti di benchmark e risultati

benchmark/projects.yaml elenca i progetti di riferimento. Sono scelti in modo che l'intera pipeline v4+ possa essere eseguita end-to-end su un'immagine dev di codespace senza intervento umano.

#RepoPerché è interessanteNote
1tukaani-project/xzLibreria reale ad alto uso di parser (liblzma); ricca catena di filtri + superficie di parsing integer/VLIBaseline
2DaveGamble/cJSONPiccolo parser JSON C in singolo file; CMake banaleSmoke test rapido per la pipeline
3akheron/janssonLibreria JSON C compatta con punto di ingresso documentato json_loadb() per byte-bufferCMake; exec/sec molto veloce
4libexpat/libexpatParser XML streaming maturo; molte CVE storicheCMake o autotools
5kkos/onigurumaMotore regex; accetta pattern + subject dell'attaccanteAutotools; la compilazione del pattern è il percorso critico

Numeri di riferimento da un'esecuzione completa della pipeline v4 sull'immagine dev di codespace (≈32 min/target):

RepoTargetHarnessEsecuzioni AFLCrashVerdetti
tukaani-project/xz88480—
DaveGamble/cJSON66360—
akheron/jansson773510harness_bug, library_hardening, duplicate, needs_investigation
libexpat/libexpat33180—
kkos/oniguruma10106013vulnerability (×2 OOB read in regerror.c), library_hardening, harness_bug, non_reproducible

I risultati a zero crash di xz / cJSON / libexpat sono attesi: quei progetti sono pesantemente fuzzati upstream. I due findings classificati come vulnerability in oniguruma sono reali letture out-of-bounds nel percorso di codice di formattazione degli avvisi di onig_snprintf_with_pattern (lettura di un byte oltre pat_end quando il pattern termina con un backslash); i report markdown per-crash includono patch suggerite.

Per aggiungere un nuovo progetto di benchmark, aggiungi una voce in benchmark/projects.yaml e (opzionalmente) documenta il motivo in benchmark/README.md. Qualsiasi cosa che la fase esistente analyze_build_system possa compilare con clang + flag AFL++ è un candidato ragionevole. I parser, decoder e serializzatori in puro C tendono a funzionare meglio.


Limitazioni e insidie

  • Solo C / C++. AFL++ è un fuzzer a strumentazione nativa.
  • Dipendente dal build system. Progetti con build system non banali (regole Bazel personalizzate, libc vendorizzata, strumenti di build proprietari) potrebbero non riuscire a compilare con i flag clang/AFL. L'agente contrassegna quei target come BUILD_FAILED: e li salta.
  • Avvisi AFL nei Codespace. AFL++ richiede kernel.core_pattern=core e una modifica al CPU governor. In un Codespace questi non sono disponibili, quindi il taskflow esporta AFL_SKIP_CPUFREQ=1 e AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 per impostazione predefinita. AFL stampa avvisi ma trova comunque crash tramite la gestione degli abort in stile libFuzzer.
  • Limitato dal modello. La qualità di scrittura degli harness dell'agente è limitata dalla comprensione del codice target da parte del modello sottostante.
  • Splice del corpus dello smart mutator solo POSIX. L'operazione di corpus-splice usa <dirent.h>. Va bene per Linux/macOS; non compilerebbe su Windows.
  • Avvertenza sulla modalità stdin. I binari AFL compilati tramite compile_harness usano libAFLDriver in modalità argv. replay_under_asan e tmin quindi usano stdin_input=False per impostazione predefinita perché libAFLDriver entra in loop infinito quando pilotato via stdin.
  • generate_smart_mutator + generate_smart_mutators usano .format() di Python — ogni { / } letterale nel template C deve essere raddoppiato ({{ / }}). Se modifichi il template e inizi a vedere KeyError, ecco perché.

Avviso di sicurezza

Questo taskflow esegue afl-fuzz, clang, llvm-cov, e comandi di build arbitrari scelti dall'LLM, direttamente sull'host (nessun container). Un agente soggetto a prompt injection potrebbe in linea di principio fare qualsiasi cosa possa fare il tuo utente. Esegui solo:

  • all'interno di ambienti usa e getta (GitHub Codespaces, VM temporanee, ecc.),
  • senza privilegi elevati,
  • con accesso alla rete limitato a ciò di cui git, apt e il build system hanno bisogno.

Il toolbox local_shell NON è dietro un prompt di conferma — il taskflow è autonomo e viene eseguito senza un umano nel loop, quindi una conferma interattiva si bloccherebbe semplicemente per sempre. Ogni comando shell viene registrato in $LOG_DIR/mcp_local_shell.log per una revisione a posteriori.


Sviluppo: testing, linting, contribuzione```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:~
Convenzioni del codebase (vedi anche `benchmark/improvements.md` per la
versione di queste relative alla cronologia delle campagne):

- Usa `os.environ.get(NAME) or "default"` invece di
  `os.environ.get(NAME, "default")`. Le stringhe vuote derivanti dalla
  sostituzione dei template YAML verrebbero altrimenti restituite.
- Usa `X | None` (PEP 604) nelle nuove annotazioni, non `Optional[X]`.
- I test invocano gli strumenti MCP tramite `.fn(...)`, non direttamente
  il nome decorato.
- Evita i letterali `/tmp/...` nei test — usa la fixture pytest `tmp_path`
  (regola di lint `S108`).
- Tutti gli import inline all'interno dei metodi di test necessitano di
  `# noqa: PLC0415` se non puoi spostarli in cima al file (ad esempio
  quando vengono importati condizionatamente dopo un `pytest.skip`).
- Una singola asserzione per riga per i test di verità composti (regola
  di lint `PT018`).

Il tracker dei miglioramenti (`benchmark/improvements.md`) è il registro
persistente di ciò che è stato aggiunto alla pipeline attraverso le
versioni. Quando aggiungi una funzionalità sostanziale, aggiungi una
sezione lì che descriva cosa è cambiato, dove risiede e quali test la
proteggono.

---

## Glossario

- **AFL++** — Fuzzer greybox guidato dalla copertura; il motore di
  esecuzione qui.
- **libAFLDriver** — Libreria statica che consente agli harness di AFL++
  di usare la convenzione dell'entry-point di libFuzzer
  (`LLVMFuzzerTestOneInput`).
- **LCOV** — Formato standard di file di traccia della copertura del
  settore. Esportiamo verso di esso tramite
  `llvm-cov export -format=lcov` e lo analizziamo noi stessi.
- **`stack_top_hash`** — Un hash di 16 caratteri dei primi N frame
  normalizzati di uno stack trace ASan/UBSan. Usato per la
  deduplicazione dei crash.
- **Corpus persistente** — Directory per-harness in
  `<workspace>/corpus/harness_<id>/` che conserva gli input interessanti
  di AFL attraverso le iterazioni e le riesecuzioni della stessa
  campagna.
- **Smart mutator** — Un `LLVMFuzzerCustomMutator` i cui token di splice
  sono estratti dal codice sorgente del target stesso
  (`generate_smart_mutator`).
- **Custom mutator (libFuzzer)** — Una funzione C fornita dall'utente
  chiamata dal motore con piena libertà su come mutare un buffer; AFL++
  supporta la stessa ABI.
- **Strumento MCP** — Una funzione decorata con FastMCP che l'agente LLM
  può chiamare.
- **OSS-Fuzz / Fuzz-Introspector** — L'infrastruttura di fuzzing
  open-source di Google e il suo strumento complementare di analisi del
  call-graph/copertura. Diverse funzionalità di questo taskflow
  (mutatori per-formato, dedup-by-stack, report call-graph + API non
  toccate, harness multi-candidato) sono ispirate ad essi.

---

## Licenza

Questo progetto è concesso in licenza secondo i termini della licenza
open source MIT. Fare riferimento al file [LICENSE](https://github.com/githubsecuritylab/seclab-taskflows-fuzzing/blob/main/LICENSE.txt) per i
termini completi.

## Maintainer

Vedi [CODEOWNERS](https://github.com/githubsecuritylab/seclab-taskflows-fuzzing/blob/main/CODEOWNERS) o contatta il team GitHub Security Lab.

## Supporto

Vedi [SUPPORT.md](https://github.com/githubsecuritylab/seclab-taskflows-fuzzing/blob/main/SUPPORT.md) per dettagli su come ottenere aiuto con
questo progetto.

## Riconoscimenti

Questo progetto si basa sui concetti e sulle tecniche di
[AFL++](https://github.com/AFLplusplus/AFLplusplus),
[OSS-Fuzz](https://github.com/google/oss-fuzz) e
[Fuzz-Introspector](https://github.com/ossf/fuzz-introspector).
Scarica lo strumento