Query MITRE, OSV.dev, and Go vulnerability database to produce a structured report of affected packages, ecosystems, and vulnerable version ranges for a CVE.
Scanned 9/22/2026
Install to Claude Code
npx -y skills add NVlabs/Skill2Env --skill cve-recon --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Cve Recon?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/nvlabs-cve-recon)More formats (shields.io, HTML) on the badges page.
---
name: cve-recon
description: Query MITRE, OSV.dev, and Go vulnerability database to produce a structured report of affected packages, ecosystems, and vulnerable version ranges for a CVE.
license: Apache-2.0
user_invocable: true
model: inherit
color: cyan
---
# CVE Reconnaissance
## When to Use This Skill
Use this skill when the user asks you to look up, describe, explain, or get details about a specific CVE — its affected packages, ecosystem, version ranges, or severity. Input is a CVE ID taken from conversation context.
## Optional Output Flags
The user may specify an optional output format flag:
- `--format markdown` — (default) Markdown report
- `--format json` — machine-readable JSON object
- `--format csv` — single-row CSV with a header row
Record the resolved value as `OUTPUT_FORMAT` (default: `markdown`).
## Input Validation
Confirm you have a CVE ID in the format `CVE-YYYY-NNNNN` (e.g., CVE-2023-38039).
If the CVE ID is missing or does not match the format, ask the user to provide it. Do not proceed.
## Prerequisites
**Resolve scripts directory** — the helper scripts are at `../scripts/` relative to this project's root:
```bash
SCRIPTS_DIR="$(git rev-parse --show-toplevel)/ocp-admin/scripts/security-validation"
test -f "$SCRIPTS_DIR/fetch_cve_metadata.py" || { echo "Error: Scripts directory not found at $SCRIPTS_DIR"; exit 1; }
```
## Workflow
Do not hallucinate data — rely strictly on script outputs. If a script produces an unexpected error, report it verbatim and stop.
### Steps 1-3 — Fetch CVE Metadata (single script call)
Run the `fetch_cve_metadata.py` script to query all sources in one call:
```bash
python $SCRIPTS_DIR/fetch_cve_metadata.py [CVE-ID]
```
The script automatically queries MITRE CVE API, OSV.dev, and (if a GO-* alias is found) the Go vulnerability database. It returns merged JSON with:
- `cve_id` — the CVE identifier
- `description` — English CVE description from MITRE
- `affected[]` — all affected packages, each with:
- `ecosystem` — Go, PyPI, npm, rpm, etc.
- `package` — package/module name
- `versions` — object with `introduced` and/or `fixed` boundaries
- `source` — which database provided this entry (mitre, osv, go_vuln_db)
- `vendor` — vendor name (from MITRE entries)
- `go_id` — Go vulnerability ID (from go_vuln_db entries only)
- `aliases[]` — cross-references (GO-*, GHSA-*, etc.)
- `errors[]` — any API failures (non-fatal; the script continues with available data)
**Error handling:**
- If `affected` is empty and `errors` contains "not found (404)": stop and report "CVE not found"
- If `affected` is empty but no 404 error: report "No affected package data available"
- If some sources failed but others succeeded: proceed with available data, note the errors
### Step 4 — Produce output
Always produce a report. Use `N/A` for any field that could not be determined.
**If `OUTPUT_FORMAT` is `markdown`:**
```markdown
## CVE Reconnaissance Report
- **CVE ID:** [CVE-ID]
- **Description:** [English description from MITRE cna.descriptions; supplemented by OSV summary if MITRE description is sparse]
### Data Sources
| Source | Status | Record ID |
|---|---|---|
| MITRE CVE | [Fetched \| Error] | [CVE-ID] |
| OSV.dev | [Fetched \| Not found \| Error] | [OSV record ID or N/A] |
| Go vuln DB | [Fetched \| Not applicable \| Not found] | [GO-YYYY-NNNN or N/A] |
**Cross-references (from OSV aliases):** [comma-separated list of aliases: GO-YYYY-NNNN, GHSA-*, etc. | None found]
### Affected Packages
[For each affected entry — merged from MITRE and OSV, deduplicated by package name + ecosystem:]
#### [vendor] / [product]
| Field | Value |
|---|---|
| Package name | [packageName] |
| Ecosystem | [Go \| RPM \| PyPI \| npm \| Rust \| PHP \| Maven \| NuGet \| Unknown] |
| Collection URL | [collectionURL or N/A] |
| Source(s) | [MITRE \| OSV.dev \| MITRE + OSV.dev] |
**Vulnerable version ranges (MITRE):**
| Version | Status | Upper bound | Bound type | Version type |
|---|---|---|---|---|
| [version] | [affected\|unaffected] | [lessThan / lessThanOrEqual value or —] | [< \| <=] | [semver\|rpm\|custom] |
Default status for unlisted versions: [defaultStatus]
[If OSV provided version ranges for this package:]
**Vulnerable version ranges (OSV.dev):**
| Introduced | Fixed |
|---|---|
| [version or "0"] | [version or "not yet fixed"] |
[If version ranges differ between MITRE and OSV: "Note: MITRE and OSV.dev report different version boundaries for this package. The union of both ranges is treated as the vulnerable range."]
[If Go vuln DB entry was found (GO-* alias detected in OSV):]
**Go vulnerability database enrichment:**
- **Go vuln ID:** [GO-YYYY-NNNN]
- **Authoritative module path:** [affected[].package.name]
- **Vulnerable ranges (Go vuln DB):**
| Introduced | Fixed |
|---|---|
| [version or "0"] | [version or "not yet fixed"] |
- **Affected packages within module:**
[List from ecosystem_specific.imports[].path, or N/A if absent]
- **Affected symbols:**
[List from ecosystem_specific.imports[].symbols[], or "All exported symbols" if absent]
- **Go vuln DB last modified:** [modified timestamp]
### CVSS
| Source | Version | Score | Severity |
|---|---|---|---|
| MITRE | [3.1 \| 3.0] | [baseScore] | [baseSeverity] |
| OSV.dev | [version or —] | [score or —] | [severity or —] |
[If scores differ: "Note: MITRE and OSV.dev report different CVSS scores. The higher score ([X]) is highlighted."]
[If no CVSS data from either source: "No CVSS data available from MITRE or OSV.dev."]
### References
[Numbered list of deduplicated URLs from both MITRE cna.references[].url and OSV references[].url, with source noted in parentheses: (MITRE), (OSV), or (both)]
```
**Missing values rule — applies to both JSON and CSV:**
- **JSON:** when a value is not available, not applicable, or unknown, use an empty string `""` — never use `null`.
- **CSV:** when a value is not available, not applicable, or unknown, leave the field empty — never write the literal word `null`.
**If `OUTPUT_FORMAT` is `json`:**
```json
{
"cve_id": "[CVE-ID]",
"description": "[English description]",
"sources": {
"mitre": {"status": "fetched | error", "record_id": "[CVE-ID]"},
"osv": {"status": "fetched | not_found | error", "record_id": "[OSV ID or empty string]", "aliases": ["GO-YYYY-NNNN", "GHSA-*"]},
"go_vuln_db": {"status": "fetched | not_applicable | not_found", "record_id": "GO-YYYY-NNNN | empty"}
},
"cvss": {
"mitre": {"version": "3.1 | 3.0 | empty", "score": 7.5, "severity": "High | empty"},
"osv": {"version": "3.1 | 3.0 | empty", "score": 7.5, "severity": "High | empty"}
},
"affected": [
{
"vendor": "[vendor]",
"product": "[product]",
"package_name": "[packageName]",
"ecosystem": "Go | RPM | PyPI | npm | Rust | PHP | Maven | NuGet | Unknown",
"collection_url": "[url or empty string]",
"source": "mitre | osv | both",
"default_status": "affected | unaffected",
"versions_mitre": [
{
"version": "[version]",
"status": "affected | unaffected",
"less_than": "[version or empty string]",
"less_than_or_equal": "[version or empty string]",
"version_type": "semver | rpm | custom"
}
],
"versions_osv": [
{"introduced": "[ver]", "fixed": "[ver or empty string]"}
],
"go_enrichment": {
"go_vuln_id": "GO-YYYY-NNNN | empty",
"module_path": "[authoritative module path or empty string]",
"ranges": [{"introduced": "[ver]", "fixed": "[ver or empty string]"}],
"affected_packages": ["[pkg/path]"],
"affected_symbols": ["[Symbol]"],
"last_modified": "[timestamp or empty string]"
}
}
],
"references": [
{"url": "[url]", "source": "mitre | osv | both"}
]
}
```
**If `OUTPUT_FORMAT` is `csv`:**
One header row followed by one data row per affected package entry:
```
cve_id,description,cvss_score_mitre,cvss_severity_mitre,cvss_score_osv,cvss_severity_osv,vendor,product,package_name,ecosystem,collection_url,source,vulnerable_versions_mitre,vulnerable_versions_osv,go_vuln_id,go_module_path,go_fixed_versions,osv_aliases
[values — version ranges as semicolon-separated strings; description truncated to 200 chars; osv_aliases as space-separated list]
```
## Dependencies
### Required MCP Servers
- None — this skill uses a bundled Python script, not MCP tools
### Required Helper Scripts
- `fetch_cve_metadata` — queries MITRE CVE API, OSV.dev, and Go vuln DB in a single call
### Related Skills
- `container-cve-validator` — full CVE validation pipeline (uses this as Step 1)
- `coreos-cve-validator` — CoreOS CVE validation (uses this as Step 2)
### Reference Documentation
- [MITRE CVE API](https://cveawg.mitre.org/api/cve/)
- [OSV.dev API](https://api.osv.dev/v1/vulns/)
- [Go Vulnerability Database](https://vuln.go.dev/)
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!