ci: sandbox govulncheck and latest-dependency smoke tests#4598
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files🚀 New features to boost your workflow:
|
🎉 All green!❄️ No new flaky tests detected 🎯 Code Coverage (details) 🔗 Commit SHA: f773ab6 | Docs | Datadog PR Page | Give us feedback! |
BenchmarksBenchmark execution time: 2026-05-12 16:18:19 Comparing candidate commit f773ab6 in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 273 metrics, 2 unstable metrics, 1 flaky benchmarks without significant changes.
|
34af022 to
31f8814
Compare
42b3d61 to
f5cf6b9
Compare
…#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
f5cf6b9 to
aa79d34
Compare
a21d539 to
2318e49
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2318e49fea
ℹ️ 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".
| go install golang.org/x/vuln/cmd/govulncheck@latest | ||
| govulncheck -format sarif \ |
There was a problem hiding this comment.
Put govulncheck on PATH before invoking it
In this sandbox go install does not make the next govulncheck command resolvable: Go installs commands to GOBIN/GOPATH/bin by default (https://pkg.go.dev/cmd/go#hdr-Compile_and_install_packages_and_dependencies), while geomys/sandboxed-step constructs PATH from standard directories plus RUNNER_TOOL_CACHE entries only (https://github.com/geomys/sandboxed-step/blob/v1.2.1/generate-config.go#L1232-L1269). After setup-go, the GOPATH bin added on the host is therefore dropped inside the sandbox, so this line and the same pattern in govulncheck-tests/the contrib script fail with govulncheck: command not found; invoke $(go env GOPATH)/bin/govulncheck, extend PATH inside the sandbox, or use go run.
Useful? React with 👍 / 👎.
| uses: geomys/[email protected] | ||
| with: | ||
| run: |- |
There was a problem hiding this comment.
Persist the SARIF output out of the sandbox
This step writes govulncheck.sarif inside geomys/sandboxed-step, but the following upload-sarif step runs back on the host and reads govulncheck.sarif from the workspace. The action documents that workspace changes do not persist by default and its default for persist-workspace-changes is false (https://raw.githubusercontent.com/geomys/sandboxed-step/v1.2.1/README.md), so once the command succeeds the report is discarded with the sandbox overlay and Code Scanning has no SARIF file to upload; set persist-workspace-changes: 'true' for this SARIF-producing step or copy the report out another way.
Useful? React with 👍 / 👎.
…andboxing Confines govulncheck execution using gVisor to prevent supply chain attacks from exfiltrating tokens or making network calls in CI. Any malicious code in a scanned dependency runs inside the sandbox with no ambient authority. This PR will fail CI: geomys/sandboxed-step is not in the DataDog enterprise action allowlist. It exists to start the discussion for adding it. See PR description for context. Ref: https://words.filippo.io/dependabot/ Ref: https://github.com/geomys/sandboxed-step Signed-off-by: Kemal Akkoyun <[email protected]>
643b259 to
2ab67a7
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 852852bc5b
ℹ️ 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".
| id: restore | ||
| if: always() | ||
| run: |- | ||
| git reset --hard HEAD |
There was a problem hiding this comment.
Reset to a trusted ref after the sandbox
Because persist-workspace-changes: 'true' lets the sandbox write the checkout, untrusted code can also rewrite .git/HEAD or refs before this host-side cleanup. git reset --hard HEAD then trusts that attacker-controlled ref, so the following local upload actions can run attacker-controlled .github/actions/... code with the Datadog/Codecov credentials; capture the checked-out SHA before entering the sandbox or re-checkout a fresh workspace before invoking credentialed/local actions.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 852852bc5b
ℹ️ 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".
| run: |- | ||
| export PATH="${{ github.workspace }}/bin:${PATH}" | ||
| ./scripts/ci_test_contrib.sh smoke ${{ toJson(matrix.chunk) }} | ||
| git reset --hard HEAD |
There was a problem hiding this comment.
Reset to a trusted ref after the sandbox
This go-get-u path persists the sandbox workspace, and the sandboxed-step README says following steps must treat that workspace as untrusted. When the sandboxed go get -u/tests can rewrite .git/HEAD and objects, git reset --hard HEAD resets to attacker-controlled content rather than the checked-out commit; the subsequent local ./.github/actions/dd-ci-upload and codecov-upload steps then run with Datadog/Codecov credentials. Capture the checked-out SHA before the sandbox and reset to that SHA, or use a fresh checkout before credentialed local actions.
Useful? React with 👍 / 👎.
`persist-workspace-changes: true` lets a sandboxed step write anywhere
in `${GITHUB_WORKSPACE}`, including `.git/HEAD`, `.git/refs/*`, and
tracked files such as `.github/actions/codecov-upload/action.yml`. The
previous post-sandbox `git reset --hard HEAD` therefore trusted whatever
the sandbox left behind, so a compromised dependency could backdoor the
local upload actions and exfiltrate `CODECOV_TOKEN` / Datadog API keys
once the host runner ran them.
Replace the `reset + clean` cleanup with a three-step sequence:
1. Capture `git rev-parse HEAD` to a step output before the sandbox runs.
2. After the sandbox, tar test results and coverage files into
`${RUNNER_TEMP}/sandbox-artifacts` (regular files only, so any
sandbox-planted symlinks are skipped).
3. Re-checkout the captured SHA with `actions/checkout … clean: true`,
then extract the artifacts back. The credentialed local actions
(`./.github/actions/dd-ci-upload`, `./.github/actions/codecov-upload`,
`DataDog/dd-sts-action`) keep their `steps.restore.outcome == 'success'`
gate, so they only run on a freshly-checked-out workspace.
Applied to:
- `.github/workflows/gotip-testing.yml` (`test-tip` job)
- `.github/workflows/smoke-tests.yml` (`go-get-u` job)
`govulncheck.yml` `govulncheck-contribs-analysis` also uses
`persist-workspace-changes`, but its only post-sandbox step is
`github/codeql-action/upload-sarif` (loaded from a pinned external
action, not the workspace) which only consumes the SARIF as data, so
it does not need the same hardening.
|
/merge |
|
View all feedbacks in Devflow UI.
The expected merge time in
|

What does this PR do?
Runs the highest-risk dependency/toolchain CI paths inside
geomys/sandboxed-step, pinned tov1.2.1's immutable SHA for the repo's SHA-pinning policy.Concretely, this PR:
golang/govulncheck-actionfor core SARIF analysis from chore(ci): govulncheck - use official golang/govulncheck-action for SARIF analysis #4599go get -u/ requestedgo-libddwafdependency upgrade compilation in a sandboxgo get -ubefore tests in a sandboxMotivation
go get -u,go install ...@latest,gotip download, and govulncheck all intentionally pull and execute code from outside this repository. That is exactly the class of CI work where sandboxing helps: it strips most of the ambient authority that a GitHub-hosted runner otherwise gives to dependency code.This builds on the checkout hardening already in the workflows (
persist-credentials: false) by also isolating the execution environment with gVisor.Notes on implementation
geomys/sandboxed-stepis pinned by commit SHA because this repository hassha_pinning_required: truefor GitHub Actions.persist-workspace-changes: 'true', then immediately rungit reset --hardandgit clean -fdxwith narrow exclusions for the required output files.${GITHUB_WORKSPACE}/bininside the sandbox so subsequent commands in the same sandboxed step can find them onPATH.Validation
Local:
make lint/actionmake -C .github/workflows test-apps.yml && git diff --exit-code -- .github/workflows/test-apps.ymlbash -n scripts/ci_test_contrib.sh scripts/ci_test_core.sh scripts/install_tools.sh scripts/lint.shgit diff --checkyqCI/manual runs:
go get -ucontrib smoke jobs.References
Reviewer's Checklist