Skip to content

ci: pin github actions to commit shas - #1040

Open
Totara-thib wants to merge 2 commits into
visgl:mainfrom
Totara-thib:ci-hardening
Open

ci: pin github actions to commit shas#1040
Totara-thib wants to merge 2 commits into
visgl:mainfrom
Totara-thib:ci-hardening

Conversation

@Totara-thib

Copy link
Copy Markdown

Hi, drive-by CI hardening in two commits, one logical change each.

Commit 1 pins every action to its commit sha, versions kept as comments. A tag like @v4 is a movable pointer: whoever controls the action, or anyone who compromises it, can re-point it and your next run executes their code with the job's token. The sensitive spot here is release.yml, where release-please and the npm publish jobs run with your release credentials. Same pattern as the tj-actions/changed-files incident (CVE-2025-30066). Release-please itself is unaffected, it reads commits, not action refs. If you later want the pins bumped automatically, adding a github-actions ecosystem to your dependabot config does it, one small block.

Commit 2 adds permissions: contents: read to the two test workflows that had none. The scope is exact, not guessed: both only check out and build, the website build reads its Maps API key from a dedicated secret and the GitHub token is unused. The deploy and release workflows already declare scoped permissions and are untouched.

One heads up: if the org uses an Actions allowlist in settings, patterns written against tags (like owner/action@v4) stop matching once refs are shas and workflows refuse to start. Entries need to be owner/action@* in that case.

All shas were resolved from the upstream repos and cross checked against their release tags. No workflow logic changes.

Found with the Plumber CLI (https://github.com/getplumber/plumber), verified on main. I will also open a PR which adds it to CI so this does not quietly drift back, that one is a bonus, this PR stands on its own.

Mutable tags are movable pointers: whoever controls an action, or
anyone who compromises it, can re-point the tag and the next run
executes unreviewed code with the job's token. The sensitive spot
here is release.yml, where release-please and the publish jobs run
with release credentials. Same pattern as the tj-actions/changed-files
incident (CVE-2025-30066).

Pinning to the full commit sha freezes what runs; the version each
sha corresponds to stays as a comment. Every sha was resolved from
the upstream repository and cross-checked against its release tag.
No workflow logic changes.
Without a permissions block, the test jobs' GITHUB_TOKEN inherits
the repository default scope. Both only check out and build (the
website build reads its API key from a dedicated secret, the GitHub
token is unused), so they get contents read. The deploy and release
workflows already declare scoped permissions and are untouched.
@Totara-thib Totara-thib changed the title Ci hardening ci: pin github actions to commit shas Aug 3, 2026
@usefulthink

Copy link
Copy Markdown
Collaborator

Thanks for spending time on this!

To be honest, I don't quite see the benefit of this – it's not like we're using actions from untrusted sources. If I didn't trust the GitHub or the googleapis teams to have their security and supply chains in order, we probably wouldn't even use those actions.
It seems to me that pinning the versions of the official actions probably only creates more potential problems by missing security updates, bugfixes, etc.

@Totara-thib

Copy link
Copy Markdown
Author

Thanks for spending time on this!

To be honest, I don't quite see the benefit of this – it's not like we're using actions from untrusted sources. If I didn't trust the GitHub or the googleapis teams to have their security and supply chains in order, we probably wouldn't even use those actions. It seems to me that pinning the versions of the official actions probably only creates more potential problems by missing security updates, bugfixes, etc.

Fair question, and I agree on the premise: googleapis and GitHub are trustworthy teams. Pinning is not about distrusting them though, it is about what a tag can do without their consent.

A tag is mutable infrastructure. In the tj-actions incident the maintainers were not malicious and the project was widely trusted: an attacker got hold of a token and re-pointed every existing version tag to malicious code, so every repo that referenced a "trusted" tag ran it on their next build. Trust in the team does not survive a compromise of the team's account or release infra, and that is the exact case a sha pin neutralizes. The same class of thing has hit other reputable projects (reviewdog's actions, the codecov uploader).

The spot that made me open this PR is release-please-action specifically: it runs in the workflow that holds your npm publish credentials, and it is a third party relative to this repo regardless of how solid Google's teams are.

On missing updates: that is what the version comments are for. With a github-actions block in dependabot (one small addition, happy to include it here), every new release still arrives as a bump PR, same cadence as tags, except each change is visible and reviewable instead of applied silently. Pins do not slow security fixes down; a moved tag is how the opposite happens.

If you want a smaller change: keep the actions/* first-party refs on tags and pin only release-please. That covers the actual exposure and cuts the diff to a few lines. Also fine to close if you would rather not, no hard feelings.

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