
Ein Benchmark zur Bewertung von KI-Agenten beim Beheben von realen Sicherheitsschwachstellen.
Ein Benchmark zur Bewertung von LLM-Agenten bei der Behebung realer Sicherheitslücken. Die Agenten laufen in sandboxed Docker-Containern und werden anhand des Sicherheitstestsuites des Maintainers bewertet.
OPENAI_API_KEY, ANTHROPIC_API_KEY und/oder POOLSIDE_API_KEY in Ihrer Umgebung (oder einer .env-Datei)Abhängigkeiten installieren:
pip install poetry
poetry install
Jede Aufgabe befindet sich unter tasks/{CVE-ID}/ und enthält:
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 Beispiel:
{
"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 ist idempotent und kann sicher erneut ausgeführt werden. test_security.py wird während des Laufs vor dem Agenten verborgen und erst nach Abschluss des Agenten injiziert.
python build.py
Dies erstellt:
cve-bench/base) — Python 3.12, git, poetry und die Testumgebung.cve-bench/{task-id}) — erweitert das Basis-Image, kopiert das Aufgabenverzeichnis und führt setup.sh aus.Optionen:
# Nur bestimmte Aufgaben erstellen
python build.py --task CVE-2026-33175 CVE-2026-42561
# Basis-Image nicht neu erstellen
python build.py --skip-base
Aufgaben-Images werden parallel erstellt (bis zu 5 Worker). Wenn ein Aufgabenverzeichnis eine Dockerfile enthält, wird diese anstelle der generischen docker/task.Dockerfile verwendet.
Vor dem Ausführen des Benchmarks überprüfen, ob die Sicherheitstests jeder Aufgabe korrekt zwischen verwundbarem und behobenem Code unterscheiden:
python validate.py
Für jede Aufgabe führt dies drei Phasen im Aufgaben-Container aus:
| Phase | Was geprüft wird |
|---|---|
| vulnerable | Sicherheitstests müssen auf dem verwundbaren SHA fehlschlagen (oder xfail erzeugen) |
| fixed | Sicherheitstests müssen auf dem behobenen SHA bestehen |
| regression | Nicht-Sicherheitstests müssen auf dem behobenen SHA bestehen |
Ergebnisse werden als Live-Tabelle angezeigt. Exit-Code ist 1, wenn eine Aufgabe in einer Phase fehlschlägt.
# Nur bestimmte Aufgaben validieren
python validate.py --task CVE-2026-33175 GHSA-r758-8hxw-4845
# Images vor der Validierung nicht neu erstellen
python validate.py --skip-build
python benchmark.py --model openai:gpt-5.5 poolside:laguna-m.1 --prompt-type advisory
Optionen:
| Flag | Beschreibung | Standard |
|---|---|---|
--model | Ein oder mehrere provider:model-id-Strings | alle konfigurierten Modelle |
--prompt-type | advisory, diagnose, locate oder eine beliebige Kombination | alle drei |
--task | Ein oder mehrere Aufgaben-IDs | alle Aufgaben |
--clean | Vorhandene Ergebnisse für den ausgewählten Bereich vor dem Start löschen | aus |
Unterstützte Anbieter:
| Anbieter | Format | Umgebungsvariable für API-Key |
|---|---|---|
| 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 |
Jeder Durchlauf erzeugt eine JSON-Ergebnisdatei in results/:
results/{task-id}__{provider}:{model}__{prompt-type}.json
Vorhandene Ergebnisdateien werden automatisch übersprungen. Läufe werden parallel über Aufgaben hinweg ausgeführt (bis zu 20 Worker), mit Ratenbegrenzung pro Anbieter (ein aktiver Request pro Anbieter gleichzeitig), um 429-Fehler zu vermeiden.
Jede Ergebnisdatei ist ein JSON-Objekt mit der folgenden Struktur:
{
"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 ist entweder "security" (aus test_security.py) oder "regression" (aus dem eigenen Testsuite des Projekts). Ein Lauf gilt nur dann als gelöst, wenn alle Sicherheitstests bestanden und keine Regressionstests fehlgeschlagen sind.
python generate_charts.py
Liest alle Ergebnisdateien aus results/ und schreibt SVG-Diagramme nach docs/images/charts/. Benötigt Chrome/Chromium für den Headless-Export von Bokeh (über chromedriver-binary).
Die Testumgebung (Harness) läuft in jedem Docker-Container als python -m harness.run. Sie ist verantwortlich für das Laden des Prompts, die Ausführung der agentischen Schleife und das Schreiben der Ergebnisdatei.
src/harness/
├── run.py # Einstiegspunkt; parst Argumente, verdrahtet Komponenten, ruft BenchmarkRunner auf
├── client/
│ ├── factory.py # Parst provider:model-id, gibt den passenden LLMClient zurück
│ ├── _client.py # Abstrakter LLMClient, ToolCall- und LLMTurn-Dataclasses
│ ├── anthropic.py # Anthropic SDK-Integration
│ └── oai.py # OpenAI SDK-Integration (auch für Poolside verwendet)
├── agent/
│ ├── core.py # Agentische Schleife: ruft Client auf, verteilt Tool-Aufrufe, verknüpft Nachrichten
│ └── runner.py # Wrappt Agent, verfolgt Timing und Turn-Liste
├── bench/
│ ├── runner.py # Orchestriert setup → agent → Sicherheitstests → Regressionstests
│ ├── result.py # BenchmarkResult- und TestResult-Dataclasses, JSON-Serialisierung
│ └── repository.py # Schreibt Ergebnisdateien auf die Festplatte
└── task/
├── tools.py # Tool-Implementierungen: ListFiles, ReadFile, SearchInFiles,
│ # EditFile, CreateFile, DeleteFile, RunPytest
└── prompt_loader.py # Liest advisory.md / diagnose.md / locate.md
Dem Agenten zur Verfügung stehende Tools:
| Tool | Beschreibung |
|---|---|
list_files | Dateien und Verzeichnisse im Repository auflisten |
read_file | Dateiinhalte lesen, optional einen Zeilenbereich |
search_in_files | Regex-Suche über die Codebasis mit optionalem Datei-Glob |
edit_file | Einen Zeilenbereich in einer vorhandenen Datei ersetzen |
create_file | Eine neue Datei erstellen |
delete_file | Eine Datei löschen |
run_pytest | Das Testsuite des Projekts ausführen; gibt einen JSON-Bericht zurück |
Alle Tools validieren Pfade relativ zum Repository-Stammverzeichnis, um Verzeichnis-Traversierung zu verhindern. Der Agent hat keinen Zugriff auf test_security.py oder auf die Git-Historie.