Skip to content

feat(ci): govulncheck - add PR checks, SARIF Code Scanning, and automated remediation#4595

Merged
gh-worker-dd-mergequeue-cf854d[bot] merged 5 commits intomainfrom
kakkoyun/govulncheck
Mar 27, 2026
Merged

feat(ci): govulncheck - add PR checks, SARIF Code Scanning, and automated remediation#4595
gh-worker-dd-mergequeue-cf854d[bot] merged 5 commits intomainfrom
kakkoyun/govulncheck

Conversation

@kakkoyun
Copy link
Copy Markdown
Member

@kakkoyun kakkoyun commented Mar 25, 2026

What does this PR do?

Migrates vulnerability scanning from Dependabot Security Alerts to `govulncheck`-based scanning. Three changes:

  1. `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.

  2. `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.

  3. `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:

  1. 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.

  2. 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.

  3. 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.

  4. PR annotations: When a PR introduces a new reachable vulnerability, GitHub adds an inline annotation on the diff pointing to the call site.

  5. Two-job design — soft gate + hard gate:

    • `govulncheck-analysis`: non-blocking, uploads SARIF for Code Scanning visibility. Always succeeds so the upload always runs.
    • `govulncheck-tests`: blocking PR check, runs `govulncheck` in text mode (exits non-zero on any reachable finding). This is the gate that fails the PR.

    Why not use `golang/govulncheck-action`? The official action is blocked by the DataDog enterprise action allowlist (it internally uses `actions/checkout@v4` and `actions/setup-go@v5` which are not in the allowlist pattern). The `govulncheck -format sarif` flag is available natively in `govulncheck@latest`, so we install it directly via `go install` instead.

Reviewer's Checklist

  • Changed code has unit tests for its functionality at or near 100% coverage.
  • System-Tests covering this feature have been added and enabled with the va.b.c-dev version tag.
  • There is a benchmark for any new code, or changes to existing code.
  • If this interacts with the agent in a new way, a system test has been added.
  • New code is free of linting errors. You can check this by running `make lint` locally.
  • New code doesn't break existing tests. You can check this by running `make test` locally.
  • Add an appropriate team label so this PR gets put in the right place for the release notes.
  • All generated files are up to date. You can check this by running `make generate` locally.
  • Non-trivial go.mod changes, e.g. adding new modules, are reviewed by @DataDog/dd-trace-go-guild. Make sure all nested modules are up to date by running `make fix-modules` locally.

References

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 25, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 60.67%. Comparing base (b22fbe0) to head (54c1038).

Additional details and impacted files

see 437 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@datadog-datadog-prod-us1-2
Copy link
Copy Markdown

datadog-datadog-prod-us1-2 bot commented Mar 25, 2026

✅ Tests

🎉 All green!

❄️ No new flaky tests detected
🧪 All tests passed

🎯 Code Coverage (details)
Patch Coverage: 100.00%
Overall Coverage: 60.03% (+3.89%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 54c1038 | Docs | Datadog PR Page | Was this helpful? React with 👍/👎 or give us feedback!

@github-advanced-security
Copy link
Copy Markdown

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:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@kakkoyun kakkoyun changed the title ci(govulncheck): add PR checks, SARIF Code Scanning, and automated remediation feat(ci): govulncheck - add PR checks, SARIF Code Scanning, and automated remediation Mar 25, 2026
@kakkoyun kakkoyun added the AI Assisted AI/LLM assistance used in this PR (partially or fully) label Mar 25, 2026
@kakkoyun kakkoyun requested a review from darccio March 25, 2026 14:53
@kakkoyun kakkoyun marked this pull request as ready for review March 25, 2026 15:09
@kakkoyun kakkoyun requested a review from a team as a code owner March 25, 2026 15:09
@pr-commenter
Copy link
Copy Markdown

pr-commenter bot commented Mar 25, 2026

Benchmarks

Benchmark execution time: 2026-03-27 11:33:43

Comparing candidate commit 54c1038 in PR branch kakkoyun/govulncheck with baseline commit b22fbe0 in branch main.

Found 0 performance improvements and 0 performance regressions! Performance is the same for 216 metrics, 8 unstable metrics.

Explanation

This is an A/B test comparing a candidate commit's performance against that of a baseline commit. Performance changes are noted in the tables below as:

  • 🟩 = significantly better candidate vs. baseline
  • 🟥 = significantly worse candidate vs. baseline

We compute a confidence interval (CI) over the relative difference of means between metrics from the candidate and baseline commits, considering the baseline as the reference.

If the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD), the change is considered significant.

Feel free to reach out to #apm-benchmarking-platform on Slack if you have any questions.

More details about the CI and significant changes

You can imagine this CI as a range of values that is likely to contain the true difference of means between the candidate and baseline commits.

CIs of the difference of means are often centered around 0%, because often changes are not that big:

---------------------------------(------|---^--------)-------------------------------->
                              -0.6%    0%  0.3%     +1.2%
                                 |          |        |
         lower bound of the CI --'          |        |
sample mean (center of the CI) -------------'        |
         upper bound of the CI ----------------------'

As described above, a change is considered significant if the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD).

For instance, for an execution time metric, this confidence interval indicates a significantly worse performance:

----------------------------------------|---------|---(---------^---------)---------->
                                       0%        1%  1.3%      2.2%      3.1%
                                                  |   |         |         |
       significant impact threshold --------------'   |         |         |
                      lower bound of CI --------------'         |         |
       sample mean (center of the CI) --------------------------'         |
                      upper bound of CI ----------------------------------'

@darccio
Copy link
Copy Markdown
Member

darccio commented Mar 25, 2026

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.

@darccio
Copy link
Copy Markdown
Member

darccio commented Mar 25, 2026

@codex review

@kakkoyun
Copy link
Copy Markdown
Member Author

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.

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.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +4 to +7
paths:
- "**/*.go"
- "**/go.mod"
- "**/go.sum"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Member Author

@kakkoyun kakkoyun Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

kakkoyun added a commit that referenced this pull request Mar 26, 2026
…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.
Copy link
Copy Markdown
Member

@darccio darccio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@darccio
Copy link
Copy Markdown
Member

darccio commented Mar 27, 2026

@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.
@kakkoyun kakkoyun force-pushed the kakkoyun/govulncheck branch from 169fc65 to bbfa874 Compare March 27, 2026 10:51
…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
kakkoyun added a commit that referenced this pull request Mar 27, 2026
…#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.
@kakkoyun kakkoyun requested a review from darccio March 27, 2026 11:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI Assisted AI/LLM assistance used in this PR (partially or fully) mergequeue-status: done

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants