Metadata-Version: 2.4
Name: cve-triage-agent
Version: 0.1.0
Summary: Agentic CVE triage CLI: scan a software stack and produce a prioritised PDF risk briefing using NVD, OSV, EPSS, CISA KEV, and Exploit-DB.
Author-email: Saieesh Rao <raosaieesh@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/ssr-ey/CVE-triage-Agent
Project-URL: Repository, https://github.com/ssr-ey/CVE-triage-Agent
Project-URL: Issues, https://github.com/ssr-ey/CVE-triage-Agent/issues
Keywords: cve,vulnerability,security,triage,agent,openai,nvd,osv,epss,kev
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: openai>=1.40.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: rich>=13.0.0
Requires-Dist: reportlab>=4.0.0
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == "dev"
Requires-Dist: twine>=5.0; extra == "dev"
Dynamic: license-file

# CVE Triage & Risk Briefing Agent

An agentic Python CLI that takes a software stack (`stack.json`), autonomously
enriches each package's known CVEs from public threat-intel sources, scores
them by *actual exploitability* (not just CVSS), and produces a professional
PDF risk briefing ready for a CTO/CISO.

The agent uses an OpenAI model (default `gpt-4o`) as the orchestrator — it
decides which tools to call, in what order, and when it has enough data to
write the final report. The Python side just runs the tools and feeds
results back.

## Data sources

- **NIST NVD** — authoritative CVE catalogue
- **OSV.dev** — best coverage for npm, PyPI, Go, Maven, RubyGems
- **FIRST EPSS** — probability of exploitation in the wild (next 30 days)
- **CISA KEV** — vulnerabilities confirmed exploited in the wild
- **CIRCL CVE / Exploit-DB** — public exploit references

## Install

```bash
pip install cve-triage-agent
```

Then create a `.env` file (or export the variables in your shell):

```
OPENAI_API_KEY=sk-...
NVD_API_KEY=                # optional — recommended for higher rate limits
OPENAI_MODEL=gpt-4o         # optional — override the default model
```

Get a free NVD API key at <https://nvd.nist.gov/developers/request-an-api-key>.

## Usage

```bash
cve-triage --stack stack.json
# → writes report.pdf
```

```bash
cve-triage --stack stack.json --output briefing.pdf
cve-triage --stack stack.json --format markdown --output briefing.md
cve-triage --stack stack.json --format json --output findings.json
cve-triage --stack stack.json --min-cvss 7.0    # drop low-severity noise
```

You can also invoke without installing the console script:

```bash
python -m cve_triage --stack stack.json
```

### Options

| Flag | Default | Description |
|------|---------|-------------|
| `--stack` | _required_ | Path to the input stack JSON file |
| `--output` | `report.pdf` (or `.md` / `.json` to match `--format`) | Output path |
| `--format` | `pdf` | `pdf`, `markdown`, or `json` |
| `--min-cvss` | `0.0` | Drop findings below this CVSS base score |
| `-v`, `--verbose` | off | Debug logging in `agent_run.log` |
| `--version` | — | Print version and exit |

### Input format (`stack.json`)

```json
[
  { "name": "django",  "version": "4.2.3",   "ecosystem": "PyPI" },
  { "name": "express", "version": "4.18.2",  "ecosystem": "npm"  },
  { "name": "openssl", "version": "3.0.7",   "ecosystem": "other" }
]
```

Supported ecosystems: `PyPI`, `npm`, `Maven`, `Go`, `RubyGems`, `NuGet`,
`other`. Use `other` for system packages like nginx or openssl that OSV's
ecosystem indices don't cover — NVD will still be queried, plus an
ecosystem-agnostic OSV fallback.

A worked example lives at `examples/stack.json`.

## Risk scoring

The composite risk score (0–100) weights:

- CVSS base severity — 40%
- EPSS exploitation probability — 35%
- CISA KEV listing — +20
- Public exploit available — +10
- Known ransomware association — +5

Tiers: **CRITICAL** ≥ 75 · **HIGH** ≥ 50 · **MEDIUM** ≥ 25 · **LOW** < 25.

CVSS floor rules guarantee that a CVE with CVSS ≥ 9.5 is always CRITICAL,
≥ 9.0 is always at least CRITICAL, and ≥ 7.0 is always at least HIGH —
exploitability signals can promote a tier but never demote one.

A CVE listed in CISA KEV with CVSS 7.5 will outrank a CVSS 9.8 with EPSS 0.001,
which is what you want.

## Output

A PDF briefing with:

- Title block + scan metadata + tier counts
- Executive summary (150–250 words, plain prose, generated by the LLM **after** scoring so it can never contradict the tables)
- Packages-scanned table (every input package, even clean ones)
- Critical/High findings table (tier-color coded)
- Per-finding detail blocks with description, why-urgent rationale, remediation, references
- Medium/Low findings table
- Methodology + data-source list

Use `--format markdown` for a plain-text version (handy for diffing) or
`--format json` for downstream tooling.

## Architecture

```
cve-triage-agent/
├── cve_triage/
│   ├── cli.py              CLI entry point (argparse → run_agent)
│   ├── loop.py             Two-pass agent: collect → score → summarise
│   ├── tools.py            NVD / OSV / EPSS / KEV / Exploit-DB integrations
│   ├── scorer.py           Composite risk score + CVSS floor rules
│   ├── reporter.py         Markdown + JSON renderers
│   └── pdf_reporter.py     reportlab Platypus PDF renderer
├── examples/
│   └── stack.json
├── pyproject.toml
└── LICENSE
```

The agent runs a two-pass loop:

1. **Pass 1** — tool-using loop where the model collects + enriches findings
   and emits a single `findings_json` block (no prose, no headers).
2. The Python side scores every finding and applies CVSS floor rules.
3. **Pass 2** — non-tool call where the model writes the executive summary,
   anchored to the *scored* findings (so the prose can never reference tiers
   that don't exist).

Tool-call traces and HTTP retry warnings land in `agent_run.log`.

## Building and publishing

```bash
pip install -e ".[dev]"           # editable install with build/twine
python -m build                    # produces dist/*.whl and dist/*.tar.gz
python -m twine upload dist/*      # publish to PyPI
```

Update author and URL fields in `pyproject.toml` before your first publish.

## License

MIT — see [LICENSE](LICENSE).
