Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
seclab-taskflows-fuzzing — GitHub Security Lab Taskflow Agent로 구동되는 LLM 기반 퍼징 파이프라인 | Kitploit
도구/GitHubGitHub/githubsecuritylab/seclab-taskflows-fuzzing
Static AnalysisVulnerability ScannersDynamic Analysis (Sandboxing)Vulnerability AnalysisCode AnalysisScripting & AutomationFuzzingMalware AnalysisUtilities & Frameworks
AI Security
GitHubgithubsecuritylab/seclab-taskflows-fuzzing

seclab-taskflows-fuzzing

GitHub Security Lab Taskflow Agent로 구동되는 LLM 기반 퍼징 파이프라인

저장소 보기
1294일 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

Seclab Taskflows Fuzzing

네이티브 C/C++ 프로젝트를 위한 LLM 기반의 OSS-Fuzz 스타일 퍼징 파이프라인. 실행에는 AFL++, 커버리지에는 clang+lcov, 하네스 작성, 커버리지 피드백 결정, 트리아지, 리포팅에는 LLM 에이전트를 사용합니다.

  • 완전 자율: GitHub 저장소를 주면 대상 식별부터 취약점 보고까지 모든 것을 처리합니다.
  • OSS-Fuzz 스타일 기법: 포맷별 뮤테이터/딕셔너리, 구조 인식 토큰 스플라이싱, 커버리지 기반 하네스 개선.
  • 익스플로잇 가능성 판정과 제안 패치가 포함된 기계 판독 가능한 크래시 보고서를 생성합니다.
  • 실시간 캠페인 모니터링을 위한 라이브 HTML 대시보드.
  • Python(taskflows/toolboxes/configs)으로 작성되었으며 AFL++용 C 하네스 생성을 포함합니다.
  • 상태: 활발한 개발 중.

배경

이 저장소는 GitHub Security Lab Taskflow Agent용 퍼징 태스크플로우를 포함합니다. 몇 가지 공유 빌딩 블록 (fetch_source_code 태스크플로우, local_file_viewer / gh_file_viewer 툴박스, 기본 model_config)을 위해 seclab-taskflows 동반 저장소에 의존합니다 — 이들은 Python 의존성으로 자동 설치됩니다.

기여를 환영합니다! 가이드라인은 CONTRIBUTING.md를 참조하세요.

요구 사항

  • Python 3.11+
  • apt에 접근할 수 있는 Linux 환경(또는 Codespace)
  • 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)

---

## 이것은 무엇인가

이 태스크플로는 완전 자율 퍼징 파이프라인입니다. 네이티브 C/C++ 프로젝트의
GitHub 저장소가 주어지면 다음을 수행합니다:

1. AFL++ + clang/llvm/lcov + ctags/cscope/graphviz가 없으면 설치하고,
2. 소스를 가져오고,
3. 후보 퍼즈 대상(파서, 디코더, 검증기 등)을 식별하고,
4. 빌드 시스템을 분석하고,
5. 대상당 하나 이상의 하네스 후보를 작성하고, 각각을
   AFL 계측 `.afl` 바이너리와 커버리지 계측 `.cov` 바이너리로 모두 빌드하고,
6. (선택적으로) 60초 커버리지로 후보를 검증하고 최선의 것을 유지하고,
7. 시간 예산을 두 배로 늘려가며 퍼즈/커버리지/개선 루프를 실행하고,
8. 모든 크래시를 트리아지하고, 이전에 알려진 크래시가 여전히 재현되는지 확인하고,
   판정, 익스플로잇 가능성, 제안 패치, 회귀 테스트 스케치를 포함한
   크래시별 마크다운 취약점 보고서를 작성하고,
9. 다음 캠페인을 위한 Fuzz-Introspector 스타일 호출 그래프 + 미접촉 API 보고서를
   작성하고,
10. 모든 것을 라이브 HTML 대시보드에 게시합니다.

이 파이프라인은 정신적으로 **OSS-Fuzz 스타일**입니다: 동일한 기법 중 상당수
(포맷별 뮤테이터와 사전, 구조 인식 토큰 스플라이싱, 커버리지 기반 하네스 개선,
기계 판독 가능 보고서, 중복 제거된 스택 해시 크래시)를 사용하지만,
훨씬 더 작고 자체 완결적입니다.

