Vulnerability Localization Benchmark is an agentic benchmark for evaluating AI models on repository-scale vulnerability localization. Given a vulnerability description and read-only terminal access to a codebase, models must explore the repository and identify which files contain security vulnerabilities.
Key Features:
- 500 real-world vulnerabilities from public GitHub Security Advisories
- Two-phase evaluation: Phase A (find vulnerabilities) and Phase B (confirm fixes)
- Multi-ecosystem coverage: npm, pip, maven, go, rust, composer
- Docker-sandboxed evaluation environment
- Reproducible with MD5-verified dataset
Unlike static code understanding benchmarks, Vulnerability Localization Benchmark measures end-to-end localization performance in realistic repository exploration settings using terminal-based interactions.
π Technical Report (coming soon) | arXiv (coming soon)
- Python 3.11 or higher
- Docker (for sandboxed evaluation)
- A model server supporting OpenAI-compatible API (e.g., vLLM)
# Verify Python version
python3 --version
# Verify Docker installation
docker --version-
Clone the repository
git clone https://github.com/cisco-foundation-ai/vulnerability-localization-benchmark.git cd vulnerability-localization-benchmark -
Install the package
pip install -e . -
Build the sandbox Docker image
docker build -t vulnerability-localization-benchmark-sandbox . -
Download and verify the dataset
python data/downloader_and_verifier.py --source-dir /path/to/dataset/
This downloads all 500 repository pairs into
data/ghsa-vulns/{alpha_id}/and verifies MD5 checksums.
-
Start your model server (example with vLLM):
CUDA_VISIBLE_DEVICES=0 python -m vllm.entrypoints.openai.api_server \ --model /path/to/model \ --served-model-name your-model \ --host 0.0.0.0 --port 8200 \ --dtype bfloat16 --gpu-memory-utilization 0.9 \ --max-model-len 32768 --tensor-parallel-size 1 \ --trust-remote-code -
Run Phase A evaluation (vulnerable codebases):
PYTHONPATH=src python3 -m vulnerability_localization_benchmark.cli \ --config configs/default.yaml \ --api-base http://localhost:8200/v1 \ --model-name your-model \ --runner vllm \ --output-dir results/my-run \ --phases a \ --workers 16 -
Run Phase B evaluation (patched codebases):
PYTHONPATH=src python3 -m vulnerability_localization_benchmark.cli \ --config configs/default.yaml \ --api-base http://localhost:8200/v1 \ --model-name your-model \ --runner vllm \ --output-dir results/my-run \ --phases b \ --workers 16
Phase A (pre_push): Model explores vulnerable codebase with terminal access (15 tool call budget), then submits files it believes contain the vulnerability. Scored on File F1 against ground truth.
Phase B (post_push): Model explores patched codebase under same protocol. Should declare "no vulnerability found". Scored on True Negative Rate.
500 real-world vulnerabilities across 6 ecosystems. 78% have assigned CVEs.
| Severity | Count | CWE Types | Ecosystems |
|---|---|---|---|
| High | 219 | 147 unique | npm, pip, maven, go, rust, composer |
| Medium | 194 | ||
| Critical | 57 | ||
| Low | 30 |
π See DATASET_CARD.md for detailed dataset documentation including data fields, biases, statistics, and licensing.
Critical: Signature Bypass (CVE-2024-32962)
- Repository: node-saml/xml-crypto (npm/JavaScript)
- CWE-347: Improper Verification of Cryptographic Signature
- Ground Truth:
src/signed-xml.ts(single file) - Challenge: Default configuration doesn't check signer authorization, only signature validity
Medium: Mutex Unsoundness
- Repository: Amanieu/parking_lot (rust)
- CWE-362: Concurrent Execution using Shared Resource with Improper Synchronization
- Ground Truth:
lock_api/src/lib.rs,lock_api/src/mutex.rs,lock_api/src/rwlock.rs(3 files) - Challenge: Data race in lock implementation affecting multiple synchronization primitives
Severity Distribution:
| Severity | Count |
|---|---|
| High | 219 |
| Medium | 194 |
| Critical | 57 |
| Low | 30 |
Top CWEs (147 unique):
| CWE | Count |
|---|---|
| CWE-400 (Resource Exhaustion) | 53 |
| CWE-20 (Improper Input Validation) | 45 |
| CWE-200 (Information Exposure) | 27 |
| CWE-22 (Path Traversal) | 27 |
| CWE-770 (Allocation without Limits) | 23 |
Top Repositories:
| Repository | Count |
|---|---|
| mmaitre314/picklescan | 21 |
| undertow-io/undertow | 14 |
| kubernetes/kubernetes | 11 |
| vyperlang/vyper | 10 |
| keycloak/keycloak | 10 |
License Distribution:
| License | Count | Percentage |
|---|---|---|
| Apache-2.0 | 241 | 48.2% |
| MIT | 161 | 32.2% |
| Other | 46 | 9.2% |
| GPL-3.0 | 15 | 3.0% |
| LGPL | 12 | 2.4% |
| MPL-2.0 | 12 | 2.4% |
| BSD-3-Clause | 5 | 1.0% |
| Creative Commons | 4 | 0.8% |
| ISC | 2 | 0.4% |
| GPL-2.0 | 1 | 0.2% |
| AGPL-3.0 | 1 | 0.2% |
All repositories retain their original open source licenses. No license changes between vulnerable and patched states. The "Other" category includes dual-licensed crates and less common licenses (e.g., MIT OR Apache-2.0, EPL-2.0, BSD-2-Clause). See data/manifest.csv for license information per repository, and the NOTICE file for complete attribution requirements.
Note: License data verified via ScanCode and GitHub Licensee tools. Some entries have dual licenses (e.g., EPL-2.0 OR Apache-2.0) where either option may be used.
Each entry provides:
pre_push.zipβ repository at the vulnerable commit (Phase A input)post_push.zipβ repository after the fix is merged (Phase B input)ground_truth_filesβ code files modified by the security patch (excludes tests and non-code files)cwe_descriptionβ generic CWE definition (used in eval prompt)
| Flag | Description |
|---|---|
--config |
YAML config path (default: configs/default.yaml) |
--api-base |
Model endpoint URL |
--model-name |
Model name as served by vLLM |
--runner |
vllm_antares / vllm / vllm_qwen_3_5 / vllm_gemma_4 |
--output-dir |
Where to write results + traces |
--phases |
a, b, or ab |
--n-limit |
Max entries to evaluate (0 = all) |
--workers |
Parallel workers (default 1) |
--resume |
Skip entries with existing results |
--permissive |
Disable command validation (sandbox is isolated) |
| Runner | Endpoint | Use Case |
|---|---|---|
vllm |
/v1/chat/completions |
Generic models with native tool calling |
vllm_antares |
/v1/completions |
Antares models with built-in reasoning |
vllm_qwen_3_5 |
/v1/chat/completions |
Qwen 3.5 with tool parser |
vllm_gemma_4 |
/v1/chat/completions |
Gemma 4 with tool parser |
For more examples and advanced usage, see the full documentation.
Per entry, two files are written to --output-dir:
{alpha_id}_phase_{a|b}.jsonβ scores, metadata, submitted files{alpha_id}_phase_{a|b}_trace.jsonβ full conversation trace
Final aggregate scores are saved to aggregate.json.
- 15 terminal calls budget per entry
- Up to 20 turns total (generation cycles)
- If model emits 3 consecutive turns with no tool call β forced stop
- If terminal budget exhausted β nudge to submit
- frequency_penalty=0.3 prevents repetition loops
--permissiveskips command validation (recommended β container is sandboxed)- Docker container build: mean 0.41s, median 0.30s, max 1.0s
From configs/default.yaml:
| Parameter | Value | Why |
|---|---|---|
| max_tokens | 16384 | Per-turn generation cap |
| max_turns | 20 | Agent loop budget |
| terminal_calls | 15 | Per-entry budget |
For vllm_antares runner:
| Parameter | Value | Why |
|---|---|---|
| Endpoint | /v1/completions |
Raw text, NOT chat API |
| temperature | 0.3 | Low variance for eval |
| frequency_penalty | 0.3 | Prevent repetition loops |
| stop tokens | <|end_of_text|>, <|start_of_role|> |
Antares special tokens |
| Generation prefix | <think>\n |
Triggers reasoning mode |
Other runners (Qwen, Gemma) use /v1/chat/completions β vLLM handles template formatting via --tool-call-parser. The Antares runner uses /v1/completions with its own template and built-in reasoning via <think> prefix.
βββ pyproject.toml # pip-installable (hatchling)
βββ Dockerfile # vulnerability-localization-benchmark-sandbox image (ubuntu:24.04)
βββ configs/default.yaml # All tunable params
βββ data/
β βββ manifest.csv # 500 entries, 26 columns
β βββ downloader_and_verifier.py # Downloads + MD5-verifies all zips
β βββ deleted-repo-mirrors/ # Zips for repos no longer on GitHub
β β βββ GHSA-4999-659w-mq36/ # pre_push.zip, post_push.zip
β βββ ghsa-vulns/ # [gitignored] downloaded zips
β βββ {alpha_id}/
β βββ pre_push.zip # Vulnerable codebase (Phase A)
β βββ post_push.zip # Patched codebase (Phase B)
βββ src/vulnerability_localization_benchmark/
β βββ __init__.py
β βββ cli.py # Entrypoint, orchestrate workers
β βββ agent.py # Agent loop (runner-agnostic)
β βββ sandbox.py # Docker container per entry
β βββ scoring.py # File F1, TNR, aggregation
β βββ model_runners/
β βββ base.py # Shared system prompt + tools schema
β βββ vllm.py # Generic vLLM /v1/chat/completions
β βββ vllm_antares.py # Antares: raw /v1/completions
β βββ vllm_qwen_3_5.py # Qwen 3.5: tool calling
β βββ vllm_gemma_4.py # Gemma 4: tool calling
βββ results/ # [gitignored] eval output
GitHub Pages leaderboard served from docs/:
docs/
βββ index.html # Interactive single-page leaderboard (all CSS/JS inline)
βββ model-performance.json # Eval results data
We welcome submissions of new model results to the public leaderboard. To add your model:
-
Evaluate your model on the benchmark by following the evaluation instructions above. This produces a per-model results file.
-
Fork this repository.
-
Add your model's entry to
docs/model-performance.json. Each entry follows this schema:{ "model": "Your-Model-Name", "type": "frontier", // "frontier" or "open-weights" "size": "7B", // parameter count; "β" for closed frontier models "file_f1": 0.123, // Phase A: File F1 (0β1) "precision": 0.234, "recall": 0.201, "true_negative_rate": 0.567, // Phase B (optional) "false_positive_rate": 0.089, "submitted_nothing_rate": 0.145 } -
Open a pull request with your added entry and a short description of your evaluation setup (model version, harness, date).
To keep the leaderboard trustworthy, submissions should include enough detail to reproduce the run:
- The exact model identifier / version and inference settings (temperature, reasoning effort, etc.).
- The harness used (this repo's CLI, or a documented equivalent).
- Raw evaluation output (attach to the PR or link to it) so maintainers can spot-check the reported metrics.
Maintainers may request the raw prediction logs before merging. Once verified, your model appears on the live leaderboard.
See the open issues for proposed features and known issues.
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated. For detailed contributing guidelines, please see CONTRIBUTING.md.
Distributed under the Apache License 2.0. See LICENSE for more information.
Dataset Licensing: The benchmark dataset uses public vulnerability data and open source repositories that retain their original licenses. See NOTICE for attribution and license compliance requirements.
Cisco Foundation AI - GitHub
Project Link: https://github.com/cisco-foundation-ai/vulnerability-localization-benchmark
For questions about data sources, attribution, or licensing, please open an issue.
- Security researchers who discovered and responsibly disclosed these vulnerabilities
- The GitHub team for maintaining the Security Advisory Database
- All open source maintainers whose repositories are included in this benchmark