Skip to content

ci: sandbox govulncheck and latest-dependency smoke tests#4598

Merged
gh-worker-dd-mergequeue-cf854d[bot] merged 9 commits into
mainfrom
kakkoyun/govulncheck-sandboxed-step
May 12, 2026
Merged

ci: sandbox govulncheck and latest-dependency smoke tests#4598
gh-worker-dd-mergequeue-cf854d[bot] merged 9 commits into
mainfrom
kakkoyun/govulncheck-sandboxed-step

Conversation

@kakkoyun

@kakkoyun kakkoyun commented Mar 25, 2026

Copy link
Copy Markdown
Member

What does this PR do?

Runs the highest-risk dependency/toolchain CI paths inside geomys/sandboxed-step, pinned to v1.2.1's immutable SHA for the repo's SHA-pinning policy.

Concretely, this PR:

  • wraps blocking govulncheck execution in a gVisor sandbox
  • adds sandboxed contrib-module SARIF generation for GitHub Code Scanning
  • keeps the official golang/govulncheck-action for core SARIF analysis from chore(ci): govulncheck - use official golang/govulncheck-action for SARIF analysis #4599
  • wraps smoke-test go get -u / requested go-libddwaf dependency upgrade compilation in a sandbox
  • wraps contrib smoke tests that run go get -u before tests in a sandbox
  • wraps gotip testing, where CI downloads and runs the latest Go toolchain, in a sandbox
  • restores/cleans workspaces after sandboxed steps before any upload/token-consuming follow-up steps, preserving only required reports, coverage, or SARIF artifacts

Motivation

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-step is pinned by commit SHA because this repository has sha_pinning_required: true for GitHub Actions.
  • Steps that need artifacts after sandbox execution use persist-workspace-changes: 'true', then immediately run git reset --hard and git clean -fdx with narrow exclusions for the required output files.
  • Govulncheck tools are installed into ${GITHUB_WORKSPACE}/bin inside the sandbox so subsequent commands in the same sandboxed step can find them on PATH.

Validation

Local:

  • make lint/action
  • make -C .github/workflows test-apps.yml && git diff --exit-code -- .github/workflows/test-apps.yml
  • bash -n scripts/ci_test_contrib.sh scripts/ci_test_core.sh scripts/install_tools.sh scripts/lint.sh
  • git diff --check
  • YAML parse checks with yq

CI/manual runs:

  • Manual Govulncheck run passed after verifying sandbox logs, SARIF preservation, and Code Scanning upload.
  • Manual Smoke Tests run passed, including sandboxed updated-dependency compile and sandboxed go get -u contrib smoke jobs.
  • Manual Gotip Testing run passed, including sandboxed gotip download/test execution.
  • Latest PR GitHub checks show no failures; only external GitLab benchmark/mergegate aggregate checks were still pending at last inspection.

References

Reviewer's Checklist

  • N/A — CI/workflow-only change, no Go code modified

@codecov

codecov Bot commented Mar 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 62.46%. Comparing base (5fd6d9c) to head (f773ab6).

Additional details and impacted files

see 444 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-prod-us1-6

datadog-prod-us1-6 Bot commented Mar 25, 2026

Copy link
Copy Markdown

Tests

🎉 All green!

❄️ No new flaky tests detected
🧪 All tests passed

