Unpinned GitHub Actions
Using GitHub Actions referenced by mutable tags like @main or @v3 instead of full commit SHAs means a compromised or hijacked action can inject malicious code into your CI pipeline without any change to your workflow file.
How It Works
GitHub Actions are referenced by owner/repo@ref where ref can be a branch, tag, or commit SHA. When you use actions/checkout@v3, GitHub resolves 'v3' to whatever commit that tag currently points to. If the action's repository is compromised, the attacker updates the tag to point to a malicious commit. Your next workflow run pulls the attacker's code automatically. Since actions run with your repository's secrets and GITHUB_TOKEN, the attacker can steal secrets, modify code, or publish malicious packages. Pinning to a full commit SHA (actions/checkout@abc123...) ensures you always run the exact code you reviewed, and any tag manipulation has no effect.
# BAD: actions referenced by mutable tags
name: CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4 # mutable tag
- uses: actions/setup-node@v4 # mutable tag
- uses: some-org/deploy@main # mutable branch!
- uses: docker/build-push-action@latest # worst: 'latest' tag# GOOD: actions pinned to full commit SHAs
name: CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
- uses: some-org/deploy@a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0
- uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0
# Use dependabot or renovate to auto-update SHA pinsReal-World Example
In the 2022 ua-parser-js supply chain attack, the npm package maintainer's account was compromised and malicious versions were published. The same attack vector applies to GitHub Actions: in 2023, the tj-actions/changed-files action was compromised when an attacker force-pushed a malicious commit and moved the version tag. Workflows pinned to the mutable tag executed the attacker's code, leaking CI secrets.
How to Prevent It
- Pin all third-party GitHub Actions to full 40-character commit SHAs, with the version tag in a comment for reference
- Use Dependabot or Renovate to automatically propose SHA pin updates when new versions are released
- Only use actions from verified creators (actions/*, github/*, or organizations you explicitly trust)
- Enable GitHub's allow list for actions at the organization level to restrict which actions can run
Affected Technologies
Data Hogo detects this vulnerability automatically.
Scan Your Repo FreeRelated Vulnerabilities
GitHub Actions Script Injection
criticalUsing untrusted event data like github.event.issue.title directly inside run: blocks allows attackers to inject arbitrary shell commands into your CI pipeline by crafting malicious issue titles, PR bodies, or commit messages.
Secrets Leaked in CI Logs
highPrinting or echoing environment variables containing secrets in CI scripts exposes them in build logs, which are often accessible to all repository collaborators and sometimes publicly visible on open-source projects.
Self-Hosted Runner Risks
highUsing self-hosted GitHub Actions runners with pull_request_target or public fork workflows allows untrusted code from external contributors to execute on your infrastructure with access to secrets, persisted state, and the host network.
Overly Permissive Workflow Permissions
mediumGitHub Actions workflows with permissions: write-all or no explicit permissions block grant the GITHUB_TOKEN excessive access, allowing a compromised step to modify code, create releases, write packages, or change repository settings.