Skip to content

ci: pin actions to SHAs with version comments - #2

Open
GoldenSis wants to merge 1 commit into
seyedehsanhadi:mainfrom
GoldenSis:ci-pin-actions
Open

ci: pin actions to SHAs with version comments#2
GoldenSis wants to merge 1 commit into
seyedehsanhadi:mainfrom
GoldenSis:ci-pin-actions

Conversation

@GoldenSis

Copy link
Copy Markdown

What this does

Pins the three actions in .github/workflows/test.yml to full commit SHAs, each with the version comment so the release stays readable and Dependabot can still offer a bump.

actions/checkout@v4      ->  11d5960a326750d5838078e36cf38b85af677262  # v4.4.0
actions/setup-python@v5  ->  a26af69be951a213d495a4c3e4e4022e16d87065  # v5.6.0
actions/setup-node@v4    ->  49933ea5288caeca8642d1e84afbd3f7d6820020  # v4.4.0

Same major for each — v4 resolves to v4.4.0 today, so this is the tag you are already running, written down. No workflow logic changed.

Why

A floating tag is mutable. actions/checkout@v4 is whatever the v4 tag points at when the job starts, so what CI executes can change without any commit here. That is the supply-chain path behind GHSA-mrrh-fwg8-r2c3 (tj-actions/changed-files, 2025-03-15, high): tags were repointed at a malicious commit, and every workflow tracking a tag ran it on the next run and leaked secrets into its logs.

The version comment matters as much as the SHA. Without it a reader cannot tell what 11d5960a… is, and Dependabot's github-actions ecosystem needs the comment to know the current version before it can propose an update — a bare SHA is frozen rather than maintained.

Evidence

Every check in test.yml run locally on this branch, macOS / Python 3.13:

$ python -m pytest tests/ -q
119 passed in 13.81s

$ bash tests/test_hooks.sh
hook tests: 72 passed, 0 failed

$ python scripts/check_docs.py
  119 python tests, 72 hook checks, 191 together, doctor prints 4 [OK]
check_docs: 273 checks passed

$ actionlint
(exit 0)

$ pinact run --check --verify-comment --min-age 7 --verify-min-age
(exit 0)

zizmor .github/workflows/
  before: 5 findings (1 suppressed): 1 medium, 3 high
  after:  2 findings (1 suppressed): 1 medium, 0 high

The three high findings were the three unpinned-uses.

Generated with pinact run (v4.1.1) rather than by hand, and verified with --min-age 7 so no pin points at a release younger than a week.

One follow-up I left out

There is no .github/dependabot.yml. Adding one for the github-actions ecosystem would keep these pins moving on their own instead of ageing in place — happy to open it separately if you want it, but it is a different change and this PR is meant to be one thing.

Pin the three actions in test.yml to full commit SHAs with a version
comment, so the workflow is reproducible and Dependabot can still see
which release each pin corresponds to. Same major for each action --
no behaviour change:

  actions/checkout@v4      -> 11d5960a... # v4.4.0
  actions/setup-python@v5  -> a26af69b... # v5.6.0
  actions/setup-node@v4    -> 49933ea5... # v4.4.0

zizmor drops from 5 findings (3 high) to 2 (0 high).
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