Skip to main content

CVELab

CI License: Apache-2.0 Python 3.11+

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

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:

  1. Collects public CVE metadata.
  2. Identifies the repository and vulnerable revision.
  3. Identifies the public fix, if available.
  4. Obtains the required source snapshots.
  5. Generates a product-specific adapter.
  6. Validates the adapter's structure before running Docker.
  7. Builds and starts the local lab.
  8. Executes the PoC and verifies the actual effect.
  9. Automatically runs the manual PoC actions (exploit and verify) against each variant as well.
  10. 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).
  11. 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 separate setup, exploit, verify, and cleanup actions.
  • 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_REQUIRED or POC_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

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)

Source distribution for cvelab 0.6.0
File Size Uploaded
cvelab-0.6.0.tar.gz 105.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cvelab 0.6.0
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

0.6.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page