Files
cc-ci-orchestrator/.claude/skills/cve-check-and-upgrade/SKILL.md
T
autonomic-bot b0bdce2c15 add /cve-check and /cve-check-and-upgrade
/cve-check answers 'what are we exposed to that an upgrade would fix?' without
running an upgrade: per-recipe, resolve the available window for EVERY image
(sidecars included), run the advisory scan over it, adjudicate whatever pass 1
could not decide, publish a report. Read-only — no PRs, no CI, no merges.

/cve-check-and-upgrade does that sweep, then runs /recipe-upgrade only on the
recipes whose upgrade actually closes a CVE, worst severity first, and reports
on both. --min-severity high for just the urgent ones; --dry-run prints the
queue and stops. Never merges.

Deliberate choices, each written into the skills:
- externals are SWEPT but never upgraded here — a security sweep that skipped
  deployed software would misreport exposure, but we don't maintain them.
- an unknown count never justifies an upgrade AND is never treated as clean;
  it goes to the Addendum.
- no upgrade available means 0 CVEs, not '?'.
- subagents are told which CVEs justify their upgrade, so the PR says why it
  exists — a PR naming the RCE it closes gets reviewed sooner.

recipe-report.py grows a page kind: 'cve' files as cve-DATE.html so a sweep
can't overwrite a weekly edition, while BOTH appear in the same archive index,
suffixed 'full report' / 'CVE check'.

/help and /cc-ci-status updated to route to them.
2026-08-11 04:04:59 +00:00

6.0 KiB
Raw Blame History

name, description
name description
cve-check-and-upgrade Security-driven upgrade run. Does a full /cve-check sweep first (per-image advisory scan of every recipe's available upgrade, with adjudication), then runs /recipe-upgrade ONLY on the recipes whose upgrade fixes at least one CVE — worst severity first — opening a verified recipe PR for each, and finally publishes one report covering both the sweep and the PRs. Recipes with no CVEs are left alone; that is the point. NEVER merges. Invoke as /cve-check-and-upgrade [recipe ...] [--min-severity high] [--capacity N] [--dry-run].

cve-check-and-upgrade

/upgrade-all upgrades everything that has an upgrade. This upgrades what has a reason. It runs the /cve-check sweep, then spends CI time only on the recipes where an upgrade actually closes a vulnerability, handling the worst first.

Use it when you want to act on security rather than churn the whole fleet: after a vendor announcement, when CI capacity is short, or between weekly runs. When you only want to know, use /cve-check. When you want everything current regardless of CVEs, use /upgrade-all.

Creates PRs. Never merges. Every PR is verified green on cc-ci and left for a human.

Arguments

  • <recipe> … — restrict the whole run to these recipes.
  • --min-severity critical|high|medium|low — only upgrade recipes whose fixed CVEs reach this severity. Default low (any CVE at all justifies the upgrade). --min-severity high is the useful "just the urgent ones" setting.
  • --capacity N — subagent pool size; defaults to the live DRONE_RUNNER_CAPACITY (the drone runner's slots), matching /upgrade-all's rolling-pool behaviour.
  • --dry-run — do the whole sweep and print exactly which recipes would be upgraded and why, then stop without spawning a single upgrade. Publishes no report and opens no PR.

Procedure

1. Sweep — run /cve-check in full

Follow .claude/skills/cve-check/SKILL.md steps 1–5 exactly: candidate list, per-image upgrade windows, the advisory scan per recipe, pass-2 adjudication of anything undecided, and the severity classification. Do not publish its report — this run produces one combined report at the end instead.

Keep, per recipe: the windows scanned, the CVE count, the CVE ids with severities, and whether the count is a floor (undetermined advisories remain) or unknown.

2. Decide what to upgrade

RECIPES_TO_UPGRADE = recipes where the scan found ≥1 CVE at or above --min-severity.

Deliberate exclusions, each recorded in the report with its reason:

  • 0 CVEs — an upgrade may exist, but nothing security-relevant. Left alone; that is the point of this skill. /upgrade-all is what sweeps those up.
  • external tier — swept for visibility, never upgraded here; someone else maintains it. Flag it loudly in the report if it has a critical, since the action is to tell them, not to open a PR.
  • UPTODATE — nothing available.
  • count ? / UNKNOWN — do not upgrade blind, and do not treat it as clean. Put it in the Addendum as needing a look. An unknown is a gap in our knowledge, not evidence of safety.

Order the queue by worst severity first (critical → high → …), count breaking ties. If --dry-run, print this queue with each recipe's CVE ids and severities, and STOP here.

3. Upgrade each one — via /recipe-upgrade subagents

Run /recipe-upgrade <recipe> per queued recipe as a subagent, in the queue order above, as a rolling pool keeping --capacity (default DRONE_RUNNER_CAPACITY) running at once and starting the next as each finishes — the same concurrency discipline as /upgrade-all §3, and safe for the same reason (per-run recipe trees + app-domain locks).

Each subagent does the full job: plan, implement the bump, verify green on cc-ci with !testme, and open a recipe PR. Default mode — no --with-tests: a genuinely stale test gets an explanatory PR comment, not a test edit.

Tell each subagent which CVEs justify its upgrade, with ids and severities, so the PR description says why it exists. That is most of this skill's value to a reviewer: a PR that names the CVSS-9.8 RCE it closes gets merged today, an unexplained version bump waits a fortnight.

Collect per recipe: PR url + number, the !testme verdict and build number, and any failure.

4. Report — one page covering sweep AND PRs

Write /tmp/cve-spec-<DATE>.json per /cve-check step 6, with these differences:

  • Rows for upgraded recipes carry the real ci (build N ✓ / RED N · <stage>) + ci_url, and pr/pr_url. status is the CI verdict (GREEN/FAILED/STALE); the live PR-status column derives itself from recipe + pr.
  • Rows for swept-but-not-upgraded recipes keep PENDING/UPTODATE with empty ci/pr, and a notes reason (0 CVEs — not upgraded, external — maintained elsewhere, below --min-severity).
  • Include changes[] — one entry per recipe that got a PR, describing what the upgrade changes and the CVEs it closes.
  • Keep "kind": "cve": it titles the page "The Recipe Report — CVE check" and files it as cve-<DATE>.html, alongside the weekly editions in the same archive index.

Then render + publish exactly as /cve-check step 7, and verify as its step 8. Print the report URL, N swept · M upgraded · K PRs green · J failed, and CVE CHECK AND UPGRADE COMPLETE.

Guardrails

  • NEVER merge. Create and verify; a human merges. Never push to true upstream.
  • Never weaken a test to make a PR green, and never edit a test without --with-tests.
  • Never upgrade a recipe whose CVE count is unknown on the assumption it is fine — surface it.
  • Never upgrade an external recipe here, even with a critical; report it instead.
  • Public-safe report only — no secrets, tokens, internal hostnames, raw logs, or spend figures.
  • If the sweep finds nothing at or above --min-severity, that is a good outcome: publish the report saying so and open no PRs. Do not manufacture work.