🎯 Code Coverage (details)
Patch Coverage: 100.00%
Overall Coverage: 61.80% (+4.01%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: f773ab6 | Docs | Datadog PR Page | Give us feedback!

@kakkoyun kakkoyun changed the title ci(govulncheck): add gVisor sandboxing via geomys/sandboxed-step feat(ci): govulncheck - add gVisor sandboxing via geomys/sandboxed-step Mar 25, 2026
@kakkoyun kakkoyun added the AI Assisted AI/LLM assistance used in this PR (partially or fully) label Mar 25, 2026
@pr-commenter

pr-commenter Bot commented Mar 25, 2026

Copy link
Copy Markdown

Benchmarks

Benchmark execution time: 2026-05-12 16:18:19

Comparing candidate commit f773ab6 in PR branch kakkoyun/govulncheck-sandboxed-step with baseline commit 5fd6d9c in branch main.

Found 0 performance improvements and 0 performance regressions! Performance is the same for 273 metrics, 2 unstable metrics, 1 flaky benchmarks without significant changes.

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 ----------------------------------'

Known flaky benchmarks

These benchmarks are marked as flaky and will not trigger a failure. Modify FLAKY_BENCHMARKS_REGEX to control which benchmarks are marked as flaky.

Known flaky benchmarks without significant changes:

  • scenario:BenchmarkOTLPTraceWriterFlush

@kakkoyun
kakkoyun force-pushed the kakkoyun/govulncheck-persist-credentials branch from 34af022 to 31f8814 Compare March 26, 2026 10:07
@kakkoyun
kakkoyun force-pushed the kakkoyun/govulncheck-sandboxed-step branch from 42b3d61 to f5cf6b9 Compare March 26, 2026 10:10
Base automatically changed from kakkoyun/govulncheck-persist-credentials to kakkoyun/govulncheck March 27, 2026 10:53
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
@kakkoyun
kakkoyun force-pushed the kakkoyun/govulncheck-sandboxed-step branch from f5cf6b9 to aa79d34 Compare March 27, 2026 11:13
Base automatically changed from kakkoyun/govulncheck to main March 27, 2026 11:49
@kakkoyun
kakkoyun force-pushed the kakkoyun/govulncheck-sandboxed-step branch 3 times, most recently from a21d539 to 2318e49 Compare April 23, 2026 08:57
@kakkoyun

Copy link
Copy Markdown
Member Author

@codex review

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

Copy link
Copy Markdown

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

Comment thread .github/workflows/govulncheck.yml Outdated
Comment on lines +69 to +70
go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck -format sarif \

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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

Comment thread .github/workflows/govulncheck.yml Outdated
Comment on lines +66 to +68
uses: geomys/[email protected]
with:
run: |-

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 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]>
@kakkoyun
kakkoyun force-pushed the kakkoyun/govulncheck-sandboxed-step branch from 643b259 to 2ab67a7 Compare April 29, 2026 07:55
@kakkoyun

Copy link
Copy Markdown
Member Author

@codex review

@kakkoyun kakkoyun changed the title feat(ci): govulncheck - add gVisor sandboxing via geomys/sandboxed-step ci: sandbox govulncheck and latest-dependency smoke tests Apr 29, 2026

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

Copy link
Copy Markdown

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

Comment thread .github/workflows/gotip-testing.yml Outdated
id: restore
if: always()
run: |-
git reset --hard HEAD

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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

@kakkoyun
kakkoyun marked this pull request as ready for review April 29, 2026 09:52
@kakkoyun
kakkoyun requested a review from a team as a code owner April 29, 2026 09:52

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

Copy link
Copy Markdown

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

Comment thread .github/workflows/smoke-tests.yml Outdated
run: |-
export PATH="${{ github.workspace }}/bin:${PATH}"
./scripts/ci_test_contrib.sh smoke ${{ toJson(matrix.chunk) }}
git reset --hard HEAD

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge 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.

@darccio darccio left a comment

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.

Nice work!

@darccio

darccio commented May 12, 2026

Copy link
Copy Markdown
Member

/merge

@gh-worker-devflow-routing-ef8351

gh-worker-devflow-routing-ef8351 Bot commented May 12, 2026

Copy link
Copy Markdown

View all feedbacks in Devflow UI.

2026-05-12 17:49:42 UTC ℹ️ Start processing command /merge


2026-05-12 17:49:47 UTC ℹ️ MergeQueue: pull request added to the queue

The expected merge time in main is approximately 15m (p90).


2026-05-12 18:03:34 UTC ℹ️ MergeQueue: This merge request was merged

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