[미래내일 일경험] 테크노트 - 8주차
FuzzGate v1.0 통합 검증 및 최종 산출물 정리 | 2026.05.18 ~ 05.24
| 프로젝트명 | AI 기반 퍼징을 활용한 취약점 탐지 및 검증 자동화 시스템 (FuzzGate) | ||
| 팀명 | The First | 작성자 | 이우곤 |
| 담당 역할 | 하네스 개발, 퍼징 파이프라인 구축, 포맷 연동 구현 | ||
📌 1. 금주 학습 목표
- FuzzGate v1.0 통합 테스트 수행 (3개 백엔드 × 3개 타깃 어댑터 매트릭스 검증)
- High 심각도 4건의 책임 있는 공개 절차에 따른 1차 제출 진행
- 단일 ZIP 번들 일괄 출력 기능 통합 및 번들 무결성 해시 이중 기록 정착
- CLI 사용자 매뉴얼 작성 및 컨테이너 안전 옵션 표준 프리셋 문서화
- SafeTensors numpy 변환 경로의 dtype 매핑 이슈 추가 검증 및 리포트 작성
- 최종 결과보고서 작성 (정량 지표 정리, 산출물 목록, 향후 확장 항목 명시)
📖 2. 학습 및 수행 내용
2-1. FuzzGate v1.0 통합 매트릭스 검증
이번 주의 가장 큰 작업은 3개 백엔드(local-harness, libFuzzer, AFL++) × 3개 타깃 어댑터(GGUF, ONNX, SafeTensors)의 총 9가지 조합을 모두 검증하여 v1.0 출시 기준에 부합하는지 확인하는 것이었다. 각 조합에 대해 1시간 시범 퍼징을 수행하면서 백엔드 교체가 후속 단계(재현 검증, Triage, 리포트 생성)에 영향을 주지 않는지를 정량적으로 측정하였다.
| 백엔드 × 타깃 | GGUF | ONNX | SafeTensors |
|---|---|---|---|
| local-harness | ✓ PASS | ✓ PASS | ✓ PASS |
| libFuzzer | ✓ PASS | ✓ PASS | ✓ PASS |
| AFL++ | ✓ PASS | ✓ PASS | △ 조건부 PASS |
9가지 조합 중 8개는 완전히 통과하였으며, AFL++ × SafeTensors 조합만 조건부 PASS로 분류되었다. 이는 SafeTensors의 공식 파서가 Rust로 작성되어 있어 AFL++의 fork 모델로는 인스트루멘테이션이 비효율적인 측면 때문이며, cargo-fuzz가 더 적합한 백엔드라는 점을 문서화하여 운영자에게 안내하도록 하였다. 이는 본질적 결함이 아닌 백엔드-타깃 조합의 특성에 가까운 사안이다.
# scripts/integration_matrix.sh - 통합 매트릭스 검증 자동화
#!/usr/bin/env bash
set -euo pipefail
BACKENDS=("local-harness" "libfuzzer" "aflpp")
TARGETS=("gguf" "onnx" "safetensors")
RESULTS_DIR="./integration_results"
for backend in "${BACKENDS[@]}"; do
for target in "${TARGETS[@]}"; do
echo "[*] Testing: $backend x $target"
fuzzgate run \
--backend "$backend" \
--target "$target" \
--workers 2 \
--timeout 1h \
--seeds "./corpus/$target" \
--output "$RESULTS_DIR/${backend}_${target}" \
|| {
echo "[!] FAILED: $backend x $target"
continue
}
# 후속 파이프라인 통과 확인 (triage + report)
fuzzgate triage --input "$RESULTS_DIR/${backend}_${target}"
fuzzgate report --input "$RESULTS_DIR/${backend}_${target}"
echo "[+] PASSED: $backend x $target"
done
done
✓ 통합 매트릭스의 의의
9가지 조합 모두에서 동일한 CLI 인터페이스로 실행되고, 동일한 형식의 표준 산출물이 생성된다는 것을 데이터로 확인한 것은 "느슨한 결합과 표준 인터페이스"라는 1주차 설계 원칙이 실제로 구현되었음을 증명하는 결과이다. 새로운 백엔드나 타깃을 추가할 때도 어댑터 구현만 추가하면 8개 후속 모듈이 그대로 동작한다는 확장성을 확보했다.
2-2. 단일 ZIP 번들 일괄 출력 및 이중 무결성 해시
6주차에 구현한 증거 번들은 케이스별로 개별 zip 파일을 생성하는 구조였으나, 다수 케이스를 한 번에 외부로 전달할 때는 단일 패키지가 더 편리하다는 운영 데이터가 누적되었다. 이번 주에는 모든 reproduced 케이스를 단일 ZIP 번들로 일괄 출력하는 기능을 통합하였다.
// crates/reporter/src/bundle.rs - 단일 ZIP 번들 생성 및 이중 해시
pub fn build_master_bundle(
cases: &[ReproducedCrash],
output_path: &Path,
) -> Result<BundleManifest> {
let mut zip = ZipWriter::new(File::create(output_path)?);
let mut manifest = BundleManifest::new();
for case in cases {
// 1) 케이스별 디렉터리 생성 (poc/, repro.sh, meta.json, ...)
let case_dir = format!("cases/{}/", case.id);
write_case_files(&mut zip, &case_dir, case)?;
// 2) 케이스 단위 해시 (압축 직전 시점)
let case_hash = sha256_of_case(case)?;
manifest.add_case(&case.id, &case_hash);
}
// 3) manifest.json 자체도 번들에 포함
zip.start_file("manifest.json", FileOptions::default())?;
zip.write_all(&serde_json::to_vec_pretty(&manifest)?)?;
zip.finish()?;
// 4) 번들 자체의 해시 (압축 직후 시점) - 별도 파일로 보관
let bundle_hash = sha256_file(output_path)?;
let hash_file = output_path.with_extension("zip.sha256");
fs::write(&hash_file, format!("{} {}\n",
bundle_hash, output_path.file_name().unwrap().to_string_lossy()))?;
Ok(manifest)
}
이중 무결성 정책은 다음 두 가지 시점에 해시를 산출한다.
- 케이스 단위 해시 (압축 직전): 각 케이스의
meta.json에 기록되어, 케이스 내부의 파일 조합이 변경되지 않았음을 검증 - 번들 단위 해시 (압축 직후): 별도의
.zip.sha256파일로 보관되어, 외부 전달 과정에서 zip 파일 자체가 변조되지 않았음을 검증
또한 번들 파일명에 해시 일부(앞 8자)를 포함하도록 명명 규칙을 정착시켰다. 예를 들어 fuzzgate-bundle-v1.0-20260520-a3f9c2b1.zip처럼 외부 분석자가 받은 파일이 어떤 버전의 번들인지 빠르게 식별할 수 있게 된다.
2-3. 1차 책임 있는 공개 절차 진행
7주차에 검토를 완료한 High 심각도 4건에 대해, 각 프로젝트의 보안 정책 절차에 따라 1차 제출을 진행하였다. 제출은 본인이 직접 수행하지 않고 신숙우 팀장이 팀 대표로 진행하였으며, 본인은 제출 리포트의 기술적 정확성을 최종 검토하는 역할을 담당하였다.
| 크래시 ID | 대상 프로젝트 | 제출 채널 | 상태 |
|---|---|---|---|
| GGUF-001 | llama.cpp | SECURITY.md 권고 채널 | 접수 확인 |
| GGUF-003 | llama.cpp | SECURITY.md 권고 채널 | 접수 확인 |
| ONNX-D-001 | onnxruntime | Microsoft MSRC | 접수 확인 (티켓 번호 부여) |
| ONNX-D-004 | onnxruntime | Microsoft MSRC | 접수 확인 (티켓 번호 부여) |
⚠️ 책임 있는 공개 정책 준수
- 90일 비공개 기간: 제출일로부터 90일 동안 취약점 세부사항을 외부에 공개하지 않음
- 본 테크노트 처리: 크래시 ID 외 세부 코드 위치, 정확한 트리거 입력, ASan 로그 원본은 본 시리즈에 포함하지 않음
- 커뮤니케이션 단일 창구: 메인테이너와의 연락은 신숙우 팀장이 담당하여 정보 일관성 유지
- 패치 검증 협력: 메인테이너 측에서 패치 후보를 공유할 경우 본인이 동일 입력으로 재현 테스트를 수행하기로 협의
2-4. CLI 사용자 매뉴얼 및 안전 옵션 표준 프리셋 문서화
v1.0 출시 산출물로 외부 사용자가 도구를 운영할 수 있도록 CLI 매뉴얼과 컨테이너 안전 옵션 표준 프리셋 문서를 작성하였다. 매뉴얼은 다음 4개 핵심 명령을 중심으로 구성하였다.
# 1) run - 퍼징 실행 (백엔드/타깃/시드 지정)
fuzzgate run \
--backend <local-harness|libfuzzer|aflpp> \
--target <gguf|onnx|safetensors> \
--workers <N> \
--timeout <duration> \
--seeds <corpus_dir> \
--output <result_dir> \
[--safety-preset standard|strict|relaxed]
# 2) triage - 재현 검증 및 단계 라벨 산출
fuzzgate triage \
--input <result_dir> \
--repeat 3 \
[--label-strict]
# 3) report - reproduced 케이스에 대해 리포트 자동 생성
fuzzgate report \
--input <result_dir> \
--template hackerone-5section \
--bundle <output.zip>
# 4) replay - 증거 번들 한 줄 재현
fuzzgate replay --bundle <bundle.zip> --case <case_id>
컨테이너 안전 옵션 표준 프리셋은 3단계로 정의하였다. 각 프리셋이 적용된 안전 옵션 목록은 케이스의 meta.json에 함께 기록되어, 외부 분석자가 재현할 때 동일한 환경을 구성할 수 있도록 한다.
| 프리셋 | 주요 옵션 | 사용 시나리오 |
|---|---|---|
| standard | cap_drop=ALL, network=none, mem=2g | 일반 운영 환경 (기본값) |
| strict | standard + read-only, pids_limit=256, seccomp 강화 | 신뢰도 높은 재현 검증 필요 시 |
| relaxed | cap_drop 최소화, ptrace 허용 | 디버깅용 (외부 보고 비추천) |
2-5. SafeTensors numpy 변환 경로 추가 검증
7주차에 발견한 SafeTensors Python 바인딩의 dtype 매핑 이슈를 24시간 장시간 퍼징으로 재검증하였다. 결과적으로 동일 패턴의 변환 경로 이슈가 추가로 2건 더 발견되어 총 4건으로 정리되었으며, 모두 Triage를 거쳐 고유 크래시로 정규화되었다.
발견된 4건 중 2건은 Rust 코어가 아닌 Python 바인딩 계층에서만 발생하는 케이스로, "안전한 코어를 감싸는 외피의 검증 누락"이라는 가설을 데이터로 다시 한 번 확인하였다. 이 케이스들은 메모리 안전성 위반이 아니라 변환 단계의 입력 검증 누락에 해당하므로, 별도 카테고리("Binding Validation")로 리포트되어 멘토님이 권고한 분류 방식을 적용하였다.
🔍 v1.0의 최종 누적 결과 (8주 종합)
| 총 누적 퍼징 시간 | 약 480시간 (3개 타깃 합산) |
| 예비 크래시 수집 | 총 64건 |
| 고유 크래시 (Triage 후) | 총 22건 |
| reproduced 라벨 (리포트 생성) | 총 16건 |
| 1차 책임 있는 공개 진행 | High 심각도 4건 |
2-6. 최종 결과보고서 작성 및 향후 확장 항목 정리
8주간의 모든 활동을 정리한 최종 결과보고서를 팀 전체가 함께 작성하였다. 본인은 하네스 개발, 퍼징 파이프라인 구축, 포맷 연동 구현 영역에 해당하는 기술 섹션과 정량 지표 항목을 담당하였다. 결과보고서에는 v1.0 산출물 목록과 함께 후속 단계에서 발전시킬 수 있는 향후 확장 항목을 명시하였다.
📦 FuzzGate v1.0 최종 산출물 (본인 담당 영역)
- 다중 백엔드(local-harness / libFuzzer / AFL++) 통합 CLI
- 다중 타깃 어댑터(GGUF / ONNX / SafeTensors)
- 구조 인지 변이 전략 (단일 필드 + cross-field + 양자화 메타데이터)
- 하네스 빌드 자동화 (CMake + Cargo build.rs 통합)
- 하네스 내부 watchdog/timeout 로직
- 시드 코퍼스 미니마이제이션 워크플로우
- HarnessFingerprint JSON 출력 (재현 가능성 보강)
🚀 향후 확장 항목 (본인 담당 영역)
- exploitability signal 분류기 가중치 재조정 (정량 지표 누적 후)
- cargo-fuzz 백엔드 정식 추가 (현재는 SafeTensors 전용 임시 구현)
- 타깃 어댑터 확장 (PyTorch pickle, TensorFlow SavedModel 등)
- 구조 인지 변이의 PoC 단계 전략을 정식 모듈로 승격
- 분산 퍼징 지원 (다중 호스트 작업 큐 도입)
🛠️ 3. 수행 활동
3-1. 개인 수행 활동
- FuzzGate v1.0 통합 매트릭스 검증 수행 (9개 조합 중 8개 PASS, 1개 조건부 PASS)
- 통합 매트릭스 자동화 스크립트(
integration_matrix.sh) 작성 및 CI 통합 - 단일 ZIP 번들 일괄 출력 기능 통합 (Reporter 모듈과 협업)
- 이중 무결성 해시 정책 정착 (케이스 단위 + 번들 단위, 파일명 해시 prefix)
- 1차 책임 있는 공개 제출 4건의 기술적 정확성 최종 검토
- CLI 매뉴얼 작성 (4개 핵심 명령 사용법 + 백엔드/타깃별 옵션 매트릭스)
- 컨테이너 안전 옵션 표준 프리셋 3단계(standard/strict/relaxed) 정의 및 문서화
- SafeTensors 24시간 장시간 퍼징 결과 분석 (Binding Validation 카테고리 4건 확정)
- 최종 결과보고서 기술 섹션 및 정량 지표 항목 작성
3-2. 팀 활동
- 온라인 정기 미팅 (05.20, Discord): 통합 매트릭스 검증 결과와 1차 제출 진행 상황을 공유. AFL++ × SafeTensors 조건부 PASS 케이스에 대해 cargo-fuzz 백엔드 정식 추가를 향후 확장 항목으로 등재하기로 합의
- 최종 정리 회의 (05.22): 팀 전체가 모여 결과보고서 초안을 검토하고, 각자 담당 영역의 산출물 목록을 최종 확정. 본인은 다중 백엔드 통합 CLI와 다중 타깃 어댑터 영역의 기술 섹션 작성을 담당
- 신숙우 팀장과 1차 제출 공조 (05.18~05.19): 4건의 책임 있는 공개 제출 진행 중 기술적 질의가 발생할 경우 즉시 답변할 수 있도록 본인이 대기. 메인테이너와의 커뮤니케이션 단일 창구는 신숙우 팀장이 담당
- 전선정 팀원과 회고 (05.23): 8주간의 협업을 돌아보며 인터페이스 설계 과정에서 배운 점을 공유. 특히 단계 라벨 시스템 도입 시 코드와 문서 양쪽에 라벨 정의를 명시하는 정책이 정착된 것을 핵심 성과로 정리
- 황희주 팀원과 매뉴얼 검토 (05.24): CLI 매뉴얼이 외부 사용자 관점에서 충분히 친절한지 함께 검토. Report Generator 측의 템플릿 선택 옵션도 매뉴얼에 누락되지 않도록 보강
- 최종 멘토링 세션 (05.24): 멘토로부터 v1.0의 완성도와 통합 매트릭스 검증 절차에 대한 전반적 긍정 평가를 받음. 또한 결과보고서의 "향후 확장 항목"이 단순한 기술 목록이 아니라 실제 후속 단계로 이어질 수 있는 구체적인 경로로 작성되었다는 점이 인상적이라는 피드백 수령
🎯 4. 프로젝트 종료에 즈음하여
8주간의 활동을 마무리하며
1주차에 노션에 그렸던 5단계 파이프라인이 8주를 거쳐 FuzzGate v1.0이라는 실제 동작하는 시스템으로 완성되었다. 9가지 백엔드 × 타깃 조합 검증 통과, 16건의 reproduced 케이스 확보, 4건의 책임 있는 공개 제출까지 모두 일정 안에 완료되었다.
본 시리즈는 이번 8주차 테크노트로 종료되며, 결과보고서와 본인의 회고는 별도 문서로 공유한다. 책임 있는 공개 진행 상황(90일 비공개 기간)과 향후 확장 항목 진행 현황은 후속 단계에서 별도 채널을 통해 공유될 예정이다.
💬 5. 느낀점 및 회고
8주차는 8주간 만들어 온 모든 것이 "FuzzGate v1.0"이라는 하나의 이름으로 정리되는 한 주였다. 1주차에 빈 디렉터리에서 출발했던 프로젝트가, 마지막 주에는 3개 백엔드 × 3개 타깃이 동일한 CLI로 동작하고 16건의 reproduced 케이스를 자동 리포트로 산출하며 책임 있는 공개 절차까지 진행되는 시스템이 되었다는 것이 아직도 실감이 잘 나지 않는다. 특히 통합 매트릭스 검증을 수행하면서 9개 조합이 모두 동일한 후속 파이프라인을 그대로 통과하는 것을 보았을 때, 1주차에 "느슨한 결합과 표준 인터페이스"를 설계 원칙으로 정한 결정이 8주 뒤에 어떤 결과를 만들어내는지를 직접 경험할 수 있었다.
단일 ZIP 번들과 이중 무결성 해시 작업은 보안 도구의 본질이 "신뢰의 전달 가능성"이라는 것을 다시 한 번 일깨워 주었다. 도구가 아무리 많은 크래시를 찾아도, 외부 분석자가 그 결과를 신뢰하고 재현할 수 없다면 의미가 없다. 케이스 단위 해시와 번들 단위 해시를 분리하여 압축 직전과 직후 시점을 각각 보장하는 정책은 처음에는 과한 것 같았지만, 외부에 결과물이 전달되는 순간을 상상해 보니 두 시점의 무결성을 모두 검증할 수 있어야 한다는 결론이 자연스러웠다. 보안 도구는 자기 자신의 출력 경로에서 새로운 위험을 만들지 않아야 한다는 결과보고서의 원칙이 작은 디테일 하나하나에 녹아드는 과정을 본 것 같다.
1차 책임 있는 공개 제출은 이번 프로젝트에서 가장 긴장되면서도 의미 있는 순간이었다. 학교 과제나 내부 테스트가 아니라 실제 사용 중인 오픈소스 프로젝트에 우리가 발견한 결과를 공식적으로 보내는 행위는, 8주간 만든 도구가 보안 생태계의 작은 일부로 기여할 수 있다는 가능성을 보여 주었다. 메인테이너로부터 접수 확인을 받은 순간, "도구를 만든 것"과 "도구로 가치를 만든 것"이 다르다는 것을 체감했다. 도구의 마지막 가치는 결국 그것이 외부 세계와 만나는 지점에서 결정된다는 점에서, 8주차의 제출은 단순한 절차가 아니라 프로젝트 전체의 의미를 완성하는 순간이었다.
CLI 매뉴얼과 안전 옵션 프리셋을 정리하면서, "잘 만든 도구"와 "잘 전달된 도구"가 다르다는 것을 새삼 느꼈다. 기술적으로 완성도가 높아도 외부 사용자가 한 시간 안에 시작할 수 없다면 그 도구는 실질적으로 사용되지 않는다. standard / strict / relaxed 3단계 프리셋을 정의한 것도, 사용자가 보안 요구사항과 운영 편의성 사이에서 매번 선택을 고민하지 않도록 의사결정 비용을 줄여 주려는 의도였다. 인프라 작업, 매뉴얼 작성처럼 화려해 보이지 않는 일들이 결국 도구가 살아남느냐를 결정한다는 패턴은 4주차의 빌드 자동화부터 마지막 주의 매뉴얼 작성까지 일관되게 확인된 교훈이다.
8주를 돌아보면, 가장 크게 변한 것은 코드를 짜는 능력이 아니라 "시스템을 시스템으로 생각하는 방식"이었다. 1주차에는 하네스 하나를 어떻게 잘 만들지가 가장 큰 고민이었다면, 8주차에는 하나의 모듈을 추가할 때 후속 단계 전체에 미치는 영향을 자연스럽게 함께 떠올리게 되었다. 인터페이스를 정의하는 일이 코드를 짜는 일보다 더 큰 결정이라는 것, 표준화된 약속이 새로운 확장의 토대가 된다는 것, 그리고 일관된 결과를 보장하는 정책이 도구의 신뢰도를 만든다는 것을 8주간 반복해서 체감했다. 이 변화는 어떤 기술 스택보다도 오래 남을 자산이 될 것이라는 생각이 든다.
마지막으로, 이 프로젝트가 단순한 학기 활동이 아니라 진로의 방향을 가르쳐 준 경험이었다는 점을 기록해 두고 싶다. AI 모델 공급망 보안이라는 영역이 가진 사회적 의미, 자동화된 보안 도구가 만들어낼 수 있는 효율의 가치, 그리고 책임 있는 공개 절차를 통해 외부 생태계에 기여하는 행위의 무게를 직접 경험할 수 있었다. 8주 전에는 단지 "퍼징을 해 보자"였던 출발이, 8주 뒤에는 "보안 엔지니어로서 어떤 일을 하고 싶은가"라는 질문에 대한 구체적인 답을 갖게 해 주었다. 함께한 The First 팀원들과 멘토님께 감사드리며, FuzzGate v1.0이 후속 단계에서도 계속 발전하기를 바라며 본 프로젝트를 마친다.
📚 6. 참고 자료
'ABC 미래내일 프로젝트' 카테고리의 다른 글
| [2026 ABC 프로젝트 멘토링 3기] 프로젝트 7주차 (0) | 2026.05.18 |
|---|---|
| [2026 ABC 프로젝트 멘토링 3기] 프로젝트 6주차 (0) | 2026.05.11 |
| [2026 ABC 프로젝트 멘토링 3기] 프로젝트 5주차 (0) | 2026.05.03 |
| [2026 ABC 프로젝트 멘토링 3기] 프로젝트 4주차 (1) | 2026.04.26 |
| [2026 ABC 프로젝트 멘토링 3기] 프로젝트 3주차 (0) | 2026.04.20 |