Skip to content

ci: pin govulncheck and narrow release workflow permissions#22

Open
chethanuk wants to merge 1 commit into
mainfrom
ci/pin-and-permissions
Open

ci: pin govulncheck and narrow release workflow permissions#22
chethanuk wants to merge 1 commit into
mainfrom
ci/pin-and-permissions

Conversation

@chethanuk

@chethanuk chethanuk commented Jul 21, 2026

Copy link
Copy Markdown
Owner

Description

Two independent hardening changes to the release/CI workflows, two lines total.

1. Pin govulncheck — for reproducibility, not supply chain

ci.yml:33 runs go install golang.org/x/vuln/cmd/govulncheck@latest.

I want to be careful about the argument here, because the obvious one is wrong. This is not
"executing unpinned third-party code" — golang.org/x/vuln is the Go team's own module, and
go install is already checksum-verified through GOSUMDB. Framing it as supply chain would be
overselling it.

The real cost of @latest is reproducibility: a new govulncheck release can turn CI red on
an unchanged tree, with nothing in the repo having moved. That's the framing grafana/tempo
uses verbatim:

"Pinned rather than @latest so the gate is reproducible and an upstream release can't
silently change CI behavior."

And this gate is load-bearing, not decorative. e6e5da0"ci: bump Go image to 1.26.5 to
fix GO-2026-5856 govulncheck failure"
— is a real vulnerability this scanner caught in the Go
standard library, which forced a toolchain bump. Protecting a gate you already rely on from
unrelated churn seems worth one line.

Pinning costs nothing in scan freshness, which is the objection I'd expect. The vulnerability
database is fetched at runtime, independently of the binary version. Verified on Go 1.26.5:

$ govulncheck -version
Go: go1.26.5
Scanner: govulncheck@v1.6.0
DB: https://vuln.go.dev
DB updated: 2026-07-08 17:05:00 +0000 UTC

$ govulncheck ./...
No vulnerabilities found.        exit 0

The DB updated: line is the proof — a pinned v1.6.0 binary still pulled a database from six
days prior. v1.6.0 is the current release, re-resolved at ship time via
git ls-remote --tags https://go.googlesource.com/vuln rather than taken from notes.

Peers: grafana/tempo, k3s-io/k3s, google/trillian, redis/go-redis, lightningnetwork/lnd.

2. Narrow release.yml workflow-level permissions

release.yml:7-8 grants workflow-level contents: write. Only one job actually inherits it, and
that job never writes. Traced all three:

Job Job-level permissions: What it needs Effect of narrowing
build (:11) none — inherits checkout (read); upload-artifact@v4 authenticates with ACTIONS_RUNTIME_TOKEN, not GITHUB_TOKEN the only affected job — and it never writes, so: safe
release (:59) :62-65 contents: write, id-token: write, attestations: write gh-release needs write; attestation needs id-token + attestations unaffected
npm-publish (:161) :167-168 contents: read checkout; npm auth is secrets.NPM_TOKEN unaffected

Job-level permissions: replaces the inherited set entirely, so release and npm-publish
are already fully insulated from the workflow-level value today. Narrowing is a strict no-op for
them, and drops an unused write grant from build.

I verified build directly rather than reasoning about it: lines 11-57 contain only
actions/checkout@v4 and actions/upload-artifact@v4, with no GITHUB_TOKEN reference and no
gh invocation anywhere.

Permission matrix re-read from the parsed YAML after the edit:

workflow-level: {'contents': 'read'}
 job build      -> INHERITS
 job release    -> {'contents': 'write', 'id-token': 'write', 'attestations': 'write'}
 job npm-publish-> {'contents': 'read'}

Deliberately NOT included: pinning softprops/action-gh-release

This repo uses exactly one third-party action, softprops/action-gh-release@v2 at
release.yml:145, in a job holding contents: write + id-token: write — so SHA-pinning it is
a reasonable thing to want, and it's the compromise class that hit tj-actions/changed-files.

I left it alone on purpose. Open dependabot PR alibaba#347 proposes moving that exact line to @v3.
Pinning it to a v2 SHA underneath that would create a direct textual conflict and pin an
about-to-be-obsolete major. Pinning should follow that decision, not pre-empt it — happy to send
it as a follow-up once alibaba#347 is resolved either way. The diff touches zero softprops lines.

Verification

  • actionlint v1.7.12 — exit 0 across all four workflows
  • govulncheck@v1.6.0 installed, reported its version, and scanned the tree clean (above)
  • Permission matrix asserted from parsed YAML after the edit, not eyeballed
  • git diff origin/main -- .github/workflows/release.yml | grep -c softprops0
  • yaml.safe_load on both changed files

