
Un benchmark para evaluar agentes de IA en la corrección de vulnerabilidades de seguridad del mundo real.
Un benchmark para evaluar agentes de LLM en la corrección de vulnerabilidades de seguridad reales. Los agentes se ejecutan dentro de contenedores Docker aislados y se puntúan según la suite de pruebas de seguridad del mantenedor.
OPENAI_API_KEY, ANTHROPIC_API_KEY y/o POOLSIDE_API_KEY en tu entorno (o un archivo .env)Instalar dependencias:
pip install poetry
poetry install
Cada tarea se encuentra en tasks/{CVE-ID}/ y contiene:
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
Ejemplo de 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 es idempotente y se puede volver a ejecutar sin riesgos. test_security.py se mantiene oculto para el agente durante la ejecución y se inyecta solo después de que el agente termine.
python build.py
Esto construye:
cve-bench/base): Python 3.12, git, poetry y el harness.cve-bench/{task-id}): extiende la base, copia el directorio de la tarea y ejecuta setup.sh.Opciones:
# Construir solo tareas específicas
python build.py --task CVE-2026-33175 CVE-2026-42561
# Omitir la reconstrucción de la imagen base
python build.py --skip-base
Las imágenes de tarea se construyen en paralelo (hasta 5 workers). Si un directorio de tarea contiene un Dockerfile, se usa en lugar del docker/task.Dockerfile genérico.
Antes de ejecutar el benchmark, verifica que las pruebas de seguridad de cada tarea distinguen correctamente el código vulnerable del corregido:
python validate.py
Para cada tarea, esto ejecuta tres fases dentro del contenedor de la tarea:
| Fase | Qué comprueba |
|---|---|
| vulnerable | Las pruebas de seguridad deben fallar (o marcar xfail) en el SHA vulnerable |
| corregido | Las pruebas de seguridad deben pasar en el SHA corregido |
| regresión | Las pruebas no relacionadas con seguridad deben pasar en el SHA corregido |
Los resultados se muestran en una tabla en vivo. El código de salida es 1 si alguna tarea falla en alguna fase.
# Validar solo tareas específicas
python validate.py --task CVE-2026-33175 GHSA-r758-8hxw-4845
# Omitir la reconstrucción de imágenes antes de la validación
python validate.py --skip-build
python benchmark.py --model openai:gpt-5.5 poolside:laguna-m.1 --prompt-type advisory
Opciones:
Proveedores compatibles:
Cada ejecución produce un archivo de resultados JSON en results/:
results/{task-id}__{provider}:{model}__{prompt-type}.json
Los archivos de resultados existentes se omiten automáticamente. Las ejecuciones se realizan de forma concurrente entre tareas (hasta 20 workers), con límite de velocidad por proveedor (una única solicitud activa por proveedor a la vez) para evitar errores 429.
Cada archivo de resultado es un objeto JSON con la siguiente estructura:
{
"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 es o bien "security" (de test_security.py) o bien "regression" (de la suite de pruebas del propio proyecto). Una ejecución se considera resuelta solo si todas las pruebas de seguridad pasan y ninguna prueba de regresión falla.
python generate_charts.py
Lee todos los archivos de resultados de results/ y escribe gráficos SVG en docs/images/charts/. Requiere Chrome/Chromium para la exportación sin interfaz de Bokeh (mediante chromedriver-binary).
El harness se ejecuta dentro de cada contenedor Docker como python -m harness.run. Es responsable de cargar el prompt, ejecutar el bucle del agente y escribir el archivo de resultados.
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
Herramientas disponibles para el agente:
Todas las herramientas validan las rutas contra la raíz del repositorio para evitar el directory traversal. El agente no tiene acceso a test_security.py ni al historial de git.
El bucle del agente se ejecuta durante como máximo 20 turnos. Si se alcanza el límite de turnos, la ejecución se registra tal cual y las pruebas de seguridad se ejecutan igualmente sobre el estado en que el agente haya dejado el repositorio.
tasks/{CVE-ID}/ y añade meta.json, setup.sh, run_tests.sh, test_security.py, advisory.md, diagnose.md, locate.md.setup.sh y run_tests.sh (chmod +x).python validate.py --task {CVE-ID}.python build.py --task {CVE-ID}.Este trabajo se realizó como investigación independiente. En el momento de llevar a cabo la investigación y preparar este repositorio, no tenía ninguna afiliación institucional.
@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: consulte LICENSE.
| Opción | Descripción | Valor predeterminado |
|---|
--model | Una o más cadenas provider:model-id | todos los modelos configurados |
--prompt-type | advisory, diagnose, locate o cualquier combinación | las tres |
--task | Uno o más IDs de tarea | todas las tareas |
--clean | Eliminar los resultados existentes para el alcance seleccionado antes de comenzar | desactivado |
| Proveedor | Formato | Variable de entorno de la clave de 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 |
| Herramienta | Descripción |
|---|
list_files | Lista archivos y directorios del repositorio |
read_file | Lee el contenido de un archivo, opcionalmente un rango de líneas |
search_in_files | Búsqueda regex en el código con un glob opcional de archivos |
edit_file | Reemplaza un rango de líneas en un archivo existente |
create_file | Crea un archivo nuevo |
delete_file | Elimina un archivo |
run_pytest | Ejecuta la suite de pruebas del proyecto; devuelve un informe JSON |