Pin release-workflow actions to commit SHAs + least-privilege token#862
Merged
Conversation
Contributor
Greptile SummaryThis PR hardens the release workflow against action tag changes and excess token access. The main changes are:
Confidence Score: 5/5This looks safe to merge.
Important Files Changed
Reviews (2): Last reviewed commit: "Pin release-workflow actions to commit S..." | Re-trigger Greptile |
timhaines
force-pushed
the
sha-pin-actions
branch
from
July 23, 2026 06:21
b8cd554 to
f05a596
Compare
Every `uses:` in build-release.yml was a mutable tag; the `release` job has `contents: write` and publishes the binaries users install, so a compromised action could tamper the release. Action tag-hijacking keeps recurring (aquasecurity/trivy-action, 75 tags, Mar 2026 TeamPCP; tj-actions, 2025; codfish/semantic-release-action, Jun 2026) and SHA-pinned workflows were immune each time. Pin all six actions to the commit each @major resolves to today (concrete version in a trailing comment; setup-uv's annotated tag dereferenced to its commit, not the tag object, so Dependabot tracks it). Also add a top-level `permissions: contents: read` (the release job keeps its explicit write) and `persist-credentials: false` on the build checkout. actionlint passes. Pairs with usestrix#860 (Dependabot github-actions keeps the pins current). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
timhaines
force-pushed
the
sha-pin-actions
branch
from
July 23, 2026 06:27
f05a596 to
33c1219
Compare
Collaborator
Collaborator
|
thanks LGTM! @timhaines |
This was referenced Jul 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pins every third-party action in the release workflow to a full commit SHA (with the version in a trailing comment), and tightens the workflow's token permissions.
Why:
build-release.yml'sreleasejob hascontents: writeand publishes the binaries users install. Everyuses:there is a mutable tag (@v2,@v4, …), and tag-hijacking of popular actions keeps happening:aquasecurity/trivy-actionhad 75 of its 76 tags force-pushed to steal CI credentials (Mar 2026, part of the TeamPCP campaign), followingtj-actions/changed-files(2025) and beforecodfish/semantic-release-action(Jun 2026). In each case, workflows referencing the action by commit SHA were unaffected — a SHA is immutable, so pinning is the fix.Changes:
checkout,setup-python,setup-uv,upload-artifact,download-artifact,action-gh-release. Each is pinned to the commit its@majorresolves to today, so there's no version change — pure immutability — with the concrete version in a trailing comment. (setup-uv's@v5is an annotated tag; it's pinned to the underlying commit, not the tag object, so Dependabot tracks it correctly.)permissions: contents: read(thebuildjob only needs read; thereleasejob keeps its explicitcontents: write), andpersist-credentials: falseon the build checkout so theGITHUB_TOKENisn't left in.git/config.actionlintpasses, and each pin resolves to the current released version.Pairs with #860 — its
github-actionsDependabot entry keeps these SHAs current (bumping the SHA + comment), so pinning doesn't leave them to go stale.