Commit 73b8a47
ci: gate releases on a vulnerability scan of the shipped bundle (#4300)
* ci: gate releases on a vulnerability scan of the shipped bundle
Adds a scan of the binaries Kairos actually ships, for the kairos-init
version this repo pins.
The existing scanning cannot see these dependencies. kairos-init
UPX-compresses the bundled binaries, and a UPX-packed Go binary no longer
exposes its module metadata, so immucore, kairos-agent, provider-kairos and
the rest are opaque to a scanner. release.yaml's grype and trivy runs are
also report-only with grype_sarif_fail_build disabled, so a green release
says nothing about CVEs.
The job resolves ARG KAIROS_INIT from images/Dockerfile, checks kairos-init
out at that tag, runs `make download` with SKIP_UPX=true so the binaries
stay readable, and scans the result with osv-scanner. The scanned artifact
is deliberately not byte-identical to the shipped one; it is composed from
the same sources at the same pins, which is what matters for dependency
scanning.
Two scanner flags are load-bearing and are commented as such, because
without either the scan finds nothing and reports success:
--no-ignore kairos-init's .gitignore excludes
pkg/bundled/binaries/, and osv-scanner
honours .gitignore.
--experimental-plugins artifact the default plugin set cannot read Go
binaries at all.
A separate step fails the build when zero packages were extracted, so a
broken scan cannot pass as a clean one.
osv-scanner.toml carries the ignore list. Anything with a published,
takeable fix is meant to be bumped rather than ignored; entries are limited
to what cannot currently be fixed, each with a reason and an expiry, and an
expired entry fails the build. Expiry varies by category so the gate stays
trustworthy: 90 days where no fix exists upstream, two weeks where the only
fix is a Go prerelease, thirty days where clearing it needs a major upgrade.
Runs on pull_request so master stays releasable, and exposes workflow_call
so release.yaml can depend on it.
Refs: #3985
Signed-off-by: Mauro Morales <contact@mauromorales.com>
* ci: scope the scan triggers to releases and the files that decide the result
Review feedback: this is a release gate, so it should not run on every pull
request.
Correct, and the unscoped trigger was actively harmful. The findings belong
to the pinned dependency set, not to the change under review, so with
advisories outstanding every open PR would show a red check for CVEs its
author did not introduce and cannot fix -- including external contributors'
PRs on a public repo. New advisories are published continuously, so a PR
green yesterday would go red today for reasons unrelated to it.
workflow_call is the gate; release.yaml depends on it. workflow_dispatch
stays for manual runs. pull_request is kept but scoped to the three files
that actually determine the outcome: the kairos-init pin in
images/Dockerfile, the ignore list, and this workflow. That keeps a bad pin
bump or a bad ignore entry caught where it is relevant, and means edits to
the workflow itself are still exercised in CI, without touching any
unrelated PR.
Signed-off-by: Mauro Morales <contact@mauromorales.com>
* ci: make the scan an actual release gate
The previous commit exposed workflow_call but nothing called it, so a
workflow named "Release vulnerability scan" never ran on a release. It
gated nothing.
release.yaml and release-arm.yaml now both start with a vulnerability-scan
job, and every publishing job depends on it: core, standard-k3s and
standard-k0s on amd64, core and standard on arm64. A tag push runs the scan
first, and if the shipped bundle carries unignored advisories the factory
jobs never run, so no artifacts and no GitHub release are produced.
The scan resolves the kairos-init pin from images/Dockerfile, so it always
describes the composition of the release being cut rather than whatever is
current on master.
One scan covers both architectures. It reads Go module metadata from the
amd64 bundle, and the module set is the same across architectures because
it comes from the same sources at the same pins.
Signed-off-by: Mauro Morales <contact@mauromorales.com>
* ci: distinguish advisories from findings in the scan report
The first CI run reported "14 unignored advisories" while the scan had
found 13. The scan was right and the message was wrong.
One advisory can affect several module versions in the same bundle, because
different binaries pin different versions -- GO-2026-5970 is present at both
golang.org/x/text@0.37.0 and @0.38.0. The count was over rows, one per
(advisory, module@version) pair, and every row was being called an advisory.
Counts both now: advisories for the headline, findings for the per-module
rows, both in the error and the step summary. The gate condition is
unchanged.
Signed-off-by: Mauro Morales <contact@mauromorales.com>
* ci: ignore two advisories whose fixes break edgevpn connectivity
Adds an upstream-regression category for the case the existing three did not
cover: a fix is published, but taking it breaks the component.
Both advisories are in the edgevpn binary, which ships in every Kairos
release from mudler/edgevpn. Bisected against edgevpn's pkg/node suite,
which exercises real peer-to-peer connectivity. Both make the "nodes can
write to the ledger" spec time out at 240s where an unmodified checkout
passes in 10-13 seconds.
webtransport-go v0.11.1 pulls quic-go 0.59.1 -> 0.60.0 and that alone
reproduces the failure; go-libp2p pins quic-go tightly, so this likely needs
a go-libp2p bump first. x/text v0.39.0 passes alone but fails combined with
the pion bumps, and x/text supplies IDNA which multiaddr uses for DNS peer
addresses.
The two advisories in the same scan that could be taken safely are in
mudler/edgevpn#1075. These two were deliberately left out of it.
Expiry is 60 days rather than the 30 used for major-upgrade-required: the
work is in a project we do not control, so a shorter clock would redden the
gate without giving anyone an action.
Signed-off-by: Mauro Morales <contact@mauromorales.com>
* ci: fix the false-green guard failing on clean scans, ignore two pending fixes
Two changes, one a real bug found while verifying the provider-kairos
v2.16.2 bump.
The guard was inverted in effect. osv-scanner's default JSON only emits
results for packages that HAVE findings, so a scan with nothing to report
produces an empty results array -- identical, to the guard, to a scan that
read no binaries at all. It would have failed every genuinely clean release,
which is the opposite of what it exists for. Adding --all-packages makes the
output list everything it read: the same bundle now reports 1425 packages
and 0 vulnerabilities, so "read nothing" and "found nothing" are finally
distinguishable.
Also adds an upstream-fix-pending category and the two advisories it covers.
Both are pion parsing DoS issues in the edgevpn binary. provider-kairos
v2.16.2 cleared its copies; the edgevpn copies need mudler/edgevpn#1075
merged and an edgevpn release before EDGEVPN_VERSION can move. Thirty days,
shorter than upstream-regression, because this one is expected to resolve.
Verified against the real bundle at provider-kairos v2.16.2: guard passes on
1425 packages, enforce passes with zero unignored advisories.
Signed-off-by: Mauro Morales <contact@mauromorales.com>
---------
Signed-off-by: Mauro Morales <contact@mauromorales.com>
Co-authored-by: Mauro Morales <contact@mauromorales.com>1 parent be1a660 commit 73b8a47
4 files changed
Lines changed: 389 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
9 | 17 | | |
10 | 18 | | |
11 | 19 | | |
| 20 | + | |
| 21 | + | |
12 | 22 | | |
13 | 23 | | |
14 | 24 | | |
| |||
114 | 124 | | |
115 | 125 | | |
116 | 126 | | |
| 127 | + | |
117 | 128 | | |
118 | 129 | | |
119 | 130 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
9 | 17 | | |
10 | 18 | | |
11 | 19 | | |
| 20 | + | |
| 21 | + | |
12 | 22 | | |
13 | 23 | | |
14 | 24 | | |
| |||
115 | 125 | | |
116 | 126 | | |
117 | 127 | | |
| 128 | + | |
118 | 129 | | |
119 | 130 | | |
120 | 131 | | |
| |||
161 | 172 | | |
162 | 173 | | |
163 | 174 | | |
| 175 | + | |
164 | 176 | | |
165 | 177 | | |
166 | 178 | | |
| |||
0 commit comments