GitHub Actions SHA Pinning, Org-Wide | Semgrep | Semgrep
Ready to move off legacy AppSec? The New Shift Program helps you switch from Checkmarx or Snyk.
Products
Semgrep Code<br>Find and fix the issues that matter in your code (SAST)
Semgrep Supply Chain<br>Fix vulnerabilities in open source dependencies and block malware
Semgrep Secrets<br>Find and fix hardcoded secrets with semantic analysis
Semgrep Guardian<br>Scan and fix AI-generated code the moment it's written
Multimodal<br>Combine AI reasoning with rule-based analysis for detection, triage, and remediation
Semgrep AppSec Platform<br>Automate, manage, and enforce security across your organization
Semgrep Workflows<br>Build and deploy security pipelines that combine static analysis with AI at scale
Product Updates<br>Stay up to date on changes to the Semgrep platform, big and small
Solutions
Open-Source Malware Protection<br>Protect against software supply chain attacks
Static application security testing<br>Increase security while accelerating development
OWASP Top 10<br>Prevent the most critical web application security risks
Secure Guardrails<br>Protect Your Code with Secure Guardrails
Fintech<br>Mitigate software supply chain risks
SaaS & Cloud<br>Increase security while accelerating development
Resources
Docs<br>Want to read all the docs? Start here
Blog<br>Get the latest news about Semgrep
ROI Calculator<br>See how Semgrep can save you time and money
Community Slack<br>Join the friendly Slack group to ask questions or share feedback
Events<br>Join us at a Semgrep Event!
Case Studies<br>See why users love Semgrep
Video Library<br>View our library of on-demand webinars
Community Edition
Company
About<br>The Semgrep story & values
Careers<br>Join the team!
Partners<br>Become a Semgrep partner
Pricing
Sign in
Product support
Contact us
Book demo
Try for free
Application Security
Speedrunrunning SHA pinning for GitHub Actions org-wide
Pinning GitHub Actions to commit SHAs is an effective supply chain defense, but annoying to do org-wide. Here's how I did it, and what I'd do differently.
Leif Dreizler
August 12th, 2026
Has pinning your organization's GitHub Actions (GHAs) to 40-character SHAs been on your to-do list since the tj-actions/changed-files incident in early 2025? If so, this blog is for you! Please learn from my mistakes as I walk you through how I made ~80 PRs in a couple days and turned on org-wide enforcement across ~350 GitHub repositories.<br>If you’re in a rush and want to skip the life story and go straight to the recipe, jump to The Rollout Guide at the end of this blog post.<br>incident tl;dr - Attackers changed every tagged release to point to a malicious commit. If your code was referencing tj-actions/changed-files by tag, e.g. uses: tj-actions/changed-files@v44.1.0 instead of uses: tj-actions/changed-files@some40charSHA, then when your GitHub Action ran it would pull in malicious code.
Image source: https://github.com/tj-actions/changed-files/issues/2464#issuecomment-2726055302
Some folks in the industry had raised concerns about this risk before, but this incident was a loud wake-up call. Unfortunately pinning everything org-wide is kind of a hassle, and GitHub doesn’t make enforcement easy (rant on that later).<br>I’ll walk you through how I enabled the GitHub setting “Require actions to be pinned to a full-length commit SHA” org-wide. Most of the work took just a couple days.<br>How the “Require actions to be pinned to a full-length commit SHA” setting works<br>If you enable this setting, GitHub will check that things are pinned prior to running your GitHub Action. If they aren’t you’ll get this error.<br>If you’re thinking “how hard could this be? there’s gotta be tools that can handle converting actions/cache@v4 to actions/cache@sha,” then you’re partially right. There are plenty of tools out there.<br>The problem is that there are other actions you need to take, and pinning v4 is the easiest one to fix.<br>To turn on this setting without breaking things you need to eliminate:<br>Tags<br>❌ actions/cache@v4<br>✅ actions/cache@057852bfaa89a56745cba8c7296529d2fc39830<br>Branches<br>❌ your-org/some-internal-action@main<br>✅ your-org/some-internal-action@caa296126883cff596d87d8935842f9db880ef25<br>Transitively unpinned actions<br>❌ action1@sha uses unpinned/action@v1<br>✅ gl;hf<br>GitHub rant<br>GitHub could definitely make enabling this setting easier, which is especially frustrating since similar functionality already exists in GitHub Rulesets.<br>There’s no way to see aggregate failures in the UI. Something like Rule insights and evaluation mode would be great. That would allow you to see what will break without actually breaking things.
Enforcement is either per-repo or org-wide, no exceptions. Being able to enforce this setting for:<br>“all repos except x, y, z”
“all Actions except a, b, c”
“direct actions only”
“repos created after x date”
Having an evaluation mode and more flexibility would help organizations ratchet up enforcement over time. I think enabling this org-wide at a large organization would...