In GitHub Actions, commit hash/SHA pinning is considered a security best-practice. It makes your actions immutable, unlike the contents of version tags which can be overwritten.
The topic’s been trending recently, after an action used by 23k repositories was compromised.
When I explored implementing it at work, however, I discovered several trade-offs that made me question its practical value.
(I’ll focus on the perspective of large enterprises; most startups aren’t losing sleep over supply chain risks)
Should be quick: famous last words
A typical engineering team can easily end up adding over 50 actions in their workflows. Checkout code, security scans, quality checks, builds, artifact management, notifications, multiple environments to deploy to, multiple services to maintain…the list goes on!
You have to manage upgrades for all of them. And you have to do it responsibly, by manually verifying that the latest commit hash doesn’t include a compromise.
You might argue this is easy, since you’re a conscientious developer. Such vigilance doesn’t scale though; tight deadlines, offshoring, complex workflows, even plain boredom, will all lead to exploits slipping through.
What about automation?
A valid question
One might be tempted to propose this solution…
- Set Dependabot Version Updates to auto-raise PRs
- Create workflow that auto-merges those PRs
Hands-free baby! Well, wait a second - that’s effectively equivalent to using version releases. You’re still picking up whatever the maintainer ships.
I’m worse off now!?
Dependabot Security Alerts only works on actions pinned with version tags. So your security posture could actually weaken if you move to commit hashes.
From the horse’s mouth
Let’s say you only use actions from well-known maintainers - AWS, for example. Now assess these 2 scenarios:
- Hacker takes over AWS’ GitHub account and manages to introduce a malicious commit in an action
- A high-severity CVE is published on an AWS action, requiring people to upgrade immediately
Which one is more common? I’d argue for the second, by far.
Great progress! Now start again
GitHub is trialing immutable actions with maintainers. Probably to address the shortcomings with commit hashes.
Immutable Actions invitation
Knowing that, should an organisation spend all that effort, knowing they may need to move to yet another solution? We’re not talking just about implementation costs by the way; the security team needs to handle comms, and monitor compliance.
Alternative #1
Stick to using version tags with well-established maintainers (AWS, Slack, HashiCorp, etc.), and avoid actions from unknown or individual authors. If the latter are needed, create an internal version within your organization (while respecting license terms). Last option is to use the commit hash just on those actions; but beware of the toil.
(Want me to write an action that helps with that? Let me know!)
Alternative #2
Follow these steps:
- create an internal repo
- write actions that are just wrappers of the external actions
- pin those external actions by commit hash
- in your workflows, replace the external actions with the internal wrappers
- pin the internal actions either by branch name, or by version if you wanna be fancy
- wonder if you were better off sticking with a Jenkins box - I’m (half-)kidding!
This way, you don’t need to hunt down hash updates across all the repositories. You can then dump this beauty on your friendly DevOps team (or whatever we’re calling them these days).
The company that spotted the tj-actions compromise offers an outsourced version of that. I need my affiliate commission!!
TLDR Verdict
Commit hash pinning is a pain. Simply sticking with version tags from reputable maintainers can be a pragmatic choice. If you do need to comply, wrap the actions in a central repo that propagates to everyone else.