Skip to content

fix(ci): govulncheck fails repo-wide on 3 unfixable lib/pq advisories, blocking every merge #1849

Description

@cristim

Blocks every merge. Not caused by any PR.

What

Security Scanning → Run govulncheck CVE scanner (all modules) now fails on three advisories in github.com/lib/pq@v1.10.9:

ID Module Fixed in
GO-2026-6170 github.com/lib/pq N/A
GO-2026-6171 github.com/lib/pq N/A
GO-2026-6172 github.com/lib/pq N/A

All three report Fixed in: N/A. No version bump clears them, now or on any schedule.

lib/pq is an indirect dependency in the root go.mod (v1.10.9 // indirect) and appears in no other module's go.mod.

Why it appeared with no code change

Same mechanism as #1829: govulncheck fetches the vulnerability database at run time, so previously-green commits turn red when advisories are published.

Evidence it is time-based rather than change-based:

The next push to main, and every PR, will fail until this is resolved.

Why this is harder than #1829

#1829 was stdlib advisories fixed in go1.26.6; a one-line toolchain bump cleared them. Here there is no fixed version to move to. The options are all judgement calls:

  1. Remove the dependency. lib/pq is deprecated upstream in favour of pgx, and this repo already uses pgx (pgxpool appears throughout internal/database). Determine what still pulls lib/pq in: if it arrives transitively through a single dependency, bumping or replacing that dependency may drop it entirely. This is the only option that actually removes the exposure.
  2. Establish it is unreachable and record that. Note the finding is currently failing the gate, and CI's govulncheck runs in source mode, which exits 0 when findings sit only at import/require level. That it fails implies the analysis reaches vulnerable symbols. Verify that directly before assuming otherwise, and check the binary too: govulncheck -mode=binary against /app/cudly from the built image tells you whether it ships.
  3. A narrowly justified, documented exception. Only if 1 is infeasible and 2 shows it unreachable. Not a blanket ignore list, and not continue-on-error, which would blind the gate to everything else. This repo has been through two rounds of exactly that failure mode (sec(build): shipped image still builds on go1.26.5, so the stdlib CVEs remain in the artifact after #1832 #1833, sec(ci): nothing scans the container image we ship, only source; a baked-in vulnerable binary is invisible by construction #1836).

Do not

Suppress the whole step, add --ignore-unfixed-style narrowing to govulncheck, or set continue-on-error. The gate is the only thing standing between a fresh advisory and a silent merge, and #1836 exists because scanning gaps let two CVE rounds ship green.

Verification bar

Whatever is chosen: re-run the per-module loop at the CI-pinned govulncheck v1.1.4 and show the result, capturing exit codes into variables rather than reading a pipeline's status. If the fix is a dependency removal, prove lib/pq is absent from the module graph afterwards (go mod why / go list -m all), not merely absent from go.mod.

Related: #1829 (same mechanism, fixable by a bump), #1837 (an unfixable advisory accepted with reasoning rather than suppressed), #1836 (why scanning gaps matter here).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions