Harden CI: pin release-pipeline actions to commit SHAs - #5281
Merged
Conversation
Pins every third-party action in the four release/publish workflows (publish, release-on-merge, release-canary, desktop-artifacts) to a full 40-character commit SHA with the semver it came from in a trailing comment. 25 uses: lines, no version changes, no permission changes. Includes pypa/gh-action-pypi-publish, which was on the moving release/v1 branch despite holding PyPI publish rights. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K754j6t7Lvc2aLTJtnC3G4
✅ Drift Bot (ClawMetry): no drift detectedDrift Bot analyzed the changed files against this project's blueprints and requirements and found no drift. |
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.
Addresses the Scorecard PinnedDependencies findings for the four workflows that build, sign and publish releases.
What this does
Every third-party action referenced by
publish.yml,release-on-merge.yml,release-canary.ymlanddesktop-artifacts.ymlnow resolves to a full 40-character commit SHA, with the semver it came from in a trailing comment:actions/checkout3d3c42e5aac5ba805825da76410c181273ba90b1actions/setup-python5fda3b95a4ea91299a34e894583c3862153e4b97actions/setup-node820762786026740c76f36085b0efc47a31fe5020actions/upload-artifactea165f8d65b6e75b540449e92b4886f43607fa02actions/download-artifactd3f86a106a0bac45b974a628896c90dbdf5c8093actions/attest-build-provenance96278af6caaf10aea03fd8d33a09a777ca52d62fpypa/gh-action-pypi-publishdc37677b2e1c63e2034f94d8a5b11f265b73ba33azure/login7184910d9eb2b1c5e48f7073824a90609bb9b6d6softprops/action-gh-release3bb12739c298aeb8a4eeaf626c5b8d85266b0e65Why this batch, and why it matters more than the others
A version tag is mutable:
actions/checkout@v7is whateverv7points at the next time a runner resolves it. Pinning to a commit fixes what runs in CI in this repository's own history.These four workflows are where that matters most, because they are the ones holding real authority — this is the pipeline that pushes to PyPI, signs the macOS and Windows desktop builds, and publishes GitHub releases.
Two references in particular:
pypa/gh-action-pypi-publish@release/v1was pointing at a branch, not even a tag — a ref designed to move — while being the step that authenticates to PyPI via Trusted Publishing. It is now pinned todc37677b, the commitrelease/v1resolves to today, which is exactly v1.14.2.azure/login@v2andsoftprops/action-gh-release@v2hold the Azure code-signing OIDC credential and the release-publishing token respectively.A note on annotated tags
Three of these actions publish annotated tags, where
refs/tags/vX.Y.Znames a tag object rather than a commit.uses:resolves against commits, so the tag-object SHA would fail at "Set up job". Each ref was peeled (refs/tags/vX.Y.Z^{}) and the commit SHA pinned:actions/attest-build-provenancev3.2.062fc1d59…96278af6…azure/loginv2.3.12035af27…7184910d…pypa/gh-action-pypi-publishv1.14.2a892a5a6…dc37677b…Scope
Pins only — no version changes, no permission changes. Each action was pinned to the latest patch within the major tag it already used, so
upload-artifact@v4stays on v4 rather than being pulled up to the v7 used inci.yml. This is a supply-chain fix, not an upgrade; mixing the two would make a CI regression much harder to bisect. Dependabot's opengithub-actionsPRs still propose those major bumps separately.No
permissions:block is touched. The write scopes these workflows need (contents: write,id-token: write,attestations: write) are untouched from #5250/#5253.Verification
python3 -c "import yaml,glob; [yaml.safe_load(open(f)) for f in glob.glob('.github/workflows/*.yml')]"— OK.python3 scripts/check_action_refs.py— OK (23 distinct references, offline shape checks pass). The live resolution runs insupply-chain.yml.git ls-remote, not from memory.uses:line — no structural, job, or permission changes.uses:reference remains in these four files.Notes
supply-chain.ymlis covered by Harden CI: pin supply-chain.yml actions to commit SHAs #5276 and the conformance/install/handoff family by Harden CI: pin conformance/install/handoff workflow actions to commit SHAs #5279; the rest of the ~117 unpinned references are follow-up batches..github/, so the product-record gate does not apply.No-PRD: CI/supply-chain hardening confined to
.github/; no product surface changes.Generated by Claude Code