Skip to content

ci: pin govulncheck, narrow release permissions#436

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

ci: pin govulncheck, narrow release permissions#436
chethanuk wants to merge 1 commit into
alibaba:mainfrom
chethanuk:ci/pin-and-permissions

Conversation

@chethanuk

@chethanuk chethanuk commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Description

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

The second is the project's own documented review rule rather than my preference.
internal/config/rules/rule_docs/github_workflows.md:4 says each job "should declare only the
permissions it needs". This PR applies that to the repo's own release workflow.

1. Pin govulncheck — for reproducibility, not supply chain

ci.yml:33 runs go install golang.org/x/vuln/cmd/govulncheck@latest, so a new govulncheck
release can turn CI red on an unchanged tree. The gate is real: e6e5da0 ("ci: bump Go image to
1.26.5 to fix GO-2026-5856 govulncheck failure"
) is a stdlib vulnerability it caught. The
vulnerability database is fetched at runtime, independently of the binary version, so pinning
does not stale the scan — a pinned v1.6.0 binary reported DB updated: 2026-07-08,
No vulnerabilities found., exit 0.

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 (:58) :61-64 contents: write, id-token: write, attestations: write gh-release needs write; attestation needs id-token + attestations unaffected
npm-publish (:159) :164-165 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 today. Narrowing is a strict no-op for them, and drops an unused
write grant from build, whose lines 11-57 contain only actions/checkout@v4 and
actions/upload-artifact@v4 — no GITHUB_TOKEN, no gh.

Verification

actionlint v1.7.12 exit 0 across all four workflows, and yaml.safe_load on both changed
files. The permission matrix above was asserted from the parsed YAML after the edit, not eyeballed.

Limitations

release.yml only fires on push: tags: ['v*'], so the permission narrowing cannot be proven by
this PR's checks — the first real exercise is the next release, and the evidence is the traced
matrix above. If build ever gains a step that writes via GITHUB_TOKEN it will need its own
job-level block. Dependabot's github-actions ecosystem does not cover go install lines, so
bumping the govulncheck pin stays manual.

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

@github-actions

Copy link
Copy Markdown
Contributor

OpenCodeReview: No comments generated. Looks good to me.

@lizhengfeng101

Copy link
Copy Markdown
Collaborator

Thanks for the thorough analysis and detailed PR description.

Changes 1 & 2 (pin govulncheck + narrow permissions) look good — the govulncheck pin addresses a real stability issue (cf. e6e5da0), and the permission narrowing follows least-privilege with no behavioral change since release and npm-publish already declare their own job-level permissions.

For change 3 (SHA-pin action-gh-release): could you drop this one? The maintenance overhead (manual SHA lookups on every bump, less readable diffs) outweighs the security benefit here — the job already has scoped permissions limiting blast radius, and it conflicts with the pending dependabot PR #347. Happy to merge the other two as-is.

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
@chethanuk chethanuk changed the title ci: pin govulncheck, narrow release permissions, SHA-pin gh-release ci: pin govulncheck, narrow release permissions Jul 22, 2026
@chethanuk

Copy link
Copy Markdown
Contributor Author

Dropped change 3. Force-pushed 4c0af22: now just the govulncheck pin and the permission narrowing, and I've retitled and trimmed the description to match. #347 can carry the softprops pin.

actionlint is clean and the two remaining hunks are unchanged. Ready when you are.

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.

2 participants