---

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

이것이 전체 인터페이스입니다. 스크립트는 자율적으로 동작하며, 첫 실행 시 AFL++를 설치한 다음 나머지 taskflow를 진행합니다. 출력 파일은 ~/.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 도구가 실행을 담당한다. 에이전트는 무엇을 퍼징할지, 어떤 하네스를 작성할지, 어떤 공백을 다음에 추적할지를 결정하고, MCP 도구는 run_afl_for, compile_harness, store_crash 등을 노출할 뿐이다.
  • 가능한 곳에서는 멱등성. 동일한 저장소에 대해 파이프라인을 재실행하면 대상/하네스/실행을 중복 생성하지 않고 upsert한다. 이것이 영구 코퍼스와 캠페인 간 이월이 작동하게 만드는 원동력이다.
  • 하네스당 두 개의 바이너리. AFL의 엣지 계측은 사람이 읽을 수 있는 커버리지 보고서에 적합하지 않으므로, 각 하네스는 두 번 빌드된다: 한 번은 afl-clang-lto -fsanitize=address,undefined로 (.afl 바이너리), 한 번은 clang -fprofile-instr-generate -fcoverage-mapping으로 (.cov 바이너리). .afl 바이너리는 퍼징을 수행하고, .cov 바이너리는 AFL 큐를 재생하여 실제 소스 라인/함수/분기 커버리지를 생성한다.

파이프라인, 단계별로

