GitHub Actions Hardening: What 2023-2026 Incidents Taught Us
Cybersecurity
From the tj-actions/changed-files compromise to the credential leakage incidents in 2025, GitHub Actions has been a reliable supply-chain attack vector. The hardening playbook is well-known. Most teams have implemented half of it.
By Arjun Raghavan, Security & Systems Lead, BIPI · October 25, 2024 · 7 min read
GitHub Actions has had a rough three years for supply chain incidents. The tj-actions/changed-files compromise in March 2025 exposed thousands of workflows to credential exfiltration. The reviewdog action incident shortly after hit similar coverage. Multiple smaller incidents involving compromised maintainer accounts have followed roughly quarterly.
The hardening playbook is not secret. GitHub published it. Sigstore recommends it. Every security team we work with has read it. Implementation is partial almost everywhere. We walk through the four hardening moves that close 90 percent of the practical attack surface.
Pin actions to commit SHAs, not tags
uses: tj-actions/changed-files@v44 looks like version pinning. It is not. Tags are mutable in Git. An attacker who compromises the maintainer account can re-point v44 to a malicious commit, and your next CI run pulls it.
uses: tj-actions/changed-files@a284dc1814e3fbfcf20bc9fdc3ad8cfb7d4cea2c is real pinning. The commit hash cannot be moved. The 2025 incident was contained at organizations that had pinned to SHAs because the malicious commit was a different SHA than the ones their workflows referenced. It rolled through the rest.
- Use Dependabot with the pin-to-commit option to manage updates.
- Renovate also supports SHA pinning with version comments for readability.
- Treat third-party actions like dependencies: review changes, do not auto-merge.
- Audit your workflows quarterly for unpinned references.
OIDC for cloud authentication
Long-lived AWS access keys in GitHub secrets are 2018 thinking. The current pattern is OIDC: GitHub issues a short-lived JWT to your workflow, AWS or GCP or Azure trusts that JWT, your workflow gets temporary credentials scoped to a specific role.
If your secrets exfiltrate, the attacker gets a 5-minute window with a specific role's permissions. Versus the days or weeks of full-account access they get with leaked static credentials. The math is not close.
GITHUB_TOKEN scope reduction
By default, GITHUB_TOKEN at the workflow level has write permissions to most of the repository. A compromised action with that token can push commits, create releases, modify branch protections.
The fix is in your workflow YAML: permissions block at the top, default contents read, then escalate per-job to only what is needed. We have walked clients through this in repositories with 200+ workflows. The first audit usually reveals 90 percent of jobs requesting permissions they never use.
Environments with required reviewers for deploys
Production deployments should not happen because a workflow ran. They should happen because a workflow ran and a human approved. GitHub Environments support required reviewers as a gate. Configure your prod environment with one or two required reviewers from a deploy-approvers team.
The friction is real. The friction is the point. We have stopped at least three near-miss incidents this way at clients, including one where a developer's compromised laptop pushed a workflow change that would have deployed a backdoored container. The required-reviewer gate caught it because the reviewer noticed the workflow diff was odd.
What your audit should check
The other thing worth doing: enable Actions step debug logging in your SIEM, ingest the audit log via webhook, and write detection rules for unusual patterns like new external action references, secret access from unexpected workflows, and workflow file changes outside the standard PR flow. Most Actions compromises have a detectable footprint if you are looking. Most teams are not, and that is the gap to close in 2026.
Read more field notes, explore our services, or get in touch at info@bipi.in. Privacy Policy · Terms.