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.
This commit is contained in:
@@ -37,6 +37,15 @@ keeps every weekly edition looking the same regardless of which model writes the
|
||||
- **Security analysis.** Scan the per-recipe `upgrade_notes_md` + the summary (and use your own
|
||||
knowledge of the version bumps) for upgrades that fix **CVEs / security issues**. For each recipe,
|
||||
**count the CVEs** the PR fixes — this drives both the table's `cve` column and the priority sort.
|
||||
- **ADDITIONALLY, and never instead:** each per-recipe log carries an `### Advisory scan
|
||||
(deterministic pre-step)` block (from `cc-ci-plan/advisory-scan.py` — GitHub Security
|
||||
Advisories + vendor security pages + OSV, with severities and fixed-in versions). Treat its
|
||||
CVE list as a **further source** and report the **UNION** of it and what you found by reading.
|
||||
Its entries are machine-derived with advisory IDs, so prefer them for CVE ids / severities /
|
||||
fixed-in versions, and cite the GHSA where present in the Security Bulletin. If a recipe has
|
||||
no scan block, or the block lists **failed sources**, the count is **not** authoritative:
|
||||
render the cve cell as `?` (unknown), never `none` — a blank that reads as "clean" is exactly
|
||||
how two CVSS-9.8 gitea RCEs were reported as "none" on 2026-08-07.
|
||||
Anything **critical/high** also gets a `security` bulletin entry (recipe · CVE id(s) + severity ·
|
||||
what it fixes · PR link); be specific about severity and what's exposed if not merged.
|
||||
- **Lead — ONE short paragraph.** A tight, concrete opener in opus's voice: fleet state in a sentence
|
||||
|
||||
@@ -157,6 +157,35 @@ On cc-ci's `~/.abra/recipes/<recipe>` (wrap every abra call per the pseudo-TTY b
|
||||
`open-recipe-pr.sh`). Do **not** push to upstream; the version bump + tag + publish are the operator's
|
||||
final `abra recipe release` step.
|
||||
|
||||
### 2a. Advisory scan (deterministic; ADDITIVE — run it, never skip it)
|
||||
|
||||
Run the deterministic scanner for the exact upgrade window and **paste its markdown block verbatim
|
||||
into the per-recipe log**:
|
||||
|
||||
```
|
||||
python3 /srv/cc-ci/cc-ci-plan/advisory-scan.py <recipe> --from <old-app-version> --to <new-app-version>
|
||||
```
|
||||
|
||||
It queries, per recipe: the **GitHub Security Advisories API** for every source repo in
|
||||
`cc-ci-plan/upstream/<recipe>.md` (CVE + GHSA + severity + vulnerable/patched ranges, so
|
||||
"fixed by THIS upgrade" is computed, not guessed), every **vendor release/security URL** in that
|
||||
registry (fetched + regex-scanned for CVE ids), and **OSV** where a package mapping exists.
|
||||
|
||||
**This does NOT replace your own release-note reading — it is an ADDITIONAL evidence source.** Do
|
||||
exactly what you did before, then union the two: the CVE count you report is the union of the CVEs
|
||||
you found in the notes and the CVEs the scan found. Never let the scan lower a count you established
|
||||
by reading.
|
||||
|
||||
Why it exists: gitea 1.27.1 fixed CVE-2026-60004 and CVE-2026-59774 (both CVSS 9.8). Both are named
|
||||
only in the vendor's blog security section — the GitHub *release notes* mention neither — so the
|
||||
release-note read found one unrelated minor item and the weekly report printed a CVE count of "1",
|
||||
then "none". Advisory databases lagged too (OSV 404'd on both; NVD's API had neither by CPE, id, or
|
||||
keyword), which is why the GitHub advisory API and the vendor pages lead.
|
||||
|
||||
If the scanner reports **failed sources**, say so in the log — an incomplete scan must not read as
|
||||
a clean one. If a vendor publishes security notes at a URL the registry lacks (gitea's
|
||||
`blog.gitea.com`), **add it to `cc-ci-plan/upstream/<recipe>.md`** so the next scan sees it.
|
||||
|
||||
### 2b. Direct deploy + inspect on cc-ci — live feedback BEFORE CI (recipe-maintainer style)
|
||||
Before opening the PR / running `!testme`, deploy the WIP recipe **directly** on the cc-ci server and
|
||||
watch it converge — the way recipe-maintainer tests on `cctest`. This gives you **live logs +
|
||||
|
||||
Reference in New Issue
Block a user