cve-coder
Agentic CVE triage pipeline: detect → patch → verify.
Given a CVE identifier, a coding agent (Claude) reads the vulnerable checkout, judges whether the vulnerability is present, applies a fix, and writes a regression test that fails on the buggy commit and passes after the fix — all without CodeQL, ChromaDB, or any language server.
Quick start
# From PyPI (once published)
pip install cve-coder
cp .env.example .env # fill in ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN
cvecoder -h
# From source
git clone https://github.com/digital-duck/cve-coder
cd cve-coder
python3 -m venv .venv && source .venv/bin/activate
pip install -e .
cp .env.example .env
cvecoder -h
Run a CVE
# Full pipeline (spec + detect + patch + verify)
cvecoder pipeline --cve-id CVE-2025-66455 --agent claude_cli --model sonnet-5
# With feedback loop (up to 3 patch→verify rounds)
cvecoder pipeline --cve-id CVE-2025-66455 --agent claude_cli --model sonnet-5 --max-iters 3
# Individual stages
cvecoder spec --cve-id CVE-2025-66455
cvecoder detect --in output/triage/CVE-2025-66455/cve-1-metadata.yaml --agent claude_cli
cvecoder patch --in output/triage/CVE-2025-66455/cve-2-findings.yaml --agent claude_cli
cvecoder verify --in output/triage/CVE-2025-66455/cve-3-fixes.yaml --agent claude_cli
# CVE not in the bundled CSV — supply repo/commit directly
cvecoder pipeline --cve-id CVE-XXXX-XXXXX \
--github-url https://github.com/owner/repo --commit <sha> \
--agent claude_cli --model sonnet-5
Output
output/triage/<CVE-ID>/
├── cve-1-metadata.yaml # NVD description, CWE, CVSS, repo/commit
├── cve-2-findings.yaml # agent verdict + file/line evidence
├── cve-3-fixes.yaml # fix strategy + git diff
├── cve-4-tests.yaml # regression test + PASS/FAIL on both checkouts
└── cve-5-pipeline.yaml # per-stage summary + overall_status
overall_status |
Meaning |
|---|---|
EFFECTIVE |
Confirmed, patched, regression test distinguishes both checkouts |
FIX_FAILED |
Test passed on both — patch didn't hold |
INCONCLUSIVE |
Test ran but didn't distinguish the two checkouts |
NO_TESTS |
Verify stage couldn't extract a runnable test |
SKIPPED_NOT_VULNERABLE |
Detect judged the CVE not present |
Adding CVEs
Edit data/project_info-py.csv (Python), data/project_info-js.csv (JS),
or data/project_info.csv (Java) with the CVE's GitHub repo, buggy commit,
and fix commit. Then run cvecoder spec --cve-id <CVE-ID> to clone and
check out the repo.
Model aliases
| Alias | Model ID |
|---|---|
sonnet-5 |
claude-sonnet-5 |
sonnet-4.5 |
claude-sonnet-4-5-20250929 |
sonnet-4 |
claude-sonnet-4-20250514 |
Architecture
cve_coder/
├── cve_coder.py # Click CLI entry point (spec/detect/patch/verify/pipeline)
├── cve_spec.py # Stage 0: NVD fetch + repo checkout
├── cve_detect.py # Stage 1: agent reads code, judges vulnerability
├── cve_patch.py # Stage 2: agent fixes the code
├── cve_verify.py # Stage 3: agent writes + runs regression test
├── triage_common.py # Shared helpers (agent invocation, YAML I/O, skills)
├── nvd_client.py # NVD API fetch + parse (no ChromaDB)
└── get_cve_repos.py # Clone repo at buggy commit (used by spec stage)
skills/detect/
├── common/SKILL.md # Detect-stage skill loaded for all languages
└── python/SKILL.md # Python-specific detect skill
data/
├── project_info.csv # Java CVEs (GitHub repo + commit info)
├── project_info-py.csv # Python CVEs
└── project_info-js.csv # JavaScript CVEs
No CodeQL, no ChromaDB, no language server required.
Metadata
Release files for cve-coder 0.1.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 | Provenance | |
|---|---|---|---|---|
| cve_coder-0.1.0.tar.gz | 141.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cve_coder-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 295.4 kB
Release files / cve_coder-0.1.0.tar.gz
| Download URL | cve_coder-0.1.0.tar.gz |
|---|---|
| Size | 141.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
45f63aff00af463b7ca548ad8a9e475fe0a1dd74b7efb27a3bdadfe777858c3b
|
|
BLAKE2b-256 checksum How to use checksums |
ff08ae2bf5fa1c66b952fa30887798200269162f8a99463de0150231ee698433
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.15
|
Release files / cve_coder-0.1.0-py3-none-any.whl
| Download URL | cve_coder-0.1.0-py3-none-any.whl |
|---|---|
| Size | 153.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
48e14fe623bbd0a7dbd6538de3ed85cea3aa7be12781f539c603cb5c72ef54c4
|
|
BLAKE2b-256 checksum How to use checksums |
141bd04372aa6c2496af73efe104749b69971d33744d772ea5e26caf3d31f4fc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.15
|
Security for cve-coder 0.1.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.