#단계Taskflow YAML
1AFL++ + 도구 설치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초기 하네스 작성 (요청 시 ×N 후보)seclab_taskflows_fuzzing.taskflows.fuzzing.write_initial_harnesses
5b하네스 빌드 (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호출 그래프 + 미접촉 API 보고서 작성seclab_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이다. 단계들은 fuzz_context.db의 SQLite 데이터베이스를 통해서만 통신한다 — 인메모리 핸드오프는 없다.


커버리지 피드백 루프

이것이 파이프라인의 핵심이다. 시간 예산은 매 반복마다 두 배가 된다:``` 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. LCOV 트레이스파일과 HTML 리포트를 생성하기 위해 `run_coverage(cov_binary_path, inputs_dir=<run>/default/queue, output_dir=<run>/coverage)`를 호출한다.
4. `coverage_report` 행과 미커버 항목별 `coverage_gap` 행을 영속화하기 위해 `store_coverage_from_lcov(run_id, lcov_path, html_path)`를 호출한다.
5. AFL의 반복 큐를 영속 코퍼스에 병합하고 크기를 제한적으로 유지하기 위해 `cmin`을 실행하는 `fold_queue_into_persistent_corpus(...)`를 호출한다.
6. `get_coverage_summary` + `get_coverage_gaps`를 읽은 뒤, 다음 중 하나를 수행한다:
   - 미커버 분기에 도달하기 위해 (`coverage_feedback`으로 태그된) 새 시드를 추가하거나,
   - 추가 API를 호출하도록 하네스 소스를 편집하거나,
   - AFL이 가드를 만족시키는 데 필요한 매직 상수에 대한 사전 항목을 자동 추가하기 위해 `enrich_dictionary_from_uncovered(...)`를 호출하거나,
   - 해당 갭을 건너뛴다 (콜드 에러 경로 / 벤더 코드).
7. 대시보드의 반복 타임라인이 무엇이 변경되었는지 추적할 수 있도록 `store_iteration_note(repo, iteration_number, harness_id, note=<one line summary>)`를 호출한다.

**정체 감지.** 두 번의 연속 반복이 모두 라인 커버리지의 절대 퍼센트 포인트 기준으로 `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/`에 넣은 다음, `fuzz_runner.py` 하단의 `_FORMAT_ASSETS` 맵에 등록한다.

### 2. 소스 인식 (프로젝트별) 스마트 뮤테이터

익숙하지 않은 포맷이거나 더 강력한 프로젝트별 토큰을 원할 때마다, `generate_smart_mutator`는 타깃 저장소의 자체 `.c`/`.h` 파일을 스캔하여 스플라이스 사전이 다음에서 추출된 `LLVMFuzzerCustomMutator` C 파일을 생성한다:

- 알파벳 문자가 3개 이상인 문자열 리터럴 (컴파일러/라이선스 노이즈, 경로, 헤더, asm 제약, 포맷 지정자를 필터링한 후),
- `#define`, `case`, `enum`에서 가져온 32비트 숫자 상수 (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. 코퍼스 스플라이스 연산

`corpus_dir`이 `generate_smart_mutator`에 전달되면, 생성된 C는 코퍼스 스플라이스 연산자도 갖게 된다: 첫 호출 시 해당 디렉터리에서 최대 64개 파일을 로드하고(각 4 KiB로 제한), 그 이후로는 해당 파일의 임의 하위 영역을 변이된 입력에 스플라이스할 수 있다. 이는 AFL의 기본 havoc이 잘 수행하지 못하는 재조합 스타일 연산자를 뮤테이터에 제공한다. `get_persistent_corpus_dir(...)`와 함께 사용하면 스플라이스 라이브러리가 "AFL이 이미 발견한 것을 리믹스"하게 된다.

---

## 반복 및 캠페인 전반에 걸친 영속 코퍼스

각 하네스는 다음 위치에 안정적인 코퍼스 디렉터리를 가진다:```
<workspace>/corpus/harness_<id>/

fuzz_iteration가 run_afl_for의 seed_dir로 사용하는 것이 바로 이것이다 (<harness>/seeds가 아니라). 매 반복이 끝날 때마다 fold_queue_into_persistent_corpus(...)가 AFL의 반복 큐를 이 디렉터리로 병합하고 afl-cmin을 실행하여 크기를 제한한다.

그 결과: 어제의 큐가 오늘의 실행으로 이어지고, 같은 프로젝트의 재실행 간에도 유지된다. 캠페인을 중지하고 재시작해도 진행 상황이 손실되지 않는다.


트리아지 및 취약점 보고서

퍼징/커버리지/개선 루프가 끝나면 세 단계가 자동으로 실행된다:

1. triage_crashes

<run>/default/crashes/에 있는 모든 크래시 파일에 대해:

  • afl-tmin으로 입력을 최소화하고,
  • replay_under_asan으로 스택 트레이스와 stack_top_hash를 캡처한다 (상위 N개의 정규화된 프레임; 템플릿, libcxx 인라인 네임스페이스, 익명 네임스페이스, LTO 숫자 접미사가 제거되어 의미상 동일한 크래시가 동일하게 해시된다),
  • 해시로 중복 제거하고, 버그 클래스 분류 + 신뢰도 노트(높음 / 중간 / 낮음)와 함께 crash 행을 저장한다.

2. confirm_fixed_crashes

이전에 분류된 모든 크래시(판정이 아직 fixed/duplicate/non_reproducible이 아닌 것)를 현재 AFL+ASan 바이너리로 재실행한다. 더 이상 크래시가 발생하지 않으면 verdict="fixed"로 표시한다. 마지막 캠페인 이후 업스트림 수정이 적용된 프로젝트에 대해 캠페인을 재실행할 때 유용하다.

3. write_vuln_reports

각 고유 크래시에 대해 에이전트는 하네스 소스 + 크래시가 발생한 함수의 소스를 읽고, 공개 API로부터의 호출 체인을 따라간 다음, OSS-Fuzz 스타일의 열 가지 판정 중 하나를 할당하고 마크다운 취약점 보고서를 작성한다:

판정의미
vulnerability실제 취약점이며, 공개 API를 통해 악용 가능
library_hardening실제 버그이지만 현실적인 공개 API 경로가 없음; 라이브러리가 스스로를 방어해야 함
harness_bug버그가 라이브러리가 아닌 우리 하네스에 있음
non_reproducible최소화된 입력에서 재실행해도 크래시가 재현되지 않음
oom메모리 부족; 공격자가 제어 가능한 크기가 무제한인 경우에만 취약점
timeout알고리즘 폭발로 인한 DoS
assertion_failureassert() 발생; 보안 관련성은 다양함
fixedconfirm_fixed_crashes에 의해 설정됨: 입력이 더 이상 재현되지 않음
duplicate다른 스택 해시를 가진 다른 크래시와 동일한 근본 원인
needs_investigation판단할 수 없음; 사람의 검토를 위해 플래그됨

각 취약점 보고서에는 다음이 포함된다:

  • 판정 + 버그 클래스 + CWE + 심각도 + 신뢰도
  • file:line 참조가 포함된 근본 원인 분석
  • 공개 API로부터의 도달 가능성 (구체적인 호출 체인)
  • 악용 가능성 평가 (읽기 vs. 쓰기, 공격자 제어, 완화책)
  • 통합 diff로 제안된 수정 ("검토 필요"로 표시됨)
  • 회귀 테스트 스케치

라이브 대시보드

대시보드는 run_fuzzing.sh에 의해 백그라운드에서 자동으로 시작된다. FUZZ_NO_DASHBOARD=1로 비활성화하고, FUZZ_DASHBOARD_PORT로 포트를 재정의한다 (기본값 8765).

Codespace에서는 포트 8765가 자동으로 포워딩된다 — 포워딩된 URL을 아무 브라우저에서나 열면 된다. 페이지는 5초마다 자동 새로고침되며 다음을 표시한다:

  • 판정 요약 칩 — 판정 카테고리별 개수, 총 실행 수, 경로, 총 실행 횟수, 크래시
  • 라이브 "실행 중" 펄스 표시기 — 진행 중인 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`의 테이블 (SQLAlchemy를 통한 SQLite):

| 테이블 | 주요 컬럼 |
|-------|--------------------|
| `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` |

스키마 마이그레이션은 `fuzz_context.py`의 `_migrate()`에 있습니다. 새 TABLE은
`Base.metadata.create_all()`에 의해 자동 생성되며, 새 COLUMN만
PRAGMA 기반 `ALTER TABLE`이 필요합니다.

---

## 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` — `.cov` 바이너리에 대해 AFL 큐를 재생하고 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` | 타깃당 작성되는 후보 하네스 수. OSS-Fuzz-Gen 스타일 경쟁을 위해 2 또는 3으로 설정합니다. 검증 단계에서 각 후보를 `QUALIFIER_SECONDS` 동안 실행하고 라인 % 기준으로 최고를 유지합니다. |
| `QUALIFIER_SECONDS` | `60` | 검증 단계에서 후보당 실시간 예산. |
| `FUZZ_PLATEAU_THRESHOLD_PCT` | `1.0` | 두 연속 반복이 정체로 간주되어 루프가 조기 중단되는 라인 커버리지 증가량 (절대 pp). |
| `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. `fuzz_runner.py` 하단의 `_FORMAT_ASSETS`에 등록합니다:   ```python
   "<name>": {
       "dictionary": "<name>.dict",
       "mutator": "<name>_mutator.c",
       "description": "Short one-liner about the format",
   },
  1. 에이전트가 list_format_assets()를 통해 자동으로 선택합니다.

새로운 MCP 도구 추가

  1. fuzz_context.py(영속성용) 또는 fuzz_runner.py(서브프로세스 작업용)에 @mcp.tool() 데코레이터가 적용된 함수를 추가합니다.
  2. 모든 인자에 Annotated[type, Field(description=...)]를 사용합니다 — description이 LLM이 보는 내용입니다.
  3. tests/test_fuzz_context.py / tests/test_fuzz_runner.py에 단위 테스트를 추가합니다. 도구의 .fn 속성을 통해 호출합니다(FastMCP 관례).
  4. 관련 taskflow YAML의 user_prompt에서 새 도구를 참조합니다.

새로운 파이프라인 단계 추가

  1. src/seclab_taskflows/taskflows/fuzzing/에 새 YAML을 생성합니다. 기존 파일 중 하나(예: triage_crashes.yaml)를 템플릿으로 사용합니다.
  2. scripts/fuzzing/run_fuzzing.sh의 올바른 두 기존 단계 사이에 연결합니다.
  3. (선택 사항) scripts/fuzzing/dashboard.py에 단계별 대시보드 섹션을 추가합니다.

스키마 마이그레이션

새로운 SQL 테이블을 추가할 때:

  • fuzz_context_models.py에 SQLAlchemy 모델을 추가합니다.
  • 그 외에는 아무것도 필요하지 않습니다 — 엔진 초기화 시 Base.metadata.create_all()이 호출되어 새 테이블이 자동으로 생성됩니다.

기존 테이블에 새로운 COLUMN을 추가할 때:

  • SQLAlchemy 모델을 업데이트합니다.
  • fuzz_context.py의 _migrate()에 PRAGMA table_info + ALTER TABLE ADD COLUMN 블록을 추가하여 기존 DB가 투명하게 업그레이드되도록 합니다.
  • 대시보드에서 해당 컬럼을 읽는 경우, scripts/fuzzing/dashboard.py의 _migrate_if_writable()도 업데이트합니다.

벤치마크 프로젝트 및 결과

benchmark/projects.yaml은 참조 프로젝트를 나열합니다. 이들은 사람의 개입 없이 codespace 개발 이미지에서 전체 v4+ 파이프라인이 엔드투엔드로 실행될 수 있도록 선택되었습니다.

#Repo흥미로운 이유비고
1tukaani-project/xz실제 파서 중심 라이브러리(liblzma); 풍부한 필터 체인 + 정수/VLI 파싱 표면기준
2DaveGamble/cJSON작은 단일 파일 C JSON 파서; 간단한 CMake파이프라인 빠른 스모크 테스트
3akheron/jansson문서화된 json_loadb() 바이트 버퍼 진입점이 있는 컴팩트한 C JSON 라이브러리CMake; 매우 빠른 exec/sec
4libexpat/libexpat성숙한 스트리밍 XML 파서; 많은 역사적 CVECMake 또는 autotools
5kkos/oniguruma정규식 엔진; 공격자 패턴 + 대상 문자열을 받음Autotools; 패턴 컴파일이 핫 패스

codespace 개발 이미지에서 전체 v4 파이프라인 실행 시 참조 수치 (대상당 약 32분):

RepoTargetsHarnessesAFL runsCrashesVerdicts
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

xz / cJSON / libexpat의 크래시 제로 결과는 예상된 것입니다: 해당 프로젝트들은 업스트림에서 집중적으로 퍼징됩니다. oniguruma에서 vulnerability로 분류된 두 건의 발견은 onig_snprintf_with_pattern의 경고 포맷팅 코드 경로에서 발생한 실제 범위 초과 읽기입니다(패턴이 백슬래시로 끝날 때 pat_end를 1바이트 초과하여 읽음). 크래시별 markdown 보고서에는 제안된 패치가 포함되어 있습니다.

새로운 벤치마크 프로젝트를 추가하려면 benchmark/projects.yaml에 항목을 추가하고 (선택 사항으로) 그 이유를 benchmark/README.md에 문서화합니다. 기존 analyze_build_system 단계가 clang + AFL++ 플래그로 빌드할 수 있는 것이라면 합리적인 후보입니다. 순수 C 파서, 디코더, 직렬화기가 가장 잘 작동하는 경향이 있습니다.


제한 사항 및 주의점

  • C / C++ 전용. AFL++는 네이티브 계측 퍼저입니다.
  • 빌드 시스템 의존적. 사소하지 않은 빌드 시스템(사용자 정의 Bazel 규칙, 벤더링된 libc, 독점 빌드 도구)을 가진 프로젝트는 clang/AFL 플래그로 빌드하지 못할 수 있습니다. 에이전트는 해당 타겟을 BUILD_FAILED:로 표시하고 건너뜁니다.
  • Codespace AFL 경고. AFL++는 kernel.core_pattern=core와 CPU governor 조정을 원합니다. Codespace에서는 이를 사용할 수 없으므로 taskflow는 기본적으로 AFL_SKIP_CPUFREQ=1과 AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1을 내보냅니다. AFL은 경고를 출력하지만 libFuzzer 스타일 abort 처리로 크래시를 여전히 찾습니다.
  • 모델 한계. 에이전트의 하네스 작성 품질은 대상 코드에 대한 기반 모델의 이해도에 의해 제한됩니다.
  • POSIX 전용 스마트 뮤테이터 코퍼스 스플라이스. 코퍼스 스플라이스 연산은 <dirent.h>를 사용합니다. Linux/macOS에서는 문제없지만 Windows에서는 컴파일되지 않습니다.
  • stdin 모드 주의사항. compile_harness로 빌드된 AFL 바이너리는 argv 모드에서 libAFLDriver를 사용합니다. 따라서 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이 선택한 임의의 빌드 명령을 호스트에서 직접(컨테이너 없이) 실행합니다. 프롬프트 인젝션이 발생한 에이전트는 원칙적으로 사용자가 할 수 있는 모든 것을 할 수 있습니다. 다음 조건에서만 실행하십시오:

  • 일회용 환경(GitHub Codespaces, 일회용 VM 등) 내부에서,
  • 상승된 권한 없이,
  • 네트워크 접근을 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, "default")` 대신 `os.environ.get(NAME) or "default"`를 사용하세요. 그렇지 않으면 YAML 템플릿 치환으로 인한 빈 문자열이 반환될 수 있습니다.
- 새 애노테이션에는 `Optional[X]`가 아닌 `X | None` (PEP 604)을 사용하세요.
- 테스트는 데코레이트된 이름이 아니라 `.fn(...)`을 통해 MCP 도구를 호출합니다.
- 테스트에서 `/tmp/...` 리터럴을 피하세요 — `tmp_path` pytest 픽스처를 사용하세요 (lint 규칙 `S108`).
- 테스트 메서드 내부의 모든 인라인 임포트는 파일 상단으로 옮길 수 없는 경우 (예: `pytest.skip` 이후 조건부로 임포트되는 경우) `# noqa: PLC0415`가 필요합니다.
- 복합 진리 테스트의 경우 한 줄에 하나의 단언만 사용하세요 (lint 규칙 `PT018`).

