cve-source-check · diff
git:20260705.380563c to git:20260710.613e243
6 added, 7 removed. Audit A to A.
---
name: cve-source-check
promoted_to: service-health-check
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: true
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:
- service-health-check
---
# CVE Source Check
Audits CVE/vulnerability source coverage for a technology stack. Given an inventory
of components and (optionally) the feeds you currently monitor, it maps each
component to authoritative CVE sources, flags gaps, and emits audit-ready reports.
## Scope
| In scope | Out of scope |
|---|---|
| Mapping components → authoritative feeds via a versioned registry | Running vulnerability scanners (Trivy/Snyk/etc.) |
| Reporting coverage and gaps in JSON + Markdown | Fetching CVE content or ranking by severity |
| Optional HEAD-check for source URL reachability | Integrating with private/commercial vuln databases |
| Audit-ready output (deterministic, reproducible) | Live LLM research per run |
## Inputs
| Flag | Purpose |
|---|---|
| `--inventory <file>` | JSON inventory: `[{name, version?, type?}, ...]` or `{components: [...]}`. |
| `--inline "name@ver,name,..."` | Quick comma-separated list. Mutually exclusive with `--inventory`. |
| `--current-sources <file>` | Optional. One URL per line. Blank lines and `#` comments skipped. |
| `--service <name>` | Free-form name used in 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 inventory format only. YAML is not supported — stdlib does not ship a YAML parser.
## Outputs
| File | Format |
|---|---|
| `cve-source-report-{service}-{YYYYMMDD}.md` | Human-readable audit report. |
| `cve-source-report-{service}-{YYYYMMDD}.json` | Machine-readable per `references/output-formats.md`. |
| Exit code | Meaning |
|---|---|
| 0 | Full coverage. |
| 1 | Gaps exist (unmapped components or unmonitored sources). |
| 2 | At least one source URL is unreachable (only with `--check-urls`). |
| 3 | Input error (missing/malformed registry or inventory). |
## Workflow
### Phase 1: LOAD
1. Locate the registry: `tech-source-registry.json` next to this SKILL.md by default.
2. Build an inventory:
- From `--inventory`: parse JSON; accept either a list or `{components: [...]}`.
- From `--inline`: split on commas, parse `name@version` pairs.
3. If `--current-sources` is provided, read URLs (one per line); normalize for
case-insensitive comparison.
**Gate**: at least one inventory component is present. Empty inventory → exit 3.
### Phase 2: MAP & VERIFY
1. For each component, look up `name` (and aliases) in the registry.
- Found → status `mapped`, attach the registry's source list.
- Missing → status `unmapped`, sources `[]`.
2. If current sources were loaded, mark each source `monitored: true` when its
normalized URL appears in the set.
3. If `--check-urls` is set, HEAD-check every unique source URL. Treat
200/301/302/403/405 as reachable; record definite failures and network errors
distinctly. See `references/source-verification.md`.
**Gate**: every component has a status; every source has `monitored` and
`reachable` fields populated (`reachable: null` when checks are skipped).
### Phase 3: REPORT
1. Compute the summary: components, mapped/unmapped, monitored, coverage %,
gaps, unreachable.
2. Write the JSON report.
3. Write the Markdown report:
- Summary table.
- Components table with ✅ / ⚠️ / ❌ markers.
- **Gaps** section listing primary then secondary sources to add (only when
gaps exist).
- **Unmapped** section listing registry-extension TODOs (only when unmapped
components exist).
4. Print a one-screen summary to stdout including report paths.
5. Set the exit code per the table above.
**Gate**: both files exist on disk and the summary printed; exit code reflects
the audit result.
## Quick start
```bash
# Inline, offline, no monitoring data
python3 scripts/check-cve-sources.py \
--inline "go@1.22,alpine@3.19,postgres@16,redis@7,nginx@1.25" \
--service my-service
# Inventory file + current monitored feeds
python3 scripts/check-cve-sources.py \
--inventory examples/inventory.example.json \
--current-sources examples/current-sources.example.txt \
--service my-service
# Same, with 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
```
## Extending the registry
To add a technology, edit `tech-source-registry.json`. Each entry needs `name`,
`aliases`, `type`, and 1–3 `sources`. Schema lives at
`references/registry-schema.md`.
- ## Reference files
+ ## Reference Loading Table
- - `references/registry-schema.md` — registry shape, allowed `kind`/`priority`,
- and how to add entries.
- - `references/source-verification.md` — HEAD-check semantics and graceful
- degradation rules.
- - `references/output-formats.md` — JSON schema, Markdown sections, and exit-code
- table.
+ | Signal | Load These Files | Why |
+ |---|---|---|
+ | adding a technology to the registry | `registry-schema.md` | Defines registry shape and allowed values. |
+ | checking source URLs | `source-verification.md` | Defines HEAD-check semantics and graceful degradation. |
+ | generating audit reports | `output-formats.md` | Defines JSON and Markdown report contracts. |
## Error handling
### "ERROR: failed to load registry"
Cause: registry file missing or malformed JSON.
Solution: confirm `tech-source-registry.json` is at `--registry` (or default
location) and parses with `python3 -m json.tool`.
### "ERROR: failed to load inventory"
Cause: inventory file missing, malformed JSON, or unexpected shape.
Solution: validate with `python3 -m json.tool`. Inventory must be a list or an
object with a `components` key.
### "ERROR: inventory is empty"
Cause: no usable components after parsing.
Solution: confirm each entry has a `name`. Inline form requires non-empty tokens.
### Coverage stuck at 0%
Cause: `--current-sources` URLs do not match registry URLs exactly (e.g., extra
path segments, trailing slashes).
Solution: copy URLs directly from the registry. The script normalizes scheme/host
case and trailing slash; everything else must match.
### `--check-urls` flags many `[—]` entries
Cause: network issues (proxy, DNS, offline) — recorded as `reachable: null`.
Solution: re-run without `--check-urls` for the audit; investigate network
separately. Network errors do not affect the gap exit code.