CVELab
cvelab generates and runs local labs for reproducible validation of vulnerabilities described by a CVE. The user supplies a CVE identifier, and the application attempts to resolve public sources, build the environment, execute a safe proof of concept (PoC), and produce evidence, a walkthrough, and a report.
The generator does not treat a reflected marker alone as proof. A successful result must demonstrate the vulnerability's effect on the actual vulnerable artifact.
Documentation
- Complete installation and usage guide
- Linux bundle and installation
- Benchmark method
- Acceptable use
- Security policy
- Contributing
- Changelog
- Roadmap
Native Linux is the recommended platform. Windows remains supported through Docker Desktop or the Docker Engine fallback in Kali WSL.
Possible outcomes
SOURCE_REPRODUCTION: both vulnerable and fixed versions are reproduced; the test succeeds against the vulnerable version and is blocked by the patched version.VULNERABLE_ONLY_REPRODUCTION: the vulnerable version is validated, but no public fix can be identified. A patched version is not fabricated.CLOSED_SOURCE_REPRODUCTION: uses only a legally obtained proprietary artifact registered locally.ARTIFACT_REQUIRED: the source code, image, or binary needed for a faithful reproduction is missing.POC_NOT_GENERATED: the available information is insufficient for real, verifiable proof.
Requirements
- Linux or Windows 10/11.
- Python 3.11 or newer.
- Docker Engine on Linux or Docker Desktop on Windows.
- Git available in
PATH. - Bash, Make, and curl for E2E profiles that use Shipyard/Kind.
- WSL with a Kali distribution is required for Shipyard only on Windows.
- An OpenAI or Anthropic API key, or a local OpenAI-compatible model server, for automatic adapter generation.
- Legal access to the product and any required license for closed-source software.
Installation
On Kali/Debian:
sudo apt update
sudo apt install -y docker.io docker-compose python3-venv git make curl
sudo systemctl enable --now docker
sudo usermod -aG docker "$USER"
newgrp docker
cd cvelab
python3 -m venv .venv
source .venv/bin/activate
python -m pip install .
cvelab --help
On Windows, from PowerShell:
cd "C:\OffSec Lab\cvelab"
py -m pip install .
cvelab --help
If the Python scripts directory is not in PATH:
& "$env:LOCALAPPDATA\Programs\Python\Python313\Scripts\cvelab.exe" --help
Before the first run
cvelab doctor
It checks Python, git, Docker, the Compose plugin, bash, the output directory
and its free space, and the provider configuration, then lists models at the
provider to confirm the key is accepted. --offline skips that one network
call. Each failure carries the command that fixes it, and the exit code is 2
when anything failed, so CI can gate on it.
Quick start
The recommended command for an open-source CVE on Linux is:
cvelab --output-root "$PWD/generated-labs" auto CVE-YYYY-NNNNN --ai on --key --model gpt-5.6-sol
On Windows:
cvelab --output-root "C:\OffSec Lab\cvelab\generated-labs" auto CVE-YYYY-NNNNN --ai on --key --model gpt-5.6-sol
The --key option without a value opens a masked prompt for the selected provider. The key is not written to the project or included in the command line.
AI providers
CVELab supports OpenAI, Anthropic, and local servers exposing an OpenAI-compatible
/v1/chat/completions endpoint. Selecting the provider explicitly is recommended.
OpenAI:
cvelab auto CVE-YYYY-NNNNN \
--provider openai --key --model YOUR_OPENAI_MODEL
Anthropic:
cvelab auto CVE-YYYY-NNNNN \
--provider anthropic --key --model YOUR_ANTHROPIC_MODEL
DeepSeek:
cvelab auto CVE-YYYY-NNNNN \
--provider deepseek --key --model deepseek-flash
DeepSeek has no web search, so when a CVE record names no commit, CVELab cannot ask the model to find one. The OSV resolver covers nearly all of that without any model at all. DeepSeek also bills peak hours at double (01:00-04:00 and 06:00-10:00 UTC on weekdays), and the cost CVELab reports uses the off-peak rate.
Local model, using Ollama's default OpenAI-compatible endpoint:
ollama create cvelab-qwen2.5-coder:7b -f linux/ollama/Modelfile.qwen2.5-coder-7b
cvelab auto CVE-YYYY-NNNNN \
--provider local \
--base-url http://127.0.0.1:11434/v1 \
--model cvelab-qwen2.5-coder:7b
Use an Ollama Modelfile with enough context for source patches and generated adapters:
FROM qwen2.5-coder:7b
PARAMETER num_ctx 65536
The standard Ollama context on GPUs below 24 GiB is only 4096 tokens, which is too small
for typical CVELab source-generation prompts. A 64K context is recommended. Larger context
windows require more RAM or VRAM. Local generation can be slow on CPU, so CVELab allows
30 minutes per local response by default; override this with CVELAB_LOCAL_TIMEOUT in seconds.
A local API key is optional. For servers such as vLLM, llama.cpp, or an authenticated
gateway, change --base-url and pass --key when required.
The equivalent environment variables are:
export CVELAB_AI_PROVIDER=openai # openai, anthropic, deepseek, or local
export CVELAB_MODEL=YOUR_MODEL
export OPENAI_API_KEY=YOUR_KEY # OpenAI only
export ANTHROPIC_API_KEY=YOUR_KEY # Anthropic only
export DEEPSEEK_API_KEY=YOUR_KEY # DeepSeek only
export CVELAB_ANTHROPIC_EFFORT=low # optional: low, medium, high, xhigh, max
export CVELAB_BASE_URL=http://127.0.0.1:11434/v1 # local only
# Any provider's endpoint and timeout can be redirected, which is how a
# corporate gateway or a proxy is used:
export CVELAB_OPENAI_BASE_URL=https://gateway.internal/v1
export CVELAB_DEEPSEEK_TIMEOUT=120
export CVELAB_LOCAL_API_KEY=YOUR_KEY # optional local authentication
export CVELAB_LOCAL_TIMEOUT=1800 # optional local request timeout
With --provider auto, CVELAB_BASE_URL selects local, an Anthropic key without an
OpenAI key selects Anthropic, and OpenAI is the fallback. Local endpoints do not provide
CVELab with web search. If the CVE record does not contain exact source references, pass
--repo, --vulnerable-ref, and, when available, --fixed-ref explicitly.
Example:
cvelab --output-root "C:\OffSec Lab\cvelab\generated-labs" auto CVE-2026-47342 --ai on --key --model gpt-5.6-sol
The auto workflow:
- Collects public CVE metadata.
- Identifies the repository and vulnerable revision.
- Identifies the public fix, if available.
- Obtains the required source snapshots.
- Generates a product-specific adapter.
- Validates the adapter's structure before running Docker.
- Builds and starts the local lab.
- Executes the PoC and verifies the actual effect.
- Automatically runs the manual PoC actions (
exploitandverify) against each variant as well. - If the build, startup, or proof fails, captures logs, regenerates the adapter based on the observed cause, and repeats validation (up to 4 attempts by default).
- Writes the evidence, walkthrough, and final report only after validation.
No intervention is required between attempts. To change the maximum number of attempts:
cvelab --output-root "$PWD/generated-labs" auto CVE-YYYY-NNNNN \
--key --model gpt-5.6-sol --max-attempts 6
The history of generation, errors, repairs, and validation is saved in
generated-labs/CVE-YYYY-NNNNN/automation.json.
CVEs with a public fix
When both the vulnerable version and the fix are available, the expected result is differential:
{
"ok": true,
"real_poc_verified": true,
"patched_tested": true,
"differential_confirmed": true
}
This means the same test case demonstrated the effect on the vulnerable version and its absence on the fixed version.
References can be provided explicitly:
cvelab --output-root "C:\OffSec Lab\cvelab\generated-labs" auto CVE-YYYY-NNNNN `
--repo https://github.com/owner/project.git `
--vulnerable-ref <vulnerable-commit> `
--fixed-ref <fix-commit> `
--ai on --key --model gpt-5.6-sol
CVEs without a public fix
The same auto command can produce a real PoC against only the vulnerable version when vulnerable source code is available but no fix has been published or identified. The generator does not unnecessarily require --fixed-ref or create a synthetic patched service.
cvelab --output-root "C:\OffSec Lab\cvelab\generated-labs" auto CVE-YYYY-NNNNN `
--repo https://github.com/owner/project.git `
--vulnerable-ref <vulnerable-commit> `
--ai on --key --model gpt-5.6-sol
A successful result without a fix indicates:
{
"ok": true,
"real_poc_verified": true,
"fix_status": "PUBLIC_FIX_NOT_IDENTIFIED",
"patched_tested": false,
"differential_confirmed": false
}
This is a proof of the vulnerability, but it does not validate remediation. The report retains this limitation and does not claim that a fixed version exists.
Main commands
| Command | Purpose |
|---|---|
doctor |
Checks the environment before a run spends time and money. |
auto |
Resolves information, builds the lab, runs the PoC, and produces deliverables. |
run |
Runs a previously generated lab again. |
source |
Generates a source-level lab using explicit Git references. |
source-all |
Generates and runs the source-level lab. |
build |
Generates a CWE-class lab; this is not a real product PoC. |
all |
Generates and runs the CWE-class lab. |
closed-auto |
Resolves requirements for a closed-source product and uses a registered local artifact. |
closed |
Builds the closed-source reproduction from the catalog. |
Run an existing lab again:
cvelab --output-root "C:\OffSec Lab\cvelab\generated-labs" run CVE-YYYY-NNNNN
Generate a source-level lab explicitly:
cvelab source CVE-YYYY-NNNNN `
--repo https://github.com/owner/project.git `
--vulnerable-ref <vulnerable-commit> `
--fixed-ref <fix-commit> `
--ai on --key --model gpt-5.6-sol
Generate and run in a single command:
cvelab source-all CVE-YYYY-NNNNN `
--repo https://github.com/owner/project.git `
--vulnerable-ref <vulnerable-commit> `
--fixed-ref <fix-commit> `
--ai on --key --model gpt-5.6-sol
What a run costs
auto makes up to four attempts, and each prompt can carry source patches, so
one CVE is not one model call. Every run reports its exact token counts, from
the provider's own figures, on stderr and in automation.json:
[cvelab] 2 model call(s) | 815,000 in | 79,000 out | 310,000 cached | ~$4.84
The dollar figure is an estimate from a price table with a date on it; the provider's invoice is authoritative. A model the table does not know reports its tokens and no price rather than a guess. To price one yourself, or to override the table:
export CVELAB_PRICE_INPUT=4.00 # USD per million input tokens
export CVELAB_PRICE_OUTPUT=20.00 # USD per million output tokens
Progress goes to stderr while a run clones, builds and validates, so stdout
stays a JSON document you can pipe. --quiet, or CVELAB_QUIET, silences it.
Deliverables
A validated lab is created in:
generated-labs/<CVE>/
Key files:
e2e/result.json: the verifiable result and reproduction statuses.e2e/: the product-specific E2E runner and probes, if used by the profile.validator/validator.py: the executable PoC/validator for the generated adapter.artifacts/PoC.py(or the profile-specific payload): the inspectable local PoC.artifacts/manual.sh: the Linux runner with separatesetup,exploit,verify, andcleanupactions.artifacts/MANUAL-POC.md: manual reproduction instructions.artifacts/EVIDENCE.json: structured evidence and provenance.artifacts/WALKTHROUGH.md: manual reproduction steps.artifacts/REPORT.md: the technical report, limitations, and conclusion.docker-compose.yml: the local Docker lab topology.source/: the Git snapshots used by the lab.
For manual reproduction, follow artifacts/WALKTHROUGH.md. An accepted PoC must include the exact command or request, the observable effect, and the verification method. An ok: true field alone is insufficient without supporting evidence in the result.
On Kali/Linux, after a successful auto run:
cd generated-labs/CVE-YYYY-NNNNN/artifacts
bash manual.sh setup vulnerable
bash manual.sh exploit vulnerable
bash manual.sh verify vulnerable
bash manual.sh cleanup
For a CVE with a public fix, repeat the same steps with patched; the expected verdict is
BLOCKED. For VULNERABLE_ONLY_REPRODUCTION, the patched variant is not offered.
Every report uses the same contract and includes the fidelity level, vendor components
executed, simulated components, raw vulnerable/patched evidence, the probe contract, and
provenance. source_component does not mean product E2E; only
product_end_to_end together with product_e2e_verified: true confirms that level.
Closed-source software
cvelab closed-auto CVE-YYYY-NNNNN --key --model gpt-5.6-sol
If the product requires authentication, entitlement, or a license, the application stops with ARTIFACT_REQUIRED. After legally obtaining the image or installation package, register the artifact once in closed-catalog.json, then the command can continue.
The generator does not bypass vendor authentication, download pirated software, or substitute a synthetic simulation for the real product.
API key and model
Recommended approach:
cvelab auto CVE-YYYY-NNNNN --ai on --key --model gpt-5.6-sol
Alternatively:
$env:OPENAI_API_KEY = "your-api-key"
$env:CVELAB_MODEL = "gpt-5.6-sol"
cvelab auto CVE-YYYY-NNNNN --ai on
Do not put the key in files, commits, screenshots, or public examples. If a key is exposed, revoke and replace it.
Docker Desktop on Windows
Before running auto or run, Docker must respond:
docker version
docker context show
docker info
If Shipyard fails while pushing to localhost:5000 with EOF or connection reset,
check temporarily without a VPN. Some VPN policies block Docker daemon access to
published ports and bridge subnets, even when the registry is healthy between
containers. Retry the test only after curl http://127.0.0.1:5000/v2/ can
reach a local registry published by Docker.
The runner handles known transient Docker context and Docker Desktop socket errors. If the Docker Desktop backend shuts down completely, the lab cannot continue until the engine is available again.
Errors such as Dockerfile.vulnerable: no such file or directory should be detected during preflight. An incomplete AI adapter is rejected rather than partially launched.
Cleanup removes only the current lab's resources. The project does not use docker system prune --volumes for normal cleanup.
Docker Engine on Linux
The Shipyard runner is launched directly through Bash and uses the current user's
Docker Engine. WSL, Docker Desktop, and separate host installations of kubectl, Kind,
or Helm are not required; the profile's Kubernetes tools are provided by the Shipyard
environment. Verify with:
docker version
docker compose version
docker info
Limitations
- No generator can faithfully reproduce every CVE from its identifier alone.
- A CVE without public vulnerable code or a legally available artifact remains
ARTIFACT_REQUIREDorPOC_NOT_GENERATED. - The absence of a public fix does not prevent a PoC against the vulnerable version, but it prevents differential validation of remediation.
- A guessed repository or commit is not accepted as provenance.
- AI generates the adapter, but the result is accepted only after executable verification of the effect.
- Synthetic CWE-class labs are demonstrations, not PoCs for the product named by the CVE.
Safety
- Labs are intended for authorized research.
- Generated services are restricted to loopback and the internal Docker network.
- Payloads must be nondestructive.
- Do not scan or attack external targets.
- Any test on a system you do not own requires explicit authorization.
Generated labs contain intentionally vulnerable software. Treat every lab directory as untrusted, and do not run labs on production hosts, on machines holding sensitive data, or on shared networks. The full boundaries are in ACCEPTABLE_USE.md.
To report a vulnerability in CVELab itself, follow SECURITY.md. Do not open a public issue.
Contributing
Reports of CVEs that fail to reproduce are the most useful contribution, and have their own issue template. See CONTRIBUTING.md for the development setup and the Developer Certificate of Origin sign-off that every commit needs.
Support
- Bugs and reproduction failures: open an issue.
- Usage questions: Discussions, or support@syncbitsoft.com.
- Security reports: see SECURITY.md. Never a public issue.
License
Apache License, Version 2.0. See LICENSE and NOTICE.
Copyright 2026 SyncBit Software SRL and the CVELab contributors.
CVE and the CVE logo are trademarks of The MITRE Corporation. CVELab is an independent open-source project, not affiliated with, endorsed by, sponsored by, or certified by The MITRE Corporation or the CVE Program, and it does not claim CVE-Compatible status.
Metadata
Release files for cvelab 0.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| cvelab-0.6.0.tar.gz | 105.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cvelab-0.6.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 194.2 kB
Release files / cvelab-0.6.0.tar.gz
| Download URL | cvelab-0.6.0.tar.gz |
|---|---|
| Size | 105.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
901067ea69c7d644f129491f972616576e64be68dbf4fb14ef5ef872cc2bfb5e
|
|
BLAKE2b-256 checksum How to use checksums |
da2868f1945bdebc98bf8e7a58c1c48ff9b465e78982165a9e7531a8acb6b182
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.
Transparency logRelease files / cvelab-0.6.0-py3-none-any.whl
| Download URL | cvelab-0.6.0-py3-none-any.whl |
|---|---|
| Size | 88.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ddb5219710dec71ad92cae385112120226a07180f52f1a07e77927e4a91512bd
|
|
BLAKE2b-256 checksum How to use checksums |
d771de3fa665f90fb25f46676cf49e50c75956e9bb15ad541868f554e3fc706d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.
Transparency log