Files
cc-ci-orchestrator/cc-ci-plan/upstream
autonomic-bot 5775fe23f8 security: deterministic advisory scan as an ADDITIVE pre-step
Why: gitea 1.27.1 fixed CVE-2026-60004 + CVE-2026-59774 (both CVSS 9.8). The
2026-08-03 report printed gitea's CVE count as '1', the 2026-08-07 report as
'none'. Cause chain: the upgrade subagent read the GitHub release notes, which
name NEITHER cve (they are announced only in the vendor blog's security section),
so it recorded one unrelated minor item; the report then derived security content
from those notes plus model knowledge, and the model's training predates the CVEs.
Nothing in the pipeline ever queried an advisory source.

cc-ci-plan/advisory-scan.py — deterministic, per recipe, per upgrade window:
  1. GitHub Security Advisories API for every source repo in the upstream registry.
     PRIMARY: CVE + GHSA + severity + vulnerable/patched ranges, so 'fixed by THIS
     upgrade' is computed. Needs no new per-recipe config (134 registry URLs are
     already github.com).
  2. Vendor release/security pages — every registry URL, fetched + regex-scanned.
     This is the source that actually had the gitea CVEs.
  3. OSV where a package mapping exists — supplementary.
Each source reports its own status so 'checked, none found' is never confused with
'not checked'. Source selection was measured, not assumed: for these two CVEs OSV
404'd and NVD's API had them by neither CPE, id, nor keyword — advisory DBs lag the
vendor, hence 1+2 lead.

Wiring is strictly ADDITIVE:
- /recipe-upgrade gains step 2a: run the scan, paste the block into the per-recipe
  log, and report the UNION of it and the existing release-note reading. The scan
  may never lower a count established by reading.
- /recipe-report treats the block as a FURTHER source, prefers its advisory ids /
  severities / fixed-in versions for citation, and must render '?' (not 'none')
  when a scan is absent or has failed sources — the false-clean 'none' is exactly
  what happened on 2026-08-07.
- upstream/gitea.md records blog.gitea.com as the security-announcement URL.

Verified on the real regression: 1.27.0 -> 1.27.1 now yields exactly the 2 missed
criticals with their GHSA ids; the wider 1.26.2 -> 1.27.1 window yields 62.
2026-08-10 18:25:58 +00:00
..
2026-08-07 04:44:40 +00:00

Upstream release-notes registry

Per-recipe maps of where each image's release notes / changelog live. This is the cc-ci analog of recipe-maintainer's recipe-info/<recipe>/upstream.md: the /recipe-upgrade skill reads cc-ci-plan/upstream/<recipe>.md so it doesn't have to rediscover the upstream source for every image on every weekly run — discover once, persist, reuse.

How /recipe-upgrade uses it (step 1)

  1. Read cc-ci-plan/upstream/<recipe>.md.
  2. If it's missing, or an image in the recipe's compose.yml isn't covered (new/renamed service), discover the upstream project + releases page for each uncovered image (WebSearch the image → its GitHub/source repo → its releases/changelog page), then write/update this file and commit it (git -C /srv/cc-ci-orch add cc-ci-plan/upstream/<recipe>.md && commit && push).
  3. Fetch the release notes from these URLs between the current → target version of each service.

Format (one file per recipe)

# Upstream sources — <recipe>

| service | image | source repo | releases / changelog |
|---------|-------|-------------|----------------------|
| app     | cryptpad/cryptpad | https://github.com/cryptpad/cryptpad | https://github.com/cryptpad/cryptpad/releases |
| web     | nginx             | https://github.com/nginx/nginx       | https://nginx.org/en/CHANGES |

## Standing notes
- <recipe-specific upgrade gotchas worth remembering between runs, e.g. "n8n: postgres volume path
  changed from /var/lib/postgresql/data to /var/lib/postgresql in 2.2x">

Keep URLs canonical (the project's own releases/CHANGES page, not a mirror). Add a Standing notes section for migration gotchas you only want to learn once.