Limitations

  • The permission narrowing cannot be proven by this PR's checks. release.yml only fires on
    push: tags: ['v*'], so the first real exercise is the next release. The evidence is the
    traced matrix above plus the fact that job-level blocks already override the workflow-level
    value for the two jobs that need write.
  • I did not run a real release. If build ever gains a step that writes via GITHUB_TOKEN, it
    would need its own job-level block — worth knowing, though nothing in it does today.
  • v1.6.0 is current as of this PR; the pin will need a bump eventually. Dependabot's
    github-actions ecosystem does not cover go install lines, so this one is manual — that's a
    genuine (small) cost of pinning and I'd rather state it than skip it.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Refactoring (no functional changes)
  • Documentation update
  • CI / Build / Tooling

How Has This Been Tested?

  • Installed govulncheck@v1.6.0, confirmed Scanner: govulncheck@v1.6.0, a runtime-fetched
    DB updated: 2026-07-08, and No vulnerabilities found. with exit 0
  • Re-resolved the current govulncheck release at ship time rather than trusting earlier notes
  • Traced and asserted the full three-job permission matrix after the edit
  • Confirmed build contains no GITHUB_TOKEN or gh usage
  • Confirmed zero softprops lines in the diff (no conflict with chore(deps): bump the actions group across 1 directory with 9 updates alibaba/open-code-review#347)
  • actionlint v1.7.12 — exit 0

Checklist

  • My code follows the project's coding style
  • I have performed a self-review of my code
  • I have added tests that prove my fix is effective — n/a, workflow config
  • New and existing unit tests pass locally with my changes
  • I have updated the documentation accordingly (not applicable)
  • I have signed the CLA

AI assistance: Claude Code helped research and verify this change. I reviewed the full diff
and take responsibility for it.

Summary by CodeRabbit

  • Chores
    • Improved release workflow security by reducing repository content permissions to read-only.
    • Updated vulnerability scanning in CI to use a pinned version, ensuring more consistent and reproducible checks across runs.

@gemini-code-assist

Copy link
Copy Markdown

Note

Gemini is unable to generate a review for this pull request due to the file types involved not being currently supported.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0476a971-bcf5-4097-8056-c75132a70a19

📥 Commits

Reviewing files that changed from the base of the PR and between ce53df5 and 4c0af22.

📒 Files selected for processing (2)
  • .github/workflows/ci.yml
  • .github/workflows/release.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/ci.yml

📝 Walkthrough

Walkthrough

CI Govulncheck installation is pinned to v1.6.0, and the release workflow now uses read-only contents permission.

Changes

Workflow hardening

Layer / File(s) Summary
Pin vulnerability scanner
.github/workflows/ci.yml
Govulncheck installation changes from latest to v1.6.0.
Harden release workflow
.github/workflows/release.yml
Release contents permission changes from write to read.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Suggested reviewers: lizhengfeng101, stay-foolish-forever

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the two main CI hardening changes: pinning govulncheck and narrowing release workflow permissions.
Description check ✅ Passed The description follows the template and includes purpose, change type, testing, checklist, and related issues sections with sufficient detail.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/pin-and-permissions

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Checkov (3.3.8)
.github/workflows/ci.yml

Traceback (most recent call last):
File "/usr/local/bin/checkov", line 2, in
from checkov.main import Checkov
ModuleNotFoundError: No module named 'checkov'

.github/workflows/release.yml

Traceback (most recent call last):
File "/usr/local/bin/checkov", line 2, in
from checkov.main import Checkov
ModuleNotFoundError: No module named 'checkov'


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chethanuk

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@chethanuk
chethanuk force-pushed the ci/pin-and-permissions branch 2 times, most recently from ce53df5 to 1510512 Compare July 21, 2026 15:12
@chethanuk

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Pin govulncheck to v1.6.0 instead of @latest. The argument is
reproducibility, not supply chain: golang.org/x/vuln is the Go team's
own module and go install is already checksum-verified via GOSUMDB.
What @latest costs is a new govulncheck release turning CI red on an
unchanged tree. This gate is load-bearing - e6e5da0 bumped the Go image
to fix GO-2026-5856 after govulncheck caught it - so protecting it from
unrelated churn is worth a pin.

Pinning costs nothing in scan freshness: the vulnerability database is
fetched at runtime, independently of the binary version. Verified:
Scanner govulncheck@v1.6.0, DB updated 2026-07-08, no vulnerabilities,
exit 0.

Narrow release.yml's workflow-level permissions from contents: write to
contents: read. Only the build job inherits it, and it only checks out
and uploads artifacts - upload-artifact authenticates with
ACTIONS_RUNTIME_TOKEN, not GITHUB_TOKEN. The release and npm-publish
jobs declare their own job-level permissions, which replace the
inherited set entirely, so both are unaffected.

Verified with actionlint (clean across all workflows) and by confirming
the release.yml still parses as YAML.
@chethanuk
chethanuk force-pushed the ci/pin-and-permissions branch from 1510512 to 4c0af22 Compare July 22, 2026 19:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant