
Бенчмарк для оценки 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 и harness.cve-bench/{task-id}) — расширяет базовый образ, копирует директорию задачи и запускает setup.sh.Опции:
# Сборка только определённых задач
python build.py --task CVE-2026-33175 CVE-2026-42561
# Пропустить пересборку базового образа
python build.py --skip-base
Образы задач собираются параллельно (до 5 рабочих процессов). Если директория задачи содержит Dockerfile, он используется вместо стандартного docker/task.Dockerfile.
Перед запуском эталона убедитесь, что тесты безопасности каждой задачи правильно различают уязвимый и исправленный код:
python validate.py
Для каждой задачи выполняются три фазы внутри контейнера задачи:
| Фаза | Что проверяется |
|---|---|
| уязвимая | Тесты безопасности должны завершиться неудачей (или xfail) на уязвимой SHA |
| исправленная | Тесты безопасности должны пройти на исправленной SHA |
| регрессия | Не-безопасностные тесты должны пройти на исправленной SHA |
Результаты отображаются в виде таблицы в реальном времени. Код выхода 1, если хотя бы одна задача не проходит какую-либо фазу.
# Проверка только определённых задач
python validate.py --task CVE-2026-33175 GHSA-r758-8hxw-4845
# Пропустить пересборку образов перед проверкой
python validate.py --skip-build
python benchmark.py --model openai:gpt-5.5 poolside:laguna-m.1 --prompt-type advisory
Опции:
Поддерживаемые провайдеры:
Каждый запуск создаёт JSON-файл с результатами в results/:
results/{task-id}__{provider}:{model}__{prompt-type}.json
Существующие файлы результатов автоматически пропускаются. Запуски выполняются параллельно по задачам (до 20 рабочих процессов) с ограничением скорости на провайдера (один активный запрос на провайдера в момент времени) для избежания ошибок 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" (из собственного набора тестов проекта). Запуск считается решённым, только если все тесты безопасности пройдены и ни один регрессионный тест не провален.
python generate_charts.py
Читает все файлы результатов из results/ и записывает SVG-графики в docs/images/charts/. Требуется Chrome/Chromium для экспорта Bokeh без отображения (через chromedriver-binary).
Harness запускается внутри каждого Docker-контейнера как python -m harness.run. Он отвечает за загрузку промпта, выполнение агентного цикла и запись файла результата.
src/harness/
├── run.py # Точка входа; разбирает аргументы, подключает компоненты, вызывает BenchmarkRunner
├── client/
│ ├── factory.py # Разбирает `provider:model-id`, возвращает соответствующий LLMClient
│ ├── _client.py # Абстрактный LLMClient, датаклассы ToolCall и LLMTurn
│ ├── anthropic.py # Интеграция с Anthropic SDK
│ └── oai.py # Интеграция с OpenAI SDK (также используется для Poolside)
├── agent/
│ ├── core.py # Агентский цикл: вызов клиента, диспетчеризация вызовов инструментов, организация сообщений
│ └── runner.py # Обёртка над Agent, отслеживание времени и списка витков
├── bench/
│ ├── runner.py # Оркестрация: настройка → агент → тесты безопасности → регрессионные тесты
│ ├── result.py # Даталклассы BenchmarkResult и TestResult, JSON-сериализация
│ └── repository.py # Запись файлов результатов на диск
└── task/
├── tools.py # Реализации инструментов: ListFiles, ReadFile, SearchInFiles,
│ # EditFile, CreateFile, DeleteFile, RunPytest
└── prompt_loader.py # Чтение advisory.md / diagnose.md / locate.md
Инструменты агента:
Все инструменты проверяют пути относительно корня репозитория для предотвращения выхода за его пределы. Агент не имеет доступа к 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.
| Флаг | Описание | По умолчанию |
|---|
--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 |
| Инструмент | Описание |
|---|
list_files | Вывести список файлов и директорий в репозитории |
read_file | Прочитать содержимое файла, опционально диапазон строк |
search_in_files | Поиск по регулярному выражению по кодовой базе с опциональным глобом для файлов |
edit_file | Заменить диапазон строк в существующем файле |
create_file | Создать новый файл |
delete_file | Удалить файл |
run_pytest | Запустить тестовый набор проекта; возвращает JSON-отчёт |