GitHub Actions offer a powerful and flexible infrastructure for CI/CD, deployments and monitoring. But every external dependency we include opens a potential door for supply-chain attacks. One simple, effective, and low-cost way to seal that door is pinning your Actions to specific commit SHAs. In this article, we’ll explore the risks, walk through how to implement SHA pinning smoothly, and show you how to automate the process so you can keep everything under control without getting a headache.
Imagine this workflow step:
- uses: actions/checkout@v3
Today, that tag points to a secure commit, but tomorrow, someone could redefine it.
In an actual March 2025 attack, tj-actions/changed-files@v1
was hijacked to leak CI secrets and credentials into logs across 200+ repositories in minutes.
The lesson? Tags are mutable, and mutable means vulnerable. GitHub itself recommends always using a full-length commit SHA, which is immutable and can’t be changed retroactively.
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
That small change ensures your workflows run only the exact code you’ve audited.
The ideal workflow? Pin once, then automate updates.
SHA pinning is powerful, but true security is multi-layered. Consider adding:
ensure-sha-pinned-actions
in CI to immediately catch any mutable refsGITHUB_TOKEN
: Limit token scopes (e.g., contents: read
) and grant higher privileges only where strictly neededIf an Action does get compromised, these additional layers drastically limit what it can do.
name: CI Secure
on: push
permissions:
contents: read
id-token: write
jobs:
ensure-pinned:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- name: Verify SHA pinning
uses: zgosalvez/github-actions-ensure-sha-pinned-actions@fc87bb5b5a97953d987372e74478de634726b3e5
test:
runs-on: ubuntu-latest
needs: ensure-pinned
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- run: npm ci && npm test
This action first enforces SHA pinning and fails the pipeline if any mutable ref is found, and then runs only after pinning is verified, ensuring a known good base.
Pinning GitHub Actions to commit SHAs is a small change that yields enormous security benefits. It guarantees that only the code you’ve approved ever runs in your CI, closing the door on tag-tampering attacks. When combined with enforcement, least-privilege tokens, and strict allow-lists, you create a CI pipeline that’s both powerful and safe.
Did you find this article interesting? Are you an “under the hood” kind of person? We’re really big on automation and we’re always looking for people in a similar vein to fill roles like this one as well as other roles here at Würth Phoenix.