커버리지 기반 퍼즈 테스팅 (지원 중단됨)
GitLab v19.5Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
요약
이 기능은 GitLab 18.0에서 지원 중단되었으며 19.0에서 제거될 예정입니다. 커버리지 기반 퍼즈 테스팅은 계측된 버전의 애플리케이션에 무작위 입력을 보내 예상치 못한 동작을 유발합니다. 퍼즈 테스팅은 GitLab Secure의 다른 보안 스캐너 및 자체 테스트 프로세스와 함께 사용해야 합니다.
이 기능은 GitLab 18.0에서 지원 중단되었으며 19.0에서 제거될 예정입니다. 이는 브레이킹 체인지입니다.
시작하기#
커버리지 기반 퍼즈 테스팅은 계측된 버전의 애플리케이션에 무작위 입력을 보내 예상치 못한 동작을 유발합니다. 이러한 동작은 수정해야 할 버그를 나타냅니다. GitLab은 파이프라인에 커버리지 기반 퍼즈 테스팅을 추가하는 기능을 제공합니다. 이를 통해 다른 QA 프로세스가 놓칠 수 있는 버그와 잠재적 보안 문제를 발견할 수 있습니다.
퍼즈 테스팅은 GitLab Secure의 다른 보안 스캐너 및 자체 테스트 프로세스와 함께 사용해야 합니다. GitLab CI/CD를 사용하는 경우 CI/CD 워크플로의 일부로 커버리지 기반 퍼즈 테스팅을 실행할 수 있습니다.
개요는 Coverage-guided Fuzzing - Advanced Security Testing을 참고합니다.
커버리지 기반 퍼즈 테스팅 상태 확인#
커버리지 기반 퍼즈 테스팅의 상태를 확인하려면 다음 단계를 수행합니다.
- 상단 표시줄에서 Search or go to를 선택하고 프로젝트를 찾습니다.
- 왼쪽 사이드바에서 Secure > Security configuration을 선택합니다.
- Coverage Fuzzing 섹션의 상태는 다음 중 하나입니다.
- Not configured
- Enabled
- GitLab Ultimate로 업그레이드하라는 안내.
커버리지 기반 퍼즈 테스팅 활성화#
커버리지 기반 퍼즈 테스팅을 활성화하려면 .gitlab-ci.yml을 다음과 같이 편집합니다.
-
Stage 목록에
fuzzStage를 추가합니다. -
애플리케이션이 Go로 작성되지 않았다면 해당 퍼징 엔진을 사용하는 Docker 이미지를 지정합니다. 예를 들면 다음과 같습니다.
image: python:latest -
GitLab 설치에 포함되어 제공되는
Coverage-Fuzzing.gitlab-ci.yml템플릿 을 포함합니다. -
요구 사항에 맞게
my_fuzz_targetjob을 사용자 지정합니다.
커버리지 기반 퍼징 구성 예시#
stages:
- fuzz
include:
- template: Coverage-Fuzzing.gitlab-ci.yml
my_fuzz_target:
extends: .fuzz_base
script:
# Build your fuzz target binary in these steps, then run it with gitlab-cov-fuzz
# See our example repos for how you could do this with any of our supported languages
- ./gitlab-cov-fuzz run --regression=$REGRESSION -- <your fuzz target>
Coverage-Fuzzing 템플릿에는 숨겨진 job
.fuzz_base가 포함되어 있으며, 각 퍼징 대상마다 이를 확장해야
합니다. 각 퍼징 대상은 별도의 job을 가져야 합니다. 예를 들어
go-fuzzing-example 프로젝트
에는 단일 퍼징 대상에 대해 .fuzz_base를 확장하는 job 이 하나 있습니다.
숨겨진 job .fuzz_base는 사용자 job에서 재정의해서는 안 되는 여러 YAML 키를
사용합니다. 이러한 키를 사용자 job에 포함한다면 원래 내용을 그대로 복사해야 합니다.
before_scriptartifactsrules
결과 이해#
출력#
각 퍼징 단계는 다음 아티팩트를 출력합니다.
gl-coverage-fuzzing-report.json: 커버리지 기반 퍼즈 테스팅과 그 결과의 세부 정보가 담긴 보고서입니다.artifacts.zip: 이 파일에는 두 개의 디렉터리가 들어 있습니다.corpus: 현재 job과 이전 모든 job 이 생성한 테스트 케이스를 모두 포함합니다.crashes: 현재 job 이 발견한 모든 크래시 이벤트와 이전 job에서 수정되지 않은 이벤트를 포함합니다.
JSON 보고서 파일은 CI/CD 파이프라인 페이지에서 내려받을 수 있습니다. 자세한 내용은 아티팩트 다운로드를 참고합니다.
코퍼스 레지스트리#
코퍼스 레지스트리는 코퍼스의 라이브러리입니다. 프로젝트 레지스트리에 있는 코퍼스는 해당 프로젝트의 모든 job에서 사용할 수 있습니다. 프로젝트 전체 레지스트리는 job 당 코퍼스 하나라는 기본 방식보다 코퍼스를 효율적으로 관리하는 방법입니다.
코퍼스 레지스트리는 패키지 레지스트리를 사용해 프로젝트의 코퍼스를 저장합니다. 레지스트리에 저장된 코퍼스는 데이터 무결성을 위해 숨겨집니다.
코퍼스를 내려받으면 처음 업로드할 때 사용한 파일 이름과 관계없이 파일 이름이 artifacts.zip 이 됩니다.
이 파일에는 코퍼스만 들어 있으며, CI/CD 파이프라인에서 내려받을 수 있는 아티팩트 파일과는
다릅니다. 또한 Reporter 이상의 권한을 가진 프로젝트 멤버는 직접 다운로드 링크로 코퍼스를 내려받을 수 있습니다.
코퍼스 레지스트리 세부 정보 보기#
코퍼스 레지스트리의 세부 정보를 보려면 다음 단계를 수행합니다.
- 상단 표시줄에서 Search or go to를 선택하고 프로젝트를 찾습니다.
- 왼쪽 사이드바에서 Secure > Security configuration을 선택합니다.
- Coverage Fuzzing 섹션에서 Manage corpus를 선택합니다.
코퍼스 레지스트리에 코퍼스 생성#
코퍼스 레지스트리에 코퍼스를 생성하는 방법은 다음 두 가지입니다.
- 파이프라인에서 코퍼스 생성
- 기존 코퍼스 파일 업로드
파이프라인에서 코퍼스 생성#
파이프라인에서 코퍼스를 생성하려면 다음 단계를 수행합니다.
.gitlab-ci.yml파일에서my_fuzz_targetjob을 편집합니다.- 다음 변수를 설정합니다.
COVFUZZ_USE_REGISTRY를true로 설정합니다.COVFUZZ_CORPUS_NAME에 코퍼스 이름을 설정합니다.COVFUZZ_GITLAB_TOKEN을 개인 액세스 토큰 값으로 설정합니다.
my_fuzz_target job 이 실행되면 코퍼스는 COVFUZZ_CORPUS_NAME 변수에 지정한 이름으로
코퍼스 레지스트리에 저장됩니다. 코퍼스는 파이프라인이 실행될 때마다 갱신됩니다.
코퍼스 파일 업로드#
기존 코퍼스 파일을 업로드하려면 다음 단계를 수행합니다.
- 상단 표시줄에서 Search or go to를 선택하고 프로젝트를 찾습니다.
- 왼쪽 사이드바에서 Secure > Security configuration을 선택합니다.
- Coverage Fuzzing 섹션에서 Manage corpus를 선택합니다.
- New corpus를 선택합니다.
- 각 필드를 입력합니다.
- Upload file을 선택합니다.
- Add를 선택합니다.
이제 .gitlab-ci.yml 파일에서 해당 코퍼스를 참조할 수 있습니다. COVFUZZ_CORPUS_NAME 변수에
사용한 값이 업로드한 코퍼스 파일에 지정한 이름과 정확히 일치하는지 확인합니다.
코퍼스 레지스트리에 저장된 코퍼스 사용#
코퍼스 레지스트리에 저장된 코퍼스를 사용하려면 이름으로 참조해야 합니다. 해당 코퍼스의 이름은 코퍼스 레지스트리 세부 정보에서 확인합니다.
사전 요구 사항:
- 프로젝트에서 커버리지 기반 퍼즈 테스팅을 활성화합니다.
.gitlab-ci.yml파일에 다음 변수를 설정합니다.COVFUZZ_USE_REGISTRY를true로 설정합니다.COVFUZZ_CORPUS_NAME을 코퍼스 이름으로 설정합니다.COVFUZZ_GITLAB_TOKEN을 개인 액세스 토큰 값으로 설정합니다.
커버리지 기반 퍼즈 테스팅 보고서#
gl-coverage-fuzzing-report.json 파일 형식에 대한 자세한 내용은
스키마를 참고합니다.
커버리지 기반 퍼징 보고서 예시:
{
"version": "v1.0.8",
"regression": false,
"exit_code": -1,
"vulnerabilities": [
{
"category": "coverage_fuzzing",
"message": "Heap-buffer-overflow\nREAD 1",
"description": "Heap-buffer-overflow\nREAD 1",
"severity": "Critical",
"stacktrace_snippet": "INFO: Seed: 3415817494\nINFO: Loaded 1 modules (7 inline 8-bit counters): 7 [0x10eee2470, 0x10eee2477), \nINFO: Loaded 1 PC tables (7 PCs): 7 [0x10eee2478,0x10eee24e8), \nINFO: 5 files found in corpus\nINFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes\nINFO: seed corpus: files: 5 min: 1b max: 4b total: 14b rss: 26Mb\n#6\tINITED cov: 7 ft: 7 corp: 5/14b exec/s: 0 rss: 26Mb\n=================================================================\n==43405==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000001573 at pc 0x00010eea205a bp 0x7ffee0d5e090 sp 0x7ffee0d5e088\nREAD of size 1 at 0x602000001573 thread T0\n #0 0x10eea2059 in FuzzMe(unsigned char const*, unsigned long) fuzz_me.cc:9\n #1 0x10eea20ba in LLVMFuzzerTestOneInput fuzz_me.cc:13\n #2 0x10eebe020 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) FuzzerLoop.cpp:556\n #3 0x10eebd765 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) FuzzerLoop.cpp:470\n #4 0x10eebf966 in fuzzer::Fuzzer::MutateAndTestOne() FuzzerLoop.cpp:698\n #5 0x10eec0665 in fuzzer::Fuzzer::Loop(std::__1::vector\u003cfuzzer::SizedFile, fuzzer::fuzzer_allocator\u003cfuzzer::SizedFile\u003e \u003e\u0026) FuzzerLoop.cpp:830\n #6 0x10eead0cd in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) FuzzerDriver.cpp:829\n #7 0x10eedaf82 in main FuzzerMain.cpp:19\n #8 0x7fff684fecc8 in start+0x0 (libdyld.dylib:x86_64+0x1acc8)\n\n0x602000001573 is located 0 bytes to the right of 3-byte region [0x602000001570,0x602000001573)\nallocated by thread T0 here:\n #0 0x10ef92cfd in wrap__Znam+0x7d (libclang_rt.asan_osx_dynamic.dylib:x86_64+0x50cfd)\n #1 0x10eebdf31 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) FuzzerLoop.cpp:541\n #2 0x10eebd765 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) FuzzerLoop.cpp:470\n #3 0x10eebf966 in fuzzer::Fuzzer::MutateAndTestOne() FuzzerLoop.cpp:698\n #4 0x10eec0665 in fuzzer::Fuzzer::Loop(std::__1::vector\u003cfuzzer::SizedFile, fuzzer::fuzzer_allocator\u003cfuzzer::SizedFile\u003e \u003e\u0026) FuzzerLoop.cpp:830\n #5 0x10eead0cd in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) FuzzerDriver.cpp:829\n #6 0x10eedaf82 in main FuzzerMain.cpp:19\n #7 0x7fff684fecc8 in start+0x0 (libdyld.dylib:x86_64+0x1acc8)\n\nSUMMARY: AddressSanitizer: heap-buffer-overflow fuzz_me.cc:9 in FuzzMe(unsigned char const*, unsigned long)\nShadow bytes around the buggy address:\n 0x1c0400000250: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa\n 0x1c0400000260: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa\n 0x1c0400000270: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa\n 0x1c0400000280: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa\n 0x1c0400000290: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa\n=\u003e0x1c04000002a0: fa fa fd fa fa fa fd fa fa fa fd fa fa fa[03]fa\n 0x1c04000002b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa\n 0x1c04000002c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa\n 0x1c04000002d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa\n 0x1c04000002e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa\n 0x1c04000002f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa\nShadow byte legend (one shadow byte represents 8 application bytes):\n Addressable: 00\n Partially addressable: 01 02 03 04 05 06 07 \n Heap left redzone: fa\n Freed heap region: fd\n Stack left redzone: f1\n Stack mid redzone: f2\n Stack right redzone: f3\n Stack after return: f5\n Stack use after scope: f8\n Global redzone: f9\n Global init order: f6\n Poisoned by user: f7\n Container overflow: fc\n Array cookie: ac\n Intra object redzone: bb\n ASan internal: fe\n Left alloca redzone: ca\n Right alloca redzone: cb\n Shadow gap: cc\n==43405==ABORTING\nMS: 1 EraseBytes-; base unit: de3a753d4f1def197604865d76dba888d6aefc71\n0x46,0x55,0x5a,\nFUZ\nartifact_prefix='./crashes/'; Test unit written to ./crashes/crash-0eb8e4ed029b774d80f2b66408203801cb982a60\nBase64: RlVa\nstat::number_of_executed_units: 122\nstat::average_exec_per_sec: 0\nstat::new_units_added: 0\nstat::slowest_unit_time_sec: 0\nstat::peak_rss_mb: 28",
"scanner": {
"id": "libFuzzer",
"name": "libFuzzer"
},
"location": {
"crash_address": "0x602000001573",
"crash_state": "FuzzMe\nstart\nstart+0x0\n\n",
"crash_type": "Heap-buffer-overflow\nREAD 1"
},
"tool": "libFuzzer"
}
]
}
취약점 처리#
취약점이 발견되면 해당 취약점을 처리할 수 있습니다. 머지 리퀘스트의 Reports 탭에 취약점이 표시되고 퍼징 아티팩트를 내려받는 버튼이 함께 제공됩니다. 탐지된 취약점 중 하나를 선택하면 세부 정보를 확인할 수 있습니다.
Security Dashboard에서도 취약점을 확인할 수 있으며, 여기에서 그룹·프로젝트·파이프라인의 모든 보안 취약점을 한눈에 볼 수 있습니다.
취약점을 선택하면 해당 취약점에 대한 추가 정보를 제공하는 모달이 열립니다.
- Status: 취약점의 상태입니다. 다른 유형의 취약점과 마찬가지로 커버리지 퍼징 취약점도 Detected, Confirmed, Dismissed, Resolved 중 하나가 됩니다.
- Project: 취약점이 존재하는 프로젝트입니다.
- Crash type: 코드에서 발생한 크래시 또는 결함의 유형입니다. 일반적으로 CWE에 대응됩니다.
- Crash state: 스택 트레이스를 정규화한 형태로, 크래시 직전 세 개의 함수를 포함합니다 (무작위 주소는 제외됩니다).
- Stack trace snippet: 스택 트레이스의 마지막 몇 줄로, 크래시의 세부 정보를 보여 줍니다.
- Identifier: 취약점의 식별자입니다. CVE 또는 CWE에 대응됩니다.
- Severity: 취약점의 심각도입니다. Critical, High, Medium, Low, Info, Unknown 중 하나입니다.
- Scanner: 취약점을 탐지한 스캐너입니다(예: Coverage Fuzzing).
- Scanner Provider: 스캔을 수행한 엔진입니다. Coverage Fuzzing의 경우 지원되는 퍼징 엔진 및 언어에 나열된 엔진 중 하나입니다.
최적화#
다음 사용자 지정 옵션을 사용해 프로젝트에 맞게 커버리지 기반 퍼즈 테스팅을 최적화합니다.
사용 가능한 CI/CD 변수#
CI/CD 파이프라인에서 커버리지 기반 퍼즈 테스팅을 구성할 때 다음 변수를 사용합니다.
GitLab 보안 스캐닝 도구의 사용자 지정은 기본 브랜치에 변경 사항을 병합하기 전에 머지 리퀘스트에서 먼저 테스트해야 합니다. 그렇지 않으면 다수의 오탐을 포함한 예상치 못한 결과가 발생할 수 있습니다.
| CI/CD 변수 | 설명 |
|---|---|
COVFUZZ_ADDITIONAL_ARGS |
gitlab-cov-fuzz에 전달되는 인수입니다. 기반 퍼징 엔진의 동작을 사용자 지정하는 데 사용합니다. 전체 인수 목록은 퍼징 엔진의 문서를 참고합니다. |
COVFUZZ_BRANCH |
장기 실행 퍼징 job을 실행할 브랜치입니다. 다른 모든 브랜치에서는 퍼징 회귀 테스트만 실행됩니다. 기본값: 리포지터리의 기본 브랜치. |
COVFUZZ_SEED_CORPUS |
시드 코퍼스 디렉터리의 경로입니다. 기본값: 비어 있음. |
COVFUZZ_URL_PREFIX |
오프라인 환경에서 사용하기 위해 클론한 gitlab-cov-fuzz 리포지터리의 경로입니다. 이 값은 오프라인 환경을 사용할 때만 변경해야 합니다. 기본값: https://gitlab.com/gitlab-org/security-products/analyzers/gitlab-cov-fuzz/-/raw. |
COVFUZZ_USE_REGISTRY |
GitLab 코퍼스 레지스트리에 코퍼스를 저장하려면 true로 설정합니다. 이 변수를 true로 설정하면 COVFUZZ_CORPUS_NAME과 COVFUZZ_GITLAB_TOKEN 변수가 필요합니다. 기본값: false. |
COVFUZZ_CORPUS_NAME |
job에서 사용할 코퍼스의 이름입니다. |
COVFUZZ_GITLAB_TOKEN |
API 읽기/쓰기 액세스 권한이 있는 개인 액세스 토큰 또는 프로젝트 액세스 토큰으로 구성한 환경 변수입니다. |
시드 코퍼스#
시드 코퍼스의 파일은 수동으로 갱신해야 합니다. 커버리지 기반 퍼즈 테스팅 job은 이 파일을 갱신하거나 덮어쓰지 않습니다.
커버리지 기반 퍼즈 테스팅 절차#
퍼즈 테스팅 절차는 다음과 같습니다.
- 대상 애플리케이션을 컴파일합니다.
gitlab-cov-fuzz도구를 사용해 계측된 애플리케이션을 실행합니다.- 퍼저가 출력한 예외 정보를 파싱하고 분석합니다.
- 다음 중 한 곳에서 코퍼스를 내려받습니다.
- 이전 파이프라인.
COVFUZZ_USE_REGISTRY가true로 설정된 경우 코퍼스 레지스트리.
- 이전 파이프라인에서 크래시 이벤트를 내려받습니다.
- 파싱한 크래시 이벤트와 데이터를
gl-coverage-fuzzing-report.json파일로 출력합니다. - 다음 중 한 곳에서 코퍼스를 갱신합니다.
- 해당 job의 파이프라인.
COVFUZZ_USE_REGISTRY가true로 설정된 경우 코퍼스 레지스트리.
커버리지 기반 퍼즈 테스팅의 결과는 CI/CD 파이프라인에서 확인할 수 있습니다.
확대 적용#
단일 프로젝트에서 커버리지 기반 퍼즈 테스팅에 익숙해지면 오프라인 환경에서의 테스트 활성화를 포함한 다음 고급 기능을 활용할 수 있습니다.
지원되는 퍼징 엔진 및 언어#
다음 퍼징 엔진을 사용해 지정된 언어를 테스트할 수 있습니다.
| 언어 | 퍼징 엔진 | 예시 |
|---|---|---|
| C/C++ | libFuzzer | c-cpp-example |
| Go | go-fuzz (libFuzzer support) | go-fuzzing-example |
| Swift | libFuzzer | swift-fuzzing-example |
| Rust | cargo-fuzz (libFuzzer support) | rust-fuzzing-example |
| Java (Maven only)1 | Javafuzz (권장) | javafuzz-fuzzing-example |
| Java | JQF (비권장) | jqf-fuzzing-example |
| JavaScript | jsfuzz |
jsfuzz-fuzzing-example |
| Python | pythonfuzz |
pythonfuzz-fuzzing-example |
| AFL (any language that works on top of AFL) | AFL | afl-fuzzing-example |
커버리지 기반 퍼즈 테스팅 실행 시간#
커버리지 기반 퍼즈 테스팅에 사용할 수 있는 실행 시간은 다음과 같습니다.
- 10분(기본값): 기본 브랜치에 권장합니다.
- 60분: 개발 브랜치와 머지 리퀘스트에 권장합니다. 실행 시간이 길수록 커버리지가 넓어집니다.
COVFUZZ_ADDITIONAL_ARGS변수에--regression=true값을 설정합니다.
전체 예시는 Go 커버리지 기반 퍼징 예시를 참고합니다.
지속적 커버리지 기반 퍼즈 테스팅#
메인 파이프라인을 차단하지 않으면서 커버리지 기반 퍼징 job을 더 오래 실행할 수도 있습니다. 이 구성은 GitLab의 상위-하위 파이프라인을 사용합니다.
이 시나리오에서 권장하는 워크플로는 메인 브랜치나 개발 브랜치에서 장기 실행 비동기 퍼징 job을 실행하고, 그 밖의 모든 브랜치와 MR에서는 짧은 동기 퍼징 job을 실행하는 것입니다. 이렇게 하면 커밋별 파이프라인을 빠르게 완료하면서도 퍼저가 애플리케이션을 충분히 탐색하고 테스트할 시간을 확보할 수 있습니다. 커버리지 기반 퍼저가 코드베이스의 깊은 버그를 찾으려면 대개 장기 실행 퍼징 job 이 필요합니다.
다음은 이 워크플로를 위한 .gitlab-ci.yml 파일의
일부입니다. 전체 예시는 Go 퍼징 예시 리포지터리를 참고합니다.
sync_fuzzing:
variables:
COVFUZZ_ADDITIONAL_ARGS: '-max_total_time=300'
trigger:
include: .covfuzz-ci.yml
strategy: depend
rules:
- if: $CI_COMMIT_BRANCH != 'continuous_fuzzing' && $CI_PIPELINE_SOURCE != 'merge_request_event'
async_fuzzing:
variables:
COVFUZZ_ADDITIONAL_ARGS: '-max_total_time=3600'
trigger:
include: .covfuzz-ci.yml
rules:
- if: $CI_COMMIT_BRANCH == 'continuous_fuzzing' && $CI_PIPELINE_SOURCE != 'merge_request_event'
이 구성은 두 개의 job을 생성합니다.
sync_fuzzing: 모든 퍼즈 대상을 차단 방식으로 짧게 실행합니다. 단순한 버그를 찾아내며, MR 이 새로운 버그를 들여오거나 예전 버그를 다시 발생시키지 않는다는 점을 확인할 수 있습니다.async_fuzzing: 브랜치에서 실행되며 개발 주기와 MR을 차단하지 않고 코드의 깊은 버그를 찾아냅니다.
covfuzz-ci.yml은 원래의 동기 방식 예시와 동일합니다.
FIPS 지원 바이너리#
커버리지 퍼징 바이너리는 Linux x86에서 golang-fips로 컴파일되며 암호화 백엔드로 OpenSSL을 사용합니다. 자세한 내용은 Go를 사용하는 GitLab의 FIPS 준수 문서를 참고합니다.
오프라인 환경#
오프라인 환경에서 커버리지 퍼징을 사용하려면 다음 단계를 수행합니다.
-
gitlab-cov-fuzz를 오프라인 GitLab 인스턴스가 접근할 수 있는 비공개 리포지터리로 클론합니다. -
각 퍼징 단계에서
COVFUZZ_URL_PREFIX를${NEW_URL_GITLAB_COV_FUZ}/-/raw로 설정합니다. 여기서NEW_URL_GITLAB_COV_FUZ는 첫 번째 단계에서 준비한 비공개gitlab-cov-fuzz클론의 URL 입니다.
문제 해결#
오류 Unable to extract corpus folder from artifacts zip file#
COVFUZZ_USE_REGISTRY가 true로 설정된 상태에서 이 오류 메시지가 나타나면, 업로드한 코퍼스
파일이 corpus라는 이름의 폴더로 압축 해제되는지 확인합니다.
오류 400 Bad request - Duplicate package is not allowed#
COVFUZZ_USE_REGISTRY를 true로 설정하고 퍼징 job을 실행할 때 이 오류 메시지가 나타나면,
중복이 허용되어 있는지 확인합니다. 자세한 내용은
중복 Generic 패키지를 참고합니다.