
Um benchmark para avaliar agentes de IA na correção de vulnerabilidades de segurança do mundo real.
Um benchmark para avaliar agentes LLM na correção de vulnerabilidades de segurança do mundo real. Os agentes são executados dentro de contêineres Docker isolados e pontuados com base na suíte de testes de segurança do mantenedor.
OPENAI_API_KEY, ANTHROPIC_API_KEY e/ou POOLSIDE_API_KEY no seu ambiente (ou um arquivo .env)Instale as dependências:
pip install poetry
poetry install
Cada tarefa reside em tasks/{CVE-ID}/ e contém:
tasks/CVE-2026-33175/
├── meta.json # ID do GHSA, CWE, CVSS, URL do repositório, SHAs vulnerável e corrigida
├── setup.sh # Clona o repositório, faz checkout do SHA vulnerável, instala dependências
├── run_tests.sh # Injeta test_security.py no repositório e executa pytest
├── test_security.py # Testes de segurança (xfail no código vulnerável, passam na correção)
├── advisory.md # Comunicado completo do GHSA (prompt mais rico)
├── diagnose.md # Apenas descrição comportamental — sem nomes de arquivos ou funções
├── locate.md # Apenas arquivo e função — sem descrição da falha
└── Dockerfile # Opcional; presente apenas quando a tarefa precisa de dependências extras do sistema
Exemplo 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 é idempotente e seguro para ser executado novamente. test_security.py é mantido oculto do agente durante a execução e injetado apenas após o término do agente.
python build.py
Isso constrói:
cve-bench/base) — Python 3.12, git, poetry e o harness.cve-bench/{task-id}) — estende a base, copia o diretório da tarefa e executa setup.sh.Opções:
# Construir apenas tarefas específicas
python build.py --task CVE-2026-33175 CVE-2026-42561
# Pular a reconstrução da imagem base
python build.py --skip-base
As imagens das tarefas são construídas em paralelo (até 5 workers). Se um diretório de tarefa contiver um Dockerfile, ele será usado em vez do docker/task.Dockerfile genérico.
Antes de executar o benchmark, verifique se os testes de segurança de cada tarefa distinguem corretamente o código vulnerável do código corrigido:
python validate.py
Para cada tarefa, isso executa três fases dentro do contêiner da tarefa:
| Fase | O que verifica |
|---|---|
| vulnerável | Os testes de segurança devem falhar (ou xfail) no SHA vulnerável |
| corrigido | Os testes de segurança devem passar no SHA corrigido |
| regressão | Os testes não relacionados à segurança devem passar no SHA corrigido |
Os resultados são exibidos como uma tabela ao vivo. O código de saída é 1 se alguma tarefa falhar em qualquer fase.
# Validar apenas tarefas específicas
python validate.py --task CVE-2026-33175 GHSA-r758-8hxw-4845
# Pular reconstrução de imagens antes da validação
python validate.py --skip-build
python benchmark.py --model openai:gpt-5.5 poolside:laguna-m.1 --prompt-type advisory
Opções:
Provedores suportados:
Cada execução produz um arquivo de resultado JSON em results/:
results/{task-id}__{provider}:{model}__{prompt-type}.json
Arquivos de resultado existentes são ignorados automaticamente. As execuções são realizadas simultaneamente entre as tarefas (até 20 workers), com limitação de taxa por provedor (uma requisição ativa por provedor por vez) para evitar erros 429.
Cada arquivo de resultado é um objeto JSON com a seguinte estrutura:
{
"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" (de test_security.py) ou "regression" (da própria suíte de testes do projeto). Uma execução é considerada resolvida apenas se todos os testes de segurança passarem e nenhum teste de regressão falhar.
python generate_charts.py
Lê todos os arquivos de resultado de results/ e escreve gráficos SVG em docs/images/charts/. Requer Chrome/Chromium para exportação headless do Bokeh (via chromedriver-binary).
O harness é executado dentro de cada contêiner Docker como python -m harness.run. Ele é responsável por carregar o prompt, executar o loop agêntico e escrever o arquivo de resultado.
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
Ferramentas disponíveis para o agente:
Todas as ferramentas validam caminhos em relação à raiz do repositório para evitar traversal de diretório. O agente não tem acesso a test_security.py nem ao histórico do git.
O loop do agente é executado por no máximo 20 turnos. Se o limite de turnos for atingido, a execução é registrada como está e os testes de segurança ainda são executados contra o estado em que o agente deixou o repositório.
tasks/{CVE-ID}/ e adicione meta.json, setup.sh, run_tests.sh, test_security.py, advisory.md, diagnose.md, locate.md.setup.sh e run_tests.sh executáveis (chmod +x).python validate.py --task {CVE-ID}.python build.py --task {CVE-ID}.Este trabalho foi conduzido como pesquisa independente. No momento da realização da pesquisa e preparação deste repositório, não tinha nenhuma afiliação 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 — veja LICENSE.
| Bandeira | Descrição | Padrão |
|---|
--model | Uma ou mais strings provider:model-id | todos os modelos configurados |
--prompt-type | advisory, diagnose, locate, ou qualquer combinação | todos os três |
--task | Um ou mais IDs de tarefas | todas as tarefas |
--clean | Excluir resultados existentes para o escopo selecionado antes de iniciar | desligado |
| Provedor | Formato | Variável de ambiente da chave 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 |
| Ferramenta | Descrição |
|---|
list_files | Lista arquivos e diretórios no repositório |
read_file | Lê o conteúdo de um arquivo, opcionalmente um intervalo de linhas |
search_in_files | Busca regex na base de código com glob opcional de arquivos |
edit_file | Substitui um intervalo de linhas em um arquivo existente |
create_file | Cria um novo arquivo |
delete_file | Exclui um arquivo |
run_pytest | Executa a suíte de testes do projeto; retorna um relatório JSON |