cve-source-check · git:20260919.28d30f9 · 2026-09-19 · sha256 2ff4a8e9a2d2923f
cve-source-check git:20260919.28d30f9A
Immutable. This exact content is served forever at /api/v1/blob/2ff4a8e9a2d2923f.
---
name: cve-source-check
promoted_to: deploy
description: "Audit CVE/vulnerability source coverage for a technology stack. Maps each component (container, library, base image, runtime) to authoritative CVE feeds, flags gaps, and produces audit-ready reports. Generic: works for any service or stack."
user-invocable: false
argument-hint: "[--inventory <file>] [--inline <tech-list>] [--current-sources <file>] [--service <name>] [--check-urls]"
allowed-tools:
- Bash
- Read
- Write
- Edit
- Glob
- Grep
routing:
triggers:
- "check cve sources"
- "cve source coverage"
- "audit cve feeds"
- "vulnerability source audit"
- "verify cve sources"
- "security feed audit"
category: infrastructure
complexity: Simple
pairs_with:
- assessment
---
# CVE Source Check
Audit CVE/vulnerability source coverage for a technology stack. Maps components
to authoritative CVE feeds via a versioned registry, flags gaps, and produces
audit-ready reports (JSON + Markdown).
**In scope**: component-to-feed mapping, coverage/gap reporting, optional URL
reachability checks. **Out of scope**: running scanners (Trivy/Snyk), fetching
CVE content, private vuln databases.
## Quick Start
```bash
# Inline, offline
python3 scripts/check-cve-sources.py \
--inline "go@1.22,alpine@3.19,postgres@16,redis@7,nginx@1.25" \
--service my-service
# Inventory + monitored feeds + link verification
python3 scripts/check-cve-sources.py \
--inventory examples/inventory.example.json \
--current-sources examples/current-sources.example.txt \
--service my-service --check-urls
```
## Inputs
| Flag | Purpose |
|---|---|
| `--inventory <file>` | JSON: `[{name, version?, type?}, ...]` or `{components: [...]}`. |
| `--inline "name@ver,..."` | Comma-separated list. Mutually exclusive with `--inventory`. |
| `--current-sources <file>` | One URL per line. `#` comments and blank lines skipped. |
| `--service <name>` | Name for report header and filenames. |
| `--check-urls` | HEAD-check every source URL (5s timeout, graceful degradation). |
| `--registry <path>` | Override default `tech-source-registry.json`. |
| `--out-dir <path>` | Output directory (default: cwd). |
JSON only. YAML not supported (no stdlib parser).
## Outputs
Files: `cve-source-report-{service}-{YYYYMMDD}.{md,json}` in `--out-dir`.
| Exit | Meaning |
|---|---|
| 0 | Full coverage. |
| 1 | Gaps (unmapped components or unmonitored sources). |
| 2 | Unreachable source URL (only with `--check-urls`). |
| 3 | Input error (missing/malformed registry or inventory). |
## Workflow
### Phase 1: LOAD
1. Locate `tech-source-registry.json` (next to SKILL.md by default, or `--registry`).
2. Build inventory from `--inventory` (JSON list or `{components: [...]}`) or `--inline` (comma-split `name@version`).
3. If `--current-sources` provided, read URLs and normalize for case-insensitive comparison.
**Gate**: at least one component present. Empty inventory -> exit 3.
### Phase 2: MAP & VERIFY
1. Look up each component `name` (and aliases) in the registry.
- Found -> `mapped`, attach source list. Missing -> `unmapped`, sources `[]`.
2. If current sources loaded, mark each source `monitored: true` when its normalized URL appears.
3. If `--check-urls`: HEAD-check each unique URL. Treat 200/301/302/403/405 as reachable. 4xx (except 403/405) and 5xx -> `reachable: false`. Timeout/DNS/TLS failure -> `reachable: null` (WARN, does not affect exit code). 5s timeout per URL, cached per run.
**Gate**: every component has status; every source has `monitored` and `reachable` fields.
### Phase 3: REPORT
1. Compute summary: components, mapped/unmapped, monitored, coverage %, gaps, unreachable.
2. Write JSON report with per-component status and per-source `monitored`/`reachable` fields.
3. Write Markdown report: summary table, components table (markers), gaps section (when gaps exist), unmapped section (when unmapped exist).
4. Print one-screen summary to stdout. Set exit code per table above.
**Gate**: both files written, summary printed.
## Registry Schema
`tech-source-registry.json` shape:
```json
{
"$schema_version": "1.0",
"kinds": ["advisory-list", "github-security", "mailing-list", "distro-tracker", "vendor-page", "mitre"],
"priorities": ["primary", "secondary"],
"technologies": [
{"name": "postgres", "aliases": ["postgresql","pg"], "type": "container",
"sources": [{"url": "https://...", "kind": "advisory-list", "priority": "primary"}]}
]
}
```
Each technology: `name` (lowercase, unique), `aliases` (list), `type` (`runtime`/`base-image`/`container`/`library`), `sources` (1-3, at least one `primary`).
To add a technology: pick canonical name, list aliases, add 1-3 sources (lead with vendor advisory page), re-run against a sample inventory.
## Error Handling
| Error | Cause | Fix |
|---|---|---|
| Failed to load registry | Missing or malformed JSON | Validate with `python3 -m json.tool` |
| Failed to load inventory | Missing, malformed, or wrong shape | Validate JSON; must be list or `{components: [...]}` |
| Inventory empty | No usable components | Each entry needs `name`. Inline needs non-empty tokens. |
| Coverage stuck at 0% | `--current-sources` URLs don't match registry | Copy URLs from registry. Scheme/host case and trailing slash are normalized; rest must match. |
| Many `[--]` entries with `--check-urls` | Network issues | Re-run without `--check-urls`. Network errors don't affect gap exit code. |