depwolf
Post-process any scanner's output — Trivy, Grype, Snyk, OWASP dependency-check, Semgrep, CodeQL SARIF, or anything that emits CVE IDs — and turn it into:
- AVIP false-positive reduction — the deterministic funnel that removes
FPs (wrong OS, version outside the affected range, not in your stack,
ignored, low risk) using the local
cpe_index.dbNVD/EPSS/KEV index. - AI-based remediation — fixed version, patch commands, step-by-step plan, and an executive summary per finding (LLM narrative optional; facts stay DB-grounded).
The engine is the AVIP FP reducer extracted as a standalone, offline-first, pure-Python CLI. It does not scan anything itself — it reduces and remediates reports that already contain CVE IDs.
- Deterministic core — matching, risk, and version decisions are computed from the database; AI never invents versions or scores.
- Zero runtime dependencies — pure stdlib, Python >= 3.12.
- Typed and tested —
CVERepositoryport isolates all SQL; CI enforces ruff, mypy, and >= 80% coverage on every PR.
Pipeline
scanner output (JSON or TXT) ──> extract CVE findings ──> AVIP FP funnel ──> remediation
Trivy / Grype / Snyk / any CVE-YYYY-NNNN deterministic DB-grounded fixes
dependency-check / SAST + pkg/version context (risk >= 35) + AI summary (optional)
The FP funnel
| Step | Decision | Basis |
|---|---|---|
| Product resolution | vendor/product aliasing + fuzzy match | cpe_index.db |
| Version range | start/end inclusive/exclusive | cpe_index.db |
| OS filter | Windows/Linux-only CVEs | vendor/product heuristics |
| In-stack check | affected product/version present in your stack | findings pkg+version |
| Ignore list | persistent ignored_cves table |
depwolf ignore |
| Risk floor | risk score >= 35 to report | CVSS 0.3846 + EPSS 0.3077 + KEV 0.3077 |
| Triage | fix_now / fix_week / fix_month | risk thresholds 80 / 60 |
Risk score and every match/version decision are computed from the database — AI (when enabled) writes summaries only.
Install
pip install depwolf
From source (for development, see CONTRIBUTING.md):
python -m pip install -e ".[dev]"
Requires Python >= 3.12. One runtime dependency: PyYAML (policy files);
optional cryptography enables Ed25519-signed index manifests ([sync] extra).
Data: cpe_index.db
The FP reducer reads a local SQLite index (vendor, product, version_start/end, cve_id, description, cvss_score, cvss_severity, epss_score, kev, published_date).
- Point at an existing DB:
export AVIP_DB_PATH=/path/to/cpe_index.db - Build/refresh one from NVD + FIRST EPSS + CISA KEV:
depwolf sync(needs internet)
The DB is not shipped with the package (1.5 GB).
Usage
# Ingest a Trivy JSON scan, reduce FPs, and attach AI remediation
depwolf scan trivy.json --format table
# Any other scanner JSON (Grype, Snyk, dependency-check, CodeQL/Semgrep SARIF)
depwolf scan grype.json --format table
depwolf scan sast.sarif --format sarif > reduced.sarif
# Plain text / stdin (any tool that prints CVE IDs)
echo "CVE-2021-44228 log4j 2.14.1" | depwolf scan
depwolf scan scanner.txt --format json --save report.json
# Scan a directory of reports
depwolf scan ./reports/ --format table
# Build gate: exit 1 if any finding >= risk 60
depwolf scan trivy.json --threshold 60; echo $?
# Remediation for a specific CVE (or list of CVEs)
depwolf remediate CVE-2021-44228
# Refresh the local NVD/EPSS/KEV index
depwolf sync
# Verify index integrity (sha256 + optional Ed25519 signature)
depwolf sync --check
# Show index path, verification status, and stats
depwolf db
# Ignore / unignore a CVE (persists to ignored_cves in cpe_index.db)
depwolf ignore CVE-2021-44228
depwolf unignore CVE-2021-44228
# Re-render a saved JSON report as SARIF/table
depwolf export report.json --format sarif
# Version
depwolf --version
scan arguments: --os linux|windows, --threshold N, --format json|sarif|table,
--stack <file> (extra 'pkg version' context), --save <path>, --no-remediate.
Remediation is on by default.
Output
- JSON:
prioritized[]findings withrisk_score,severity,patch_priority,fixed_version,patch_commands,step_by_step_fix,remediation_summary, plus funnel stats (filtered_out,false_positive_rate,filtered_reasons). - SARIF 2.1.0: GitHub Code Scanning compatible (error/warning/note levels).
- Table: human-readable terminal output.
Exit codes
| Code | Meaning |
|---|---|
| 0 | clean — no findings at/above --threshold |
| 1 | findings at/above --threshold (gate fail) |
| 2 | usage/parse error |
AI remediation
Facts (fixed_version, patch commands, affected range, CVSS/EPSS/KEV) come
only from cpe_index.db. To have the executive summary drafted by an LLM,
set AVIP_OPENAI_API_KEY (and optionally AVIP_AI_MODEL). The model receives
verified facts and is instructed not to invent versions; all matching and
remediation decisions remain deterministic.
CI / DevSecOps
.github/workflows/ci.yml— enforced gate on every push/PR: ruff, ruff format, mypy, pytest with coverage (>= 80%), and a wheel/sdist build with a fresh-venv smoke test, across Python 3.12/3.13 and Ubuntu/Windows..github/workflows/sca.yml— depwolf dogfooding its own repo: runsdepwolf scan . --format sarif, uploads SARIF to GitHub Code Scanning, and fails the build when the gate trips..github/workflows/release.yml— taggingv<version>(must matchdepwolf --version) builds, attests, and publishes to PyPI with a GitHub Release and generated notes.dependabotkeeps Python + GitHub Actions dependencies current.
Input handling
- JSON: recursively walks the structure and pulls every
CVE-\d{4}-\d{4,7}value (works forVulnerabilityID,ruleId,id, references, ...), with sibling context for package / version / severity / target. - TXT: parses CVE IDs per line, optionally with a
pkg versionprefix. - Anything that contains a CVE ID works.
Project layout
depwolf/
__init__.py __version__ (single source of truth)
domain/ pure logic: versions, matching, funnel, model, ports
ports.py CVERepository protocol (typed DB boundary)
funnel.py composable Filter/Funnel chain
match.py fuzzy product/version matching
versions.py Debian-style version comparison engine
model.py canonical finding/range data types
application/ use-cases
matcher.py thin facade over the funnel (parse_stack, match_stack, ...)
filters.py the six funnel filters (invalid/not_found/os/ignored/stack/risk)
remediation.py DB-grounded fixes + optional AI narrative
ingest.py universal CVE extraction from any JSON/TXT
risk.py risk score = CVSS 0.3846 + EPSS 0.3077 + KEV 0.3077
infrastructure/ sqlite store (SqliteIndexStore), DB seeding, sync
interfaces/ CLI entry point, JSON/SARIF/table serialization
tests/ pytest suite (LOG4J_ROWS fixture data in conftest.py)
Security & reporting
See SECURITY.md for responsible disclosure. Do not file public issues for vulnerabilities.
Changelog
See CHANGELOG.md (Keep a Changelog, SemVer).
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file depwolf-0.1.0.tar.gz.
File metadata
- Download URL: depwolf-0.1.0.tar.gz
- Upload date:
- Size: 60.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aee81c185c27c087d3c1fe03e6ddf28495bb9fcc6934cbdf84390a01bb7fee2e
|
|
| MD5 |
44beac9f3db6eee41cefaa0d6f935338
|
|
| BLAKE2b-256 |
4f1bd11d2414c60b0fab7d5c2b74d416dbeeeac330c3373462345fe587f868a5
|
Provenance
The following attestation bundles were made for depwolf-0.1.0.tar.gz:
Publisher:
release.yml on depwolf/depwolf
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
depwolf-0.1.0.tar.gz -
Subject digest:
aee81c185c27c087d3c1fe03e6ddf28495bb9fcc6934cbdf84390a01bb7fee2e - Sigstore transparency entry: 2419374594
- Sigstore integration time:
-
Permalink:
depwolf/depwolf@5324720422e0c167f5be40854380e2b9bdd946b8 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/depwolf
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5324720422e0c167f5be40854380e2b9bdd946b8 -
Trigger Event:
push
-
Statement type:
File details
Details for the file depwolf-0.1.0-py3-none-any.whl.
File metadata
- Download URL: depwolf-0.1.0-py3-none-any.whl
- Upload date:
- Size: 58.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b5198d2e3208797fa22d81fa88834ad5aec381426c1a426255149314af992843
|
|
| MD5 |
b581c33560138aae5735fc7e4b72e29b
|
|
| BLAKE2b-256 |
5b35cbdf73d3fee608c25603a20a3171e7f1ed6825f9b5848b28d485a69d7113
|
Provenance
The following attestation bundles were made for depwolf-0.1.0-py3-none-any.whl:
Publisher:
release.yml on depwolf/depwolf
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
depwolf-0.1.0-py3-none-any.whl -
Subject digest:
b5198d2e3208797fa22d81fa88834ad5aec381426c1a426255149314af992843 - Sigstore transparency entry: 2419374752
- Sigstore integration time:
-
Permalink:
depwolf/depwolf@5324720422e0c167f5be40854380e2b9bdd946b8 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/depwolf
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5324720422e0c167f5be40854380e2b9bdd946b8 -
Trigger Event:
push
-
Statement type: