Metadata-Version: 2.4
Name: cvelab
Version: 0.6.0
Summary: Local-only CVE reproduction and PoC generator with differential vulnerable-versus-patched validation
Author-email: SyncBit Software SRL <contact@syncbitsoft.com>
Maintainer-email: SyncBit Software SRL <contact@syncbitsoft.com>
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/AndreiIonascu17/cvelab
Project-URL: Repository, https://github.com/AndreiIonascu17/cvelab
Project-URL: Documentation, https://github.com/AndreiIonascu17/cvelab/blob/main/GUIDE.md
Project-URL: Changelog, https://github.com/AndreiIonascu17/cvelab/blob/main/CHANGELOG.md
Project-URL: Issues, https://github.com/AndreiIonascu17/cvelab/issues
Project-URL: Security Policy, https://github.com/AndreiIonascu17/cvelab/blob/main/SECURITY.md
Keywords: cve,vulnerability,security,proof-of-concept,reproduction,docker,vulnerability-research,appsec,llm
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: Natural Language :: English
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Testing
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: ruff>=0.14; extra == "dev"
Requires-Dist: mypy>=1.13; extra == "dev"
Dynamic: license-file

# CVELab

[![CI](https://github.com/AndreiIonascu17/cvelab/actions/workflows/ci.yml/badge.svg)](https://github.com/AndreiIonascu17/cvelab/actions/workflows/ci.yml)
[![License: Apache-2.0](https://img.shields.io/badge/License-Apache--2.0-blue.svg)](LICENSE)
[![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/downloads/)

`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](GUIDE.md)
- [Linux bundle and installation](linux/README.md)
- [Benchmark method](benchmarks/README.md)
- [Acceptable use](ACCEPTABLE_USE.md)
- [Security policy](SECURITY.md)
- [Contributing](CONTRIBUTING.md)
- [Changelog](CHANGELOG.md)
- [Roadmap](ROADMAP.md)

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:

```bash
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:

```powershell
cd "C:\OffSec Lab\cvelab"
py -m pip install .
cvelab --help
```

If the Python scripts directory is not in `PATH`:

```powershell
& "$env:LOCALAPPDATA\Programs\Python\Python313\Scripts\cvelab.exe" --help
```

## Before the first run

```bash
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:

```bash
cvelab --output-root "$PWD/generated-labs" auto CVE-YYYY-NNNNN --ai on --key --model gpt-5.6-sol
```

On Windows:

```powershell
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:

```bash
cvelab auto CVE-YYYY-NNNNN \
  --provider openai --key --model YOUR_OPENAI_MODEL
```

Anthropic:

```bash
cvelab auto CVE-YYYY-NNNNN \
  --provider anthropic --key --model YOUR_ANTHROPIC_MODEL
```

DeepSeek:

```bash
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:

```bash
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:

```text
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:

```bash
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:

```powershell
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:

```bash
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:

```json
{
  "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:

```powershell
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.

```powershell
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:

```json
{
  "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:

```powershell
cvelab --output-root "C:\OffSec Lab\cvelab\generated-labs" run CVE-YYYY-NNNNN
```

Generate a source-level lab explicitly:

```powershell
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:

```powershell
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`:

```text
[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:

```bash
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:

```text
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:

```bash
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

```powershell
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:

```powershell
cvelab auto CVE-YYYY-NNNNN --ai on --key --model gpt-5.6-sol
```

Alternatively:

```powershell
$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:

```powershell
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:

```bash
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](ACCEPTABLE_USE.md).

To report a vulnerability in CVELab itself, follow [SECURITY.md](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](https://github.com/AndreiIonascu17/cvelab/issues/new?template=reproduction_failure.yml).
See [CONTRIBUTING.md](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](https://github.com/AndreiIonascu17/cvelab/issues/new/choose).
- Usage questions: [Discussions](https://github.com/AndreiIonascu17/cvelab/discussions), or support@syncbitsoft.com.
- Security reports: see [SECURITY.md](SECURITY.md). Never a public issue.

## License

Apache License, Version 2.0. See [LICENSE](LICENSE) and [NOTICE](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.
