CI security scanning¶
afmpeg's merge-request gate runs several security scanners from the
phpboyscout/cicd go-security component. This page explains what each does and
records the non-obvious decisions — especially the osv-scanner handling, which
cost real debugging time and is worth not re-deriving.
The scanners¶
| Job | Tool | Scope | Reachability-aware? |
|---|---|---|---|
govulncheck |
Go's official scanner | stdlib + imported packages | Yes — call-graph aware |
osv-scanner |
Google OSV-DB | go.mod (declared deps) |
No — module/lockfile level |
trivy |
Aqua vuln DB | filesystem | No |
gitleaks |
secret-pattern scan | git history | n/a |
govulncheck and osv-scanner overlap deliberately: govulncheck is precise
(it only reports advisories your code actually reaches), osv-scanner is broad
(it reports every advisory against a declared dependency, reachable or not). A
finding in osv-scanner that govulncheck stays silent on is almost always an
unreachable advisory.
The GO-2026-5932 decision (x/crypto)¶
Symptom. Since a vuln-DB update, osv-scanner failed every MR on
GO-2026-5932 in golang.org/x/crypto (v0.53.0), while govulncheck did not
flag it.
Why it can't be dropped. x/crypto is not a stray dependency — it is the
foundation of the OpenPGP release-verification stack:
pkg/afmpeg
→ gitlab.com/phpboyscout/go/signing/verify (WithModuleRelease / WKD — specs 0010/0011)
→ github.com/ProtonMail/go-crypto/openpgp (OpenPGP)
→ golang.org/x/crypto/hkdf
It is additionally pulled by cloudflare/circl, golang.org/x/net (the HTTP/2
download path) and golang.org/x/mod. Removing it means removing signed-release
verification. And there is no fixed version upstream (FIXED VERSION: --),
so a bump cannot help either.
Why ignoring it is correct, not a shortcut. govulncheck — which is
call-graph aware — confirms afmpeg never calls the affected symbol: only
x/crypto/hkdf is linked, not the vulnerable function. So the finding is an
unreachable, unfixable, undroppable module-level false positive. That is exactly
what an ignore entry is for. Reachability is still enforced, by govulncheck.
The waiver is not carried here per-repo: it ships in the go-security
component itself (from cicd v0.21.0), which applies it to every consumer. afmpeg
therefore keeps no local .osv-scanner.toml. Revisit when x/crypto ships a fix —
that removal happens in the component, not here.
The two osv-scanner gotchas (now handled by the component)¶
Getting osv-scanner green took more than an ignore entry, and the debugging is
worth keeping even though the fix now lives upstream. The go-security component
used to run /osv-scanner -L go.mod, and two things broke — both fixed in
cicd v0.21.0 (spec: the component's osv-scanner-toolchain-and-waiver):
-
Config not applied. osv-scanner does not auto-discover
.osv-scanner.tomlfor a-L(lockfile) scan, and the job passed no--config, so any ignore list was silently inert. The component now appends its global waivers to the repo's.osv-scanner.toml(creating it if absent) and always passes--config, so per-repo ignores work too. -
Exit 127 from a failed internal build. osv-scanner runs its own
govulncheckfor call-analysis, which builds the module using the Go toolchain bundled in the scanner image (GOTOOLCHAIN=local). Oncego.modrequired Go 1.26.5, that build failed inside the older-Go scanner image (go.mod requires go >= 1.26.5 (running go 1.26.4; GOTOOLCHAIN=local)), and osv-scanner exited 127 — but only after the ignore emptied the result set (with findings present it exits 1, masking the error). The component now defaultsosv_scanner_call_analysisto false (passing--no-call-analysis=all): that reachability step is redundant (the dedicatedgovulncheckjob already provides it) and it fragilely couples the scanner image's Go togo.mod's requirement.
afmpeg briefly carried these as a local osv-scanner: job override; that override
(and the local .osv-scanner.toml) were removed once it adopted go-security
@v0.21.0.
The Go 1.26.5 bump¶
Separately, GO-2026-5856 and GO-2026-4970 are standard-library advisories
fixed in Go 1.26.5, so they can only be cleared by the toolchain. Bumping
go.mod's go directive to 1.26.5 cleared both (govulncheck green,
osv-scanner stdlib findings gone). The shared dev-tools image resolves the
1.26.5 toolchain fine (GOTOOLCHAIN=auto), so the bump did not break the Go
jobs — it only tripped osv-scanner's bundled-Go call-analysis, per gotcha 2.
Rule of thumb for the next scanner failure¶
- Does
govulncheckalso flag it? If yes, it's reachable — fix it (bump or patch), don't ignore. osv-scanner-only + a fixed version exists → bump the dep.osv-scanner-only + no fix +govulnchecksilent + undroppable → ignore with a datedignoreUntiland record why here.- A scanner failing on infrastructure (toolchain version, exit-code quirk),
not a real finding → fix it in
.gitlab-ci.yml, and note the cause so the next person doesn't re-debug it.