개선 사항 추적기(`benchmark/improvements.md`)는 버전 전반에 걸쳐 파이프라인에 추가된 내용을 지속적으로 기록하는 로그입니다. 실질적인 기능을 추가할 때는 변경된 내용, 위치, 그리고 이를 보호하는 테스트를 설명하는 섹션을 그곳에 추가하세요.

---

## 용어집

- **AFL++** — 커버리지 기반 그레이박스 퍼저; 여기서의 실행 엔진입니다.
- **libAFLDriver** — AFL++ 하네스가 libFuzzer 진입점 규약(`LLVMFuzzerTestOneInput`)을 사용할 수 있게 해주는 정적 라이브러리입니다.
- **LCOV** — 업계 표준 커버리지 트레이스파일 형식입니다. 우리는 `llvm-cov export -format=lcov`를 통해 내보내고 직접 파싱합니다.
- **`stack_top_hash`** — ASan/UBSan 스택 트레이스의 상위 N개 정규화된 프레임에 대한 16자 해시입니다. 크래시 중복 제거에 사용됩니다.
- **영구 코퍼스** — `<workspace>/corpus/harness_<id>/`에 위치한 하네스별 디렉터리로, 동일한 캠페인의 반복 및 재실행에 걸쳐 AFL의 흥미로운 입력을 유지합니다.
- **스마트 뮤테이터** — 스플라이스 토큰이 대상 자체의 소스 코드에서 추출되는 `LLVMFuzzerCustomMutator`입니다 (`generate_smart_mutator`).
- **커스텀 뮤테이터 (libFuzzer)** — 버퍼를 어떻게 변이할지에 대한 완전한 자유를 가지고 엔진이 호출하는 사용자 제공 C 함수입니다; AFL++는 동일한 ABI를 지원합니다.
- **MCP 도구** — LLM 에이전트가 호출할 수 있는 FastMCP 데코레이트된 함수입니다.
- **OSS-Fuzz / Fuzz-Introspector** — Google의 오픈소스 퍼징 인프라와 그 동반 콜 그래프/커버리지 분석 도구입니다. 이 태스크플로우의 여러 기능(형식별 뮤테이터, 스택별 중복 제거, 콜 그래프 + 미접촉 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)의 개념과 기법을 기반으로 구축되었습니다.
도구 다운로드