feat(ci): govulncheck - add PR checks, SARIF Code Scanning, and automated remediation#4595
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files🚀 New features to boost your workflow:
|
|
✅ Tests 🎉 All green!❄️ No new flaky tests detected 🎯 Code Coverage (details) 🔗 Commit SHA: 54c1038 | Docs | Datadog PR Page | Was this helpful? React with 👍/👎 or give us feedback! |
|
You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool. What Enabling Code Scanning Means:
For more information about GitHub Code Scanning, check out the documentation. |
BenchmarksBenchmark execution time: 2026-03-27 11:33:43 Comparing candidate commit 54c1038 in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 216 metrics, 8 unstable metrics.
|
|
I agree with the spirit of Filippo's post, and I like this approach, but a heads-up: IMO we'll get more support tickets and escalations because we aren't going to bump dependencies with a CVE unless the impacted code is used (directly or not) by ours. |
|
@codex review |
This is something we should live with. The recent incident showed us that just upgrading forward for sake of upgrading can make us more vulnerable. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5bd1ecd736
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| paths: | ||
| - "**/*.go" | ||
| - "**/go.mod" | ||
| - "**/go.sum" |
There was a problem hiding this comment.
Trigger govulncheck on go.work dependency changes
The PR trigger is filtered to *.go, go.mod, and go.sum, but this repo also has go.work/go.work.sum; a PR that only changes workspace replacements or workspace dependency pins will skip this workflow entirely, so reachable-vulnerability gating and SARIF upload are bypassed for that change. Add go.work and go.work.sum to the pull_request.paths list so dependency-only workspace changes are still scanned.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 169fc65 and added go.work and go.work.sum to the pull_request.paths filter. Workspace-level dependency changes will now trigger both jobs.
…ntrib SARIF gap Add go.work and go.work.sum to pull_request.paths so workspace-level dependency changes (replacements, workspace pins) trigger govulncheck instead of silently bypassing it. Add a TODO comment documenting that contrib module vulnerabilities are caught by the blocking govulncheck-tests check but do not appear in GitHub Code Scanning alerts — contrib SARIF upload is a follow-up improvement requiring multi-SARIF tooling. Addresses Codex review feedback on PR #4595.
|
@kakkoyun I was going to merge this, but there is a conflict. Can you take care of it? Thanks! |
…mediation Replace Dependabot Security Alerts with govulncheck-based scanning. Dependabot flags every CVE in transitive deps regardless of reachability, generating alert fatigue. govulncheck uses call graph analysis to only report vulnerabilities in code paths that are actually called. Changes: - govulncheck.yml: add pull_request trigger (blocks PRs with reachable vulns), SARIF upload to GitHub Code Scanning via the official golang/govulncheck-action, always installs govulncheck@latest, adds concurrency group, pins all actions to latest SHA - govulncheck-fix.yml: new weekly remediation workflow that scans all modules (core + 65+ contrib), identifies fixes, updates go.mod files, and opens a PR automatically - govulncheck-fix.sh: remediation script that parses govulncheck JSON output, extracts module@fixedVersion pairs, runs go get + go mod tidy across all affected modules Next step: disable Dependabot Security Alerts for Go in GitHub repo settings once this merges (Settings > Code security > Dependabot alerts).
…tion golang/govulncheck-action is blocked by the DataDog enterprise action allowlist (it internally uses actions/checkout@v4.1.1 and actions/setup-go@v5.0.0 which are not in the allowlist). Replace with: setup-go + go install govulncheck@latest + govulncheck -format sarif, which uses only GitHub-created actions (allowed).
…ntrib SARIF gap Add go.work and go.work.sum to pull_request.paths so workspace-level dependency changes (replacements, workspace pins) trigger govulncheck instead of silently bypassing it. Add a TODO comment documenting that contrib module vulnerabilities are caught by the blocking govulncheck-tests check but do not appear in GitHub Code Scanning alerts — contrib SARIF upload is a follow-up improvement requiring multi-SARIF tooling. Addresses Codex review feedback on PR #4595.
169fc65 to
bbfa874
Compare
…eps (#4597) ### What does this PR do? Adds `persist-credentials: false` to all `actions/checkout` steps in the govulncheck workflows (`govulncheck.yml` and `govulncheck-fix.yml`). ### Motivation Per [Filippo Valsorda's recommendation](https://words.filippo.io/dependabot/), `actions/checkout` leaves a temporary GitHub token on the runner filesystem by default. Any code executed in the job — including `govulncheck` downloading the vuln DB, `go get` fetching modules, and transitive dependency code — can read this token. Adding `persist-credentials: false` revokes the token from the filesystem immediately after checkout. The `govulncheck-fix.yml` workflow still works correctly because its push step uses `gh auth setup-git` with `GH_TOKEN` env var, which configures its own credential helper independently of the checkout-persisted credential. No existing workflow in this repo currently uses `persist-credentials: false`. This change starts with the govulncheck workflows as a natural follow-up to [#4595](#4595) — the team can decide whether to adopt it repo-wide. Technically we should adopt `persist-credentials: false` across all workflows in this repo. See [actions/checkout docs](https://github.com/actions/checkout#persist-credentials). ### Reviewer's Checklist - [x] N/A — CI/workflow-only change, no Go code modified ### References - [Filippo Valsorda: Turn Dependabot Off](https://words.filippo.io/dependabot/) — section on supply chain attack mitigation - [actions/checkout: persist-credentials](https://github.com/actions/checkout#persist-credentials) — official docs - [PR #4595](#4595) — parent govulncheck migration PR
…#4605) ## Why The `govulncheck-analysis` job (non-blocking SARIF upload) only scanned core packages. Contrib module vulnerabilities were caught by `govulncheck-tests` (blocking, sandboxed) but never appeared in the GitHub Security tab / Code Scanning. This created a gap: a contrib CVE would fail the PR check but leave no trace in the Security dashboard. This PR closes that gap by adding a parallel non-blocking `govulncheck-contribs-analysis` job that scans every contrib module and uploads results to GitHub Code Scanning. ## What - **New script**: `govulncheck-contribs-sarif.sh` — mirrors `govulncheck-contribs-v2.sh` but uses `-format sarif`. It scans each contrib module, writes a per-module SARIF file to a temp directory, then merges all runs into a single output file via `jq`. - **New job**: `govulncheck-contribs-analysis` — sets up Go, installs govulncheck, runs the script, and uploads the merged SARIF under the `govulncheck-contribs` category. - **Updated comment** in `govulncheck-analysis`: replaces the `TODO` with a reference to the new job. - **Updated `paths` filter**: adds `govulncheck-contribs-sarif.sh` so changes to the script trigger the workflow. ## Design decisions **Why merge SARIF with `jq` instead of uploading per-module files?** The `upload-sarif` action accepts a directory, but uploading N files (one per contrib module) would create N separate tool runs in Code Scanning, making the Security tab noisy. Merging runs into one SARIF file keeps results grouped under a single `govulncheck-contribs` category. **Why not sandbox this job?** The `govulncheck-contribs-analysis` job is non-blocking and informational, consistent with `govulncheck-analysis`. The sandboxed `govulncheck-tests` job provides the security boundary for blocking checks. ## Stack This PR is part of a stack: ``` main └── #4595 kakkoyun/govulncheck (base) └── #4597 kakkoyun/govulncheck-persist-credentials └── #4598 kakkoyun/govulncheck-sandboxed-step └── #4599 kakkoyun/govulncheck-action-allowlist └── this PR kakkoyun/govulncheck-contrib-sarif ``` Merge order: #4595 → #4597 → #4598 → #4599 → this PR. ## Test plan - [ ] CI passes on this branch (all three jobs green) - [ ] `govulncheck-contribs-analysis` job appears in the Actions run - [ ] SARIF upload succeeds (check `upload-sarif` step output) - [ ] GitHub Security tab shows findings under `govulncheck-contribs` category after merge to main
The contrib SARIF gap is addressed by govulncheck-contribs-analysis (PR #4605), which scans each contrib module and uploads results to GitHub Code Scanning under a distinct category.

What does this PR do?
Migrates vulnerability scanning from Dependabot Security Alerts to `govulncheck`-based scanning. Three changes:
`govulncheck.yml` (updated): adds a `pull_request` trigger so govulncheck now gates PRs; adds a SARIF upload job that feeds into GitHub Code Scanning (replaces Dependabot alerts in the Security tab); always installs `govulncheck@latest`; adds a concurrency group to cancel stale runs; pins all actions to latest SHA.
`govulncheck-fix.yml` (new): weekly remediation workflow (Mondays 6 AM UTC, also `workflow_dispatch`) that scans all modules, identifies reachable vulnerabilities with available fixes, updates the affected `go.mod` files, and opens a PR automatically.
`govulncheck-fix.sh` (new): remediation script that parses `govulncheck -json` streaming output, extracts `(module, fixedVersion)` pairs from `finding.trace[-1]`, runs `go get module@version` across all affected `go.mod` files (core + all 65+ contrib modules), and runs `go mod tidy`.
Motivation
Dependabot Security Alerts flag every CVE in transitive dependencies regardless of whether the vulnerable code is actually reachable — the push that triggered this PR showed 32 alerts. `govulncheck` uses Go call graph analysis to only report vulnerabilities in code paths that are actually called, eliminating false positives.
After this merges, Dependabot Security Alerts for Go can be disabled in repo settings (Settings → Code security → Dependabot alerts). The `dependabot.yml` config is kept as-is since it only manages GitHub Actions version updates, which is still useful.
How SARIF + GitHub Code Scanning works
The `govulncheck-analysis` job runs `govulncheck -format sarif` and uploads the result via `github/codeql-action/upload-sarif`. Here is what happens end-to-end:
SARIF file generated: `govulncheck -format sarif` emits a structured JSON file (Static Analysis Results Interchange Format) describing each reachable vulnerability — including file path, line number, severity, CVE reference, and the full call chain that reaches the vulnerable symbol. Critically, `-format sarif` exits 0 even when vulnerabilities are found, so the upload step always runs regardless of findings.
Uploaded to GitHub Code Scanning: The SARIF is posted to the GitHub Code Scanning API under the `govulncheck` category. GitHub parses it and creates persistent alerts in Security → Code scanning alerts. Each alert includes the call stack showing exactly how the vulnerable code is reached from this module.
De-duplication across runs: If the same vulnerability appears in multiple scans, GitHub tracks it as a single alert (not a new one each time). When a dependency is updated and the vulnerability disappears from the SARIF, GitHub automatically closes the alert.
PR annotations: When a PR introduces a new reachable vulnerability, GitHub adds an inline annotation on the diff pointing to the call site.
Two-job design — soft gate + hard gate:
Reviewer's Checklist
References