Files
2026-07-13 13:39:12 +08:00

60 lines
4.0 KiB
Markdown

---
title: "Supply-Chain Gates"
---
# Supply-Chain Gates (Phase 8 · Block A)
OmniRoute publishes npm + Docker artifacts. These gates provide provenance,
inventory (SBOM) and CVE scanning, all OSS, plugged into release workflows.
**Advisory-first** posture — they report now, promote to blocking after the 1st
green release.
| Gate | Tool | Where | Blocks? | Output |
| --------------------- | ---------------------------------------------- | ----------------------------- | ------------------------ | --------------------------------------------- |
| SLSA provenance (npm) | `npm --provenance` (OIDC) | `npm-publish.yml` | only if publish fails | badge npmjs / `npm audit signatures` |
| SBOM npm | `@cyclonedx/cyclonedx-npm` | `npm-publish.yml` | only if generation fails | Release asset + artifact |
| SBOM image | `anchore/sbom-action` (syft) | `docker-publish.yml` (merge) | advisory | CycloneDX artifact |
| Trivy CVE (SARIF) | `aquasecurity/trivy-action` | `docker-publish.yml` (merge) | advisory | SARIF (HIGH+CRITICAL) → Security tab |
| Trivy CRITICAL gate | `aquasecurity/trivy-action` | `docker-publish.yml` (merge) | **blocking** | `exit-code: '1'` on fixable CRITICAL |
| osv vulnCount | `osv-scanner` (`check:vuln-ratchet --ratchet`) | `ci.yml` (`quality-extended`) | **blocking** | ratchets `metrics.vulnCount` (direction:down) |
| OpenSSF Scorecard | `ossf/scorecard-action` | `scorecard.yml` (cron) | advisory | SARIF → Security + badge |
The image CVE ratchet uses **two steps** in `docker-publish.yml`: the SARIF step
(`HIGH,CRITICAL`, `exit-code: 0`) keeps HIGH+CRITICAL visible in the Security tab
without blocking; the _CRITICAL gate_ step (`severity: CRITICAL`, `ignore-unfixed: true`,
`exit-code: 1`) fails the release on a CRITICAL CVE **with a fix available**. `ignore-unfixed`
prevents blocking the release for a base-image CVE without an upstream patch.
## ⚠️ CVE Variance (blocking osv/Trivy gates)
osv and Trivy compare deps against CVE databases that **continuously grow**. A PR
that **touches no dependencies** can suddenly turn red because a new CVE was
disclosed in an existing dep (osv: measured `vulnCount` > baseline; Trivy: a new
fixable CRITICAL in the image). **This is EXPECTED operational behavior of a blocking
CVE gate, not a product regression.**
When osv or Trivy go red due to a newly disclosed CVE, the remedy is:
1. **Bump the affected dep** (preferred) — upgrade to the patched version via `package.json`
`overrides` (transitive deps) or rebuild the image on a patched base.
2. **If there is no upstream fix:**
- **osv:** re-baseline `metrics.vulnCount` in `config/quality/quality-baseline.json`
(`npm run quality:ratchet -- --update` does not cover dedicated gates — edit the value by
hand, `direction:down`) with a justification note + tracking issue.
- **Trivy:** add an entry in `.trivyignore` (CVE-ID per line) with a justification
comment + tracking issue. `ignore-unfixed: true` already covers CVEs without
patches automatically.
Both gates **gracefully SKIP** (exit 0) when the tool is absent or the measurement
fails (osv-scanner not in PATH, osv.dev/network unreachable, invalid JSON) — a
**measurement** failure never blocks, only a **measured** regression blocks.
## Backlog: Scorecard advisory → blocking
After the 1st green release with Scorecard reporting:
- Scorecard: score ratchet (freezes the measured score; cannot decrease).
Complements the Phase 7 gates (osv-scanner, gitleaks, actionlint+zizmor): zizmor
audits the workflows themselves; Scorecard measures the repo posture in aggregate.