
AI 에이전트가 실제 보안 취약점을 수정하는 성능을 평가하기 위한 벤치마크입니다.
실제 보안 취약점 수정에 있어 LLM 에이전트를 평가하기 위한 벤치마크입니다. 에이전트는 샌드박스 처리된 Docker 컨테이너 안에서 실행되며, 관리자의 보안 테스트 스위트를 기준으로 점수가 매겨집니다.
.env 파일)의 OPENAI_API_KEY, ANTHROPIC_API_KEY 및/또는 POOLSIDE_API_KEY의존성 설치:
pip install poetry
poetry install
각 작업은 tasks/{CVE-ID}/ 아래에 있으며 다음을 포함합니다:
tasks/CVE-2026-33175/
├── meta.json # GHSA ID, CWE, CVSS, repo URL, vulnerable and fixed SHAs
├── setup.sh # Clones repo, checks out the vulnerable SHA, installs dependencies
├── run_tests.sh # Injects test_security.py into the repo and runs pytest
├── test_security.py # Security tests (xfail on vulnerable code, pass on the fix)
├── advisory.md # Full GHSA advisory (richest prompt)
├── diagnose.md # Behavioural description only — no file or function names
├── locate.md # File and function only — no description of the flaw
└── Dockerfile # Optional; only present when the task needs extra system deps
meta.json 예시:
{
"ghsa_id": "GHSA-xxxx-xxxx-xxxx",
"cwe": ["CWE-287"],
"cvss": 9.1,
"repo": {
"url": "https://github.com/org/project",
"vulnerable_sha": "abc123^",
"fixed_sha": "abc123"
}
}
setup.sh는 멱등적이므로 다시 실행해도 안전합니다. test_security.py는 실행 중에는 에이전트에게 숨겨져 있으며, 에이전트가 작업을 마친 후에만 주입됩니다.
python build.py
다음을 빌드합니다:
cve-bench/base) — Python 3.12, git, poetry 및 하네스.cve-bench/{task-id}) — 기본 이미지를 확장하고, 작업 디렉터리를 복사한 다음 setup.sh를 실행합니다.옵션:
# Build specific tasks only
python build.py --task CVE-2026-33175 CVE-2026-42561
# Skip rebuilding the base image
python build.py --skip-base
작업 이미지는 병렬로 빌드됩니다(최대 5개 워커). 작업 디렉터리에 Dockerfile이 포함된 경우 일반적인 docker/task.Dockerfile 대신 해당 파일이 사용됩니다.
벤치마크를 실행하기 전에 각 작업의 보안 테스트가 취약한 코드와 수정된 코드를 올바르게 구분하는지 확인하세요:
python validate.py
각 작업에 대해 작업 컨테이너 내부에서 세 가지 단계가 실행됩니다:
| 단계 | 검사 내용 |
|---|---|
| vulnerable | 보안 테스트가 취약한 SHA에서 실패(또는 xfail)해야 함 |
| fixed | 보안 테스트가 수정된 SHA에서 통과해야 함 |
| regression | 비보안 테스트가 수정된 SHA에서 통과해야 함 |
결과는 실시간 테이블로 표시됩니다. 어떤 작업이라도 어떤 단계에서 실패하면 종료 코드는 1입니다.
# Validate specific tasks only
python validate.py --task CVE-2026-33175 GHSA-r758-8hxw-4845
# Skip rebuilding images before validation
python validate.py --skip-build
python benchmark.py --model openai:gpt-5.5 poolside:laguna-m.1 --prompt-type advisory
옵션:
| 플래그 | 설명 | 기본값 |
|---|---|---|
--model | 하나 이상의 provider:model-id 문자열 | 구성된 모든 모델 |
--prompt-type | advisory, diagnose, locate 또는 임의의 조합 | 세 가지 모두 |
--task | 하나 이상의 작업 ID | 모든 작업 |
--clean | 시작 전에 선택된 범위의 기존 결과 삭제 | 꺼짐 |
지원되는 공급자:
| 제공자 | 형식 | API 키 환경 변수 |
|---|---|---|
| OpenAI | openai:gpt-5.5 | OPENAI_API_KEY |
| Anthropic | anthropic:claude-haiku-4-5-20251001 | ANTHROPIC_API_KEY |
| Poolside | poolside:laguna-m.1 | POOLSIDE_API_KEY |
각 실행은 results/에 JSON 결과 파일을 생성합니다:
results/{task-id}__{provider}:{model}__{prompt-type}.json
기존 결과 파일은 자동으로 건너뜁니다. 실행은 작업 전반에 걸쳐 동시에 수행되며(최대 20개 워커), 429 오류를 방지하기 위해 공급자별 속도 제한(공급자당 동시 활성 요청 1개)이 적용됩니다.
각 결과 파일은 다음 구조를 가진 JSON 객체입니다:
{
"cve_id": "CVE-2026-33175",
"model_id": "openai:gpt-5.5",
"prompt_type": "advisory",
"timestamp": "2026-05-01T12:00:00",
"model_duration_s": 142.3,
"test_duration_s": 8.1,
"turns": [
{
"tool_calls_and_results": [...],
"input_tokens": 12400,
"output_tokens": 310
}
],
"tests": [
{
"kind": "security",
"name": "test_email_verified",
"outcome": "passed"
}
]
}
tests[].kind는 "security"(test_security.py에서 유래) 또는 "regression"(프로젝트 자체 테스트 스위트에서 유래) 중 하나입니다. 모든 보안 테스트가 통과하고 회귀 테스트가 하나도 실패하지 않는 경우에만 해당 실행이 해결된 것으로 간주됩니다.
python generate_charts.py
results/의 모든 결과 파일을 읽고 SVG 차트를 docs/images/charts/에 작성합니다. Bokeh의 헤드리스 내보내기에는 Chrome/Chromium이 필요합니다(chromedriver-binary 사용).
하네스는 각 Docker 컨테이너 내부에서 python -m harness.run으로 실행됩니다. 프롬프트 로드, 에이전트 루프 실행, 결과 파일 작성을 담당합니다.
src/harness/
├── run.py # Entry point; parses args, wires components, calls BenchmarkRunner
├── client/
│ ├── factory.py # Parses provider:model-id, returns the correct LLMClient
│ ├── _client.py # Abstract LLMClient, ToolCall and LLMTurn dataclasses
│ ├── anthropic.py # Anthropic SDK integration
│ └── oai.py # OpenAI SDK integration (also used for Poolside)
├── agent/
│ ├── core.py # Agentic loop: calls client, dispatches tool calls, threads messages
│ └── runner.py # Wraps Agent, tracks timing and turn list
├── bench/
│ ├── runner.py # Orchestrates setup → agent → security tests → regression tests
│ ├── result.py # BenchmarkResult and TestResult dataclasses, JSON serialisation
│ └── repository.py # Writes result files to disk
└── task/
├── tools.py # Tool implementations: ListFiles, ReadFile, SearchInFiles,
│ # EditFile, CreateFile, DeleteFile, RunPytest
└── prompt_loader.py # Reads advisory.md / diagnose.md / locate.md
에이전트가 사용할 수 있는 도구:
| 도구 | 설명 |
|---|---|
list_files | 저장소의 파일 및 디렉터리 나열 |
read_file | 파일 내용 읽기, 선택적으로 줄 범위 지정 |
search_in_files | 코드베이스 전체에서 정규식 검색, 선택적 파일 글로브 지원 |
edit_file | 기존 파일의 줄 범위 교체 |
create_file | 새 파일 생성 |
delete_file | 파일 삭제 |
run_pytest | 프로젝트의 테스트 스위트 실행, JSON 보고서 반환 |
모든 도구는 디렉터리 트래버설을 방지하기 위해 저장소 루트를 기준으로 경로를 검증합니다. 에이전트는 test_security.py 또는 git 히스토리에 접근할 수 없습니다.
에이전트 루프는 최대 20턴 동안 실행됩니다. 턴 상한에 도달하면 실행은 그 상태 그대로 기록되며, 에이전트가 저장소를 남겨둔 상태를 기준으로 보안 테스트가 계속 실행됩니다.
tasks/{CVE-ID}/를 만들고 meta.json, setup.sh, run_tests.sh, test_security.py, advisory.md, diagnose.md, locate.md를 추가합니다.setup.sh와 run_tests.sh를 실행 가능하게 만듭니다(chmod +x).python validate.py --task {CVE-ID}.python build.py --task {CVE-ID}.이 작업은 독립적인 연구로 수행되었습니다. 연구를 수행하고 이 저장소를 준비하는 당시, 필자는 어떠한 기관에도 소속되어 있지 않았습니다.
@misc{gattipinheiro2026cvebench,
author = {Gatti Pinheiro, Giovanni},
title = {{CVE-Bench}: Benchmarking {LLM} Agents on Real-World Security Vulnerability Fixes},
year = {2026},
howpublished = {\url{https://giovannigatti.github.io/cve-bench}},
note = {Code available at \url{https://github.com/GiovanniGatti/cve-bench}}
}
MIT — LICENSE를 참조하세요.