Skip to content

ci: stop gating the build on the runner's Go patch release - #15

Merged
juicycleff merged 1 commit into
mainfrom
fix/security-gate-stdlib
Aug 14, 2026
Merged

ci: stop gating the build on the runner's Go patch release#15
juicycleff merged 1 commit into
mainfrom
fix/security-gate-stdlib

Conversation

@juicycleff

@juicycleff juicycleff commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

main is red, and nothing in this repository caused it.

Vulnerability #1: GO-2026-6090   crypto/tls
    Found in: crypto/tls@go1.25.12
    Fixed in: crypto/tls@go1.25.13
Vulnerability #2: GO-2026-5972   encoding/asn1
    Found in: encoding/asn1@go1.25.12
    Fixed in: encoding/asn1@go1.25.13
Failing because govulncheck-fail-on-findings is true.

Both findings describe the version of Go the runner happened to install. The fix for both is go1.25.13, which arrives when the toolchain reaches the setup-go manifest and not before. Between an advisory being published and that happening, every branch is red on something no one here can act on.

That window will keep reopening on every Go patch release, so this is not a one-off.

What it also broke

A reusable workflow reports one conclusion for all of its jobs. When ci / Security failed, the whole ci job was marked failed, and everything declaring needs: ci skipped with it: drivers, extension, bench, lint. A skipped job reports as neither pass nor fail, so four modules quietly stopped being built and tested while the run still looked healthy.

The if: ${{ !cancelled() }} change already on main stops the cascade. This PR removes the cause.

The fix

govulncheck-fail-on-findings goes to false on the shared job. gosec still gates from there, and govulncheck findings are still reported, they just stop failing the build on the toolchain's behalf.

The real gate moves to a new vulncheck matrix that scans every module in the repository:

root, extension, azuredriver, gcsdriver, s3driver, sftpdriver

That closes a second hole at the same time. govulncheck resolves imports per module, so the shared job's scan of the repository root never once looked at the sub-modules, which is where every third-party dependency the project ships actually lives.

vulncheck deliberately does not declare needs: ci. A vulnerability gate that a failure elsewhere can skip is not a gate.

The rule it applies:

  • Standard-library findings get reported and never gate. They track the runner, not this code.
  • A finding gates only when its trace reaches a called symbol. If it stops at module or package level the dependency is present but the vulnerable code never runs, which is Dependabot's job to report rather than a build gate's job to block.
  • Reachable third-party findings gate unless they are listed in .github/govulncheck-allowlist.txt, which stays a backlog rather than an exemption. Delete a line to enforce a fix.

One gate, not two copies

The drivers job was carrying its own copy of that script. It now lives in .github/actions/govulncheck-gate and both callers use it, so the allowlist handling and the stdlib split cannot drift apart.

Verified

Every module was scanned locally before any of this was committed.

Module stdlib (reported) third-party (gating) Result
root 5 0 pass
extension 9 0 pass
sftpdriver 1 0 pass
gcsdriver 7 5, all allowlisted pass
s3driver 8 1, allowlisted pass
azuredriver 8 3, all allowlisted pass

Root and extension have no reachable third-party findings at all, so neither one needs an allowlist entry. Worth noting how lopsided those columns are: gate on the left-hand column and the build is red permanently, for reasons that change every few weeks and never involve this code.

Worth knowing

Re-running the failed job on main does not fix it. go1.25.13 is released and sits in the setup-go manifest, but a re-run still came back reporting Found in: crypto/tls@go1.25.12, because the runner image already ships a Go that satisfies the "1.25" spec and setup-go takes the cached hit instead of downloading the newer patch. So main stays red until the runner image rolls forward on GitHub's schedule, or until this lands.

The security job's govulncheck output is still visible in the run summary. You lose the automatic failure on a root-module finding from that job, but vulncheck (root) gates on exactly that, with the stdlib noise removed.

Nothing here touches the docs/ Next.js alerts or the three allowlisted driver backlogs. Those are still open.

The shared workflow's security job failed on any govulncheck finding,
standard-library ones included. A stdlib finding names the version of Go the
runner happens to have installed, so from the moment an advisory is published
until the fixed toolchain reaches the setup-go manifest, every branch went red
on something nobody here could act on. That window has been open on main since
GO-2026-6090 and GO-2026-5972 landed, both fixed in go1.25.13.

It also cascaded. A reusable workflow reports one conclusion for all of its
jobs, so the failure skipped drivers, extension, bench and lint along with it.

Set govulncheck-fail-on-findings false for that job and move the gate into a
new vulncheck matrix. gosec still gates from the shared job.

The gate itself moves into .github/actions/govulncheck-gate so the root
module, extension and the four drivers all run the same rule instead of the
drivers job carrying its own copy. Standard-library findings report; only
reachable third-party findings missing from the allowlist fail the build.
Verified locally against all six modules: root, extension and sftpdriver come
back clean, and the other three match their existing allowlist entries.

vulncheck deliberately does not declare needs: ci, so it cannot be skipped by
a failure somewhere else.
@juicycleff
juicycleff merged commit 33a74b0 into main Aug 14, 2026
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant