
実世界のセキュリティ脆弱性を修正するAIエージェントを評価するためのベンチマーク。
実世界のセキュリティ脆弱性の修正においてLLMエージェントを評価するためのベンチマークです。エージェントはサンドボックス化されたDockerコンテナ内で実行され、メンテナのセキュリティテストスイートに基づいてスコアリングされます。
OPENAI_API_KEY、ANTHROPIC_API_KEY、POOLSIDE_API_KEY のいずれかを設定(または .env ファイルを使用)依存関係のインストール:
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
各タスクについて、タスクコンテナ内で次の3つのフェーズが実行されます:
| フェーズ | チェック内容 |
|---|---|
| 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 | 1つ以上の provider:model-id 文字列 | 設定済みの全モデル |
--prompt-type | advisory、diagnose、locate、または任意の組み合わせ | 3つすべて |
--task | 1つ以上のタスク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ワーカー)、プロバイダーごとのレート制限(プロバイダーごとに同時に1つのアクティブなリクエスト)により429エラーを回避します。
各結果ファイルは次の構造を持つ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"(プロジェクト自身のテストスイート由来)のいずれかです。すべてのセキュリティテストが成功し、回帰テストが1つも失敗しない場合にのみ、実行は解決済みと見なされます。
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 を参照してください。