Your CI/CD pipeline relies on trust. Each time a workflow runs, it pulls actions by tags like v1.29.5, v5, or latest. These tags point to code that might change between runs. A compromised maintainer account, a forced push, or a tag reassignment can turn your trusted automation into a vulnerability.
The solution is clear: pin actions to commit SHAs instead of mutable tags. Tags can change, but SHAs are fixed. However, this approach introduces challenges. SHA-pinned workflows are harder to read, update, and explain to teams unfamiliar with 40-character hex strings in YAML files.
So, should you pin? While SHA pinning undeniably boosts security, the real question is whether the operational cost is justified for your environment.
The Case for SHA Pinning
Pinning actions to SHAs is a key strategy in supply chain threat modeling. When you reference actions/checkout@v4, you're trusting the maintainer not to alter what v4 points to. You're also trusting GitHub's infrastructure, the maintainer's credentials, and every dependency in the action's supply chain.
This is a lot of trust for a system with write access to your repository, secrets, and deployment infrastructure.
SHA pinning disrupts this trust chain. By using actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab, you're pointing to immutable content. An attacker can't change what that SHA points to without compromising GitHub's object store, a much tougher target.
This is especially crucial for third-party actions. You didn't create them, don't control their release process, and might not monitor their repositories for suspicious activity. Pinning to SHAs ensures a compromised maintainer can't silently inject malicious code by retagging a release.
Operationally, SHA pinning provides deterministic builds. The same workflow will run the same code months later, regardless of upstream changes. This is valuable for compliance audits, incident response, and reproducibility.
The Case Against SHA Pinning
The downside isn't about security; it's about the workflow burden that makes teams avoid it.
First, readability suffers. A 40-character SHA doesn't indicate the version you're running. You can add comments like # v1.29.5, but then you're maintaining two references that can drift. Tools like Dependabot can update the SHA but may leave the comment outdated, leading to confusion.
Second, update speed decreases. With tags, dependency bots can propose updates automatically. With SHAs, you need tools to resolve tags to SHAs, check for new releases, and create pull requests with the new SHA and a readable reference. Not all teams have this tooling.
Third, there's the initial setup challenge. Adopting SHA pinning mid-project means resolving every tag to its current SHA, verifying those SHAs, and documenting your choices. For a repository with numerous workflows and action references, this can be a significant effort.
Finally, consider the scope. Should you pin first-party actions like actions/checkout? These are maintained by GitHub with presumably strong security controls. The risk is different from a third-party action maintained by a solo developer. Pinning everything maximizes security but also increases maintenance.
Where Teams Actually Land
Most teams use a tiered approach. They pin third-party actions, anything outside the actions/* namespace, and leave first-party actions on tags. This balances risk and maintenance, protecting against likely threats while keeping frequently updated actions manageable.
Some teams maintain an allowlist, pinning everything except trusted, frequently-updated actions. Others pin everything and invest in automation tools like Ghapin to resolve tags to SHAs in bulk and keep comments synchronized.
Teams that don't pin usually haven't threat-modeled their pipeline or have decided the risk is acceptable. If your workflows don't handle secrets, deploy to production, or write back to the repository, the impact of a compromised action is limited.
Our Take
Pin third-party actions. Skip first-party actions unless your threat model requires it.
The attack surface is real. Supply chain compromises have occurred in npm, PyPI, and Docker Hub. GitHub Actions repositories are also targets, and the consequences of a compromised action, credential theft, malicious commits, lateral movement into production systems, justify the workflow overhead.
Use tools to make it manageable. Ghapin and similar utilities can resolve tags to SHAs in bulk, update workflows, and preserve the original tag as a comment. While comments may drift, they're more helpful than a bare SHA when reviewing workflows later.
Document your pinning policy in your TPRM runbooks. Clearly state which actions are pinned and why. Pin new actions before production use. When Dependabot flags an update, verify the new SHA matches the expected release before merging.
If you haven't started pinning, begin with your most critical workflows, those that deploy to production, access cloud credentials, or write to your main branch. You don't need to pin everything immediately, just the areas where a supply chain compromise would be most damaging.





