ThreatPaperBeta
Supply Chain AttackCritical

GitHub Actions Supply Chain Compromise: tj-actions/changed-files Poisoning (CVE-2025-30066)

By Sethu Satheesh · 15 Mar 2025 · 14 min read

Threat Actor: Unknown (unattributed as of publication) · Target: GitHub Actions ecosystem — compromise of `tj-actions/changed-files` GitHub Action via stolen bot token, retroactively poisoning v1 through v45.0.7 and exposing CI/CD secrets from 23,000+ dependent repositories

Source: github.com


Executive Summary

Between approximately March 12–14, 2025, attackers compromised a GitHub Personal Access Token (PAT) belonging to tj-actions-bot — a bot account used by the maintainer of tj-actions/changed-files, one of the most widely-used GitHub Actions in the ecosystem. Using this token, the attackers retroactively rewrote version tags v1 through v45.0.7 to point to a single malicious commit, meaning any repository that pinned to a tag (rather than an immutable commit SHA) would silently receive the compromised code on its next workflow run.

The malicious payload, obfuscated using base64 encoding, downloaded a secondary Python script that scanned the GitHub Actions runner process memory (specifically Runner.worker) using regular expressions to extract CI/CD secrets — including AWS access keys, GitHub tokens, npm tokens, and SSH private keys. These secrets were then printed directly into the workflow's build logs. In repositories with public visibility, these logs were accessible to anyone on the internet.

The attack was discovered on March 14, 2025 after security researchers noticed anomalous behavior in the Action's output. The Action was patched (v46.0.1) and all malicious tags were reverted by March 15, 2025. The Rust Security Response Team, GitHub, CISA, and multiple security vendors published advisories, urging all users who ran the compromised Action between March 12–15, 2025 to treat all secrets exposed in that window as compromised and rotate them immediately.

The incident is linked to an earlier compromise of reviewdog/action-setup@v1 (CVE-2025-30154), which researchers believe was used as a stepping stone to obtain the tj-actions-bot token. No specific threat actor group was publicly attributed for this attack.

Scale: Over 23,000 repositories are estimated to have been affected.

Verification of Claims

  1. Claim: Attackers compromised the tj-actions-bot GitHub PAT to push the malicious commit. → Verified → GitHub Security Advisory GHSA-mrrh-fwg6-7kvq; Wiz research; GitHub investigation confirmed bot token was the access vector, not a maintainer account takeover.

  2. Claim: Version tags v1 through v45.0.7 were retroactively updated to point to a malicious commit. → Verified → GitHub commit history confirms all listed tags were redirected to commit 0e58ed8; NIST NVD entry for CVE-2025-30066 confirms the scope.

  3. Claim: The malicious payload scanned Runner.worker process memory for secrets using regex and printed them to build logs. → Verified → Sysdig threat research and StepSecurity analysis confirm the Python script behavior: regex scanning of process memory, output printed to $GITHUB_STEP_SUMMARY and stdout.

  4. Claim: Secrets were printed to workflow logs, not exfiltrated to an external C2 endpoint. → Verified → Multiple independent researchers (Sysdig, Wiz, StepSecurity) confirmed: secrets were logged to stdout/step summary, not sent to a remote server. However, in public repos these logs were publicly accessible.

  5. Claim: ~23,000+ repositories were affected. → Verified → GitHub and security researchers estimated over 23,000 repositories had workflows using the affected versions during the window.

  6. Claim: The attack is linked to reviewdog/action-setup@v1 compromise (CVE-2025-30154). → Partially verified → Wiz and other researchers identified infrastructure and timing overlap suggesting the reviewdog compromise (which occurred days earlier) may have provided the attacker with access to the tj-actions-bot token. GitHub's investigation supported this link but no definitive confirmation was published.

  7. Claim: No specific threat actor was attributed. → Verified → As of publication, no security vendor (GitHub, Wiz, Mandiant, CrowdStrike, SentinelOne) has publicly named a threat actor group responsible for this attack.

  8. Claim: CISA published an advisory on this incident. → Verified → CISA alert of 18 March 2025, "Supply Chain Compromise of Third-Party tj-actions/changed-files (CVE-2025-30066) and reviewdog/action-setup@v1 (CVE-2025-30154)". CISA also added CVE-2025-30066 to the Known Exploited Vulnerabilities catalog on the same date, which makes remediation binding on US federal civilian agencies under BOD 22-01.

Timeline

Date Actor Event Source
~Mar 11–12, 2025 Unknown reviewdog/action-setup@v1 tags compromised (CVE-2025-30154); attacker gains access to cross-repo tokens Wiz Research / CVE-2025-30154
~Mar 12, 2025 Unknown Attacker uses stolen tj-actions-bot PAT to push malicious commit (0e58ed8) to tj-actions/changed-files GitHub Advisory GHSA-mrrh-fwg6-7kvq
Mar 12–14, 2025 Unknown Attacker retroactively rewrites all version tags (v1–v45.0.7) to point to malicious commit GitHub Commit History
Mar 12–14, 2025 Victim repos Repositories using any tj-actions/changed-files@vX tag (not SHA-pinned) execute malicious payload on workflow run Sysdig / StepSecurity Analysis
Mar 12–14, 2025 Malicious payload Python script scans Runner.worker process memory; extracts secrets via regex; prints to workflow logs Sysdig Threat Research
Mar 14, 2025 Security researcher Anomalous output detected in tj-actions/changed-files workflow logs; reported to GitHub Security GitHub Security Blog
Mar 14, 2025 GitHub / tj-actions Investigation begins; malicious commit identified; tags start being reverted GitHub Advisory
Mar 15, 2025 tj-actions maintainer All tags reverted to legitimate commits; patched version v46.0.1 released GitHub Release / Advisory
Mar 15, 2025 GitHub GitHub Security Advisory GHSA-mrrh-fwg6-7kvq published; Dependabot alerts sent to affected repos GitHub Security
Mar 18, 2025 CISA Publishes alert on both compromised actions and adds CVE-2025-30066 to the KEV catalog: rotate all secrets exposed in the window, pin to commit SHA CISA alert
Mar 15–17, 2025 Security community Sysdig, Wiz, StepSecurity, SentinelOne, Snyk, Harness publish technical analyses; link to CVE-2025-30154 Multiple vendor blogs
Ongoing Security community Incident drives industry-wide adoption of SHA pinning; GitHub accelerates Action signature verification roadmap GitHub Blog / SLSA community

Attack Anatomy

Initial Access — Bot Token Compromise via reviewdog

The attacker's access to the tj-actions repository was not through a compromised maintainer account, but through a stolen tj-actions-bot GitHub PAT:

  1. Predecessor Compromise: reviewdog/action-setup@v1 was compromised (CVE-2025-30154) in the days prior. Researchers believe the token used for reviewdog cross-repo access, or a secret accessible during reviewdog workflow execution, provided the attacker with the tj-actions-bot PAT.
  2. Bot Account Abuse: The tj-actions-bot PAT had write access to the tj-actions/changed-files repository, specifically the ability to push commits and update tags — a capability needed for automated release workflows.
  3. No Maintainer Account Compromise: The human maintainer's personal GitHub account was not compromised. The attack relied entirely on the bot's machine token.

Key insight: Bot/machine tokens are often granted the same privileges as human maintainers, but are harder to monitor and may not have the same MFA protections.

Execution — Retroactive Tag Rewriting

Unlike most supply chain attacks that inject malicious code into a new version release, this attack poisoned all existing version tags simultaneously:

  1. Single Malicious Commit: Attacker pushed one commit (0e58ed8) containing the malicious dist/index.js
  2. Tag Mass Rewrite: Updated all version tags (v1, v2, ... v45.0.7) to point to this commit using the git tag -f (force) flag
  3. Stealth: Users pinned to v44 or v45 (for example) did not need to update — their next workflow run automatically used the malicious code
  4. No New Release Published: No new version number was published; the attack was invisible in release history
Before attack:  tj-actions/changed-files@v44 → commit abc123 (legitimate)
After attack:   tj-actions/changed-files@v44 → commit 0e58ed8 (malicious)

Credential Access — Memory Scanning and Log Exfiltration

The malicious dist/index.js (a bundled Node.js file) performed the following:

  1. Download Secondary Payload: Fetched a Python script from a remote URL
  2. Process Memory Scanning: The Python script attached to the Runner.worker process and scanned its memory for strings matching credential patterns:
    • AWS key patterns: AKIA[0-9A-Z]{16}
    • GitHub token patterns: gh[pousr]_[A-Za-z0-9]{36}
    • Generic key/secret/token patterns
  3. Log Exfiltration (not C2): Extracted secrets were written to:
    • Standard output (stdout) — visible in workflow run logs
    • $GITHUB_STEP_SUMMARY — visible in the Actions summary tab
  4. Public Repo Exposure: In repositories with public visibility, build logs are accessible to anyone without authentication, meaning extracted secrets were effectively publicly exposed

Note: Unlike many supply chain attacks, this attack did NOT send secrets to an attacker-controlled C2 server directly. The attacker's collection mechanism was passive — reading the public (or accessible) workflow logs. This may indicate the attacker expected to harvest credentials from public repo logs, or planned to access private logs via a follow-on intrusion.

Detection

The attack was discovered when security researchers and users noticed:

  • Unexpected content in workflow logs (credential-like strings appearing in output)
  • Unusual Python subprocess spawning during tj-actions/changed-files execution
  • The malicious dist/index.js differing from committed source code in src/

Loading diagram...

Threat Actor Profile

  • Name / Alias: Unknown — no public attribution as of publication date
  • Attribution Confidence: None — GitHub, Wiz, CISA, and other researchers have not publicly attributed this attack to any known threat actor group
  • Motivation: Unclear — credential harvesting (financial, espionage, or supply chain positioning). The passive log-based exfiltration method is unusual compared to direct C2 exfiltration used by more sophisticated actors.
  • Sophistication Level: Moderate — The technique of retroactive tag rewriting is well-understood and not novel, but the choice of targeting a widely-used Action for maximum blast radius shows supply chain targeting awareness. The chaining via reviewdog shows multi-step planning.
  • Related Incident: CVE-2025-30154 (reviewdog/action-setup@v1) — same window, believed linked
  • MITRE ATT&CK Techniques:
    • T1195.001 — Supply Chain Compromise: Compromise Software Dependencies (GitHub Action)
    • T1195.002 — Supply Chain Compromise: Compromise Software Supply Chain (bot token abuse)
    • T1552.001 — Unsecured Credentials: Credentials In Files (secrets in workflow environment)
    • T1003 — OS Credential Dumping (process memory scanning of Runner.worker)
    • T1059.006 — Command and Scripting Interpreter: Python (secondary payload)
    • T1059.007 — Command and Scripting Interpreter: JavaScript (Node.js in Action)
    • T1027 — Obfuscated Files or Information (base64 encoded payload in dist/index.js)
    • T1562.001 — Impair Defenses (executing in trusted CI/CD context, no EDR)
    • T1530 — Data from Cloud Storage (accessing secrets from runner environment)

Technical Indicators

cve:
  - "CVE-2025-30066 (tj-actions/changed-files)"
  - "CVE-2025-30154 (reviewdog/action-setup)"
 
github_advisories:
  - "GHSA-mrrh-fwg6-7kvq (tj-actions/changed-files)"
  - "GHSA-g2r7-5v8h-9gph (reviewdog/action-setup)"
 
malicious_commits:
  - repository: "tj-actions/changed-files"
    commit_sha: "0e58ed8671d6b60d0890c21b07f8835ace038e67"
    description: "Malicious commit pointed to by all poisoned version tags"
 
affected_versions:
  - "tj-actions/changed-files: v1 through v45.0.7 (all tags retroactively updated)"
  - "reviewdog/action-setup: v1 (prior compromise, CVE-2025-30154)"
 
clean_versions:
  - "tj-actions/changed-files: v46.0.1 and later (patched)"
 
attack_window:
  - "Approximately March 12, 2025 07:00 UTC to March 15, 2025 (tags reverted)"
 
payload_behavior:
  - "Downloads Python script from remote URL"
  - "Scans Runner.worker process memory using regex patterns"
  - "Credential patterns targeted: AWS keys (AKIA...), GitHub tokens (gh[pousr]_...), generic secrets"
  - "Prints extracted secrets to stdout and $GITHUB_STEP_SUMMARY"
  - "No confirmed direct C2 exfiltration endpoint"
 
detection_artifacts:
  - "Workflow logs: credential-like strings appearing in tj-actions/changed-files step output"
  - "Workflow logs: Python subprocess spawning from Node.js Action"
  - "GitHub Audit Log: bot token push of commit 0e58ed8 to tj-actions/changed-files"
  - "GitHub Audit Log: mass tag update across all version tags"
  - "Dependabot alerts: GHSA-mrrh-fwg6-7kvq for any workflow using tj-actions/changed-files@vX"
 
remediation_indicators:
  - "Safe: tj-actions/changed-files pinned to SHA beyond 0e58ed8 (after March 15 revert)"
  - "Safe: tj-actions/changed-files@v46.0.1 or later"
  - "Compromised if: any workflow used tj-actions/changed-files@v1 through @v45.0.7 (via tag) between Mar 12–15, 2025"

Impact Assessment

  • Repositories Directly Exposed: 23,000+ (estimated) that ran workflows using the compromised Action during the attack window
  • Secret Types at Risk: Any secrets passed into the workflow as environment variables or GitHub Actions secrets context, including:
    • AWS access keys (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
    • GitHub tokens (GITHUB_TOKEN, personal access tokens, fine-grained PATs)
    • npm registry tokens (NPM_TOKEN, NODE_AUTH_TOKEN)
    • SSH private keys (SSH_PRIVATE_KEY, deploy keys)
    • Docker registry credentials
    • Cloud provider service account keys (GCP, Azure)
    • Any custom secret passed to the workflow
  • Public vs. Private Repos: Public repository workflow logs were immediately accessible to any internet user. Private repository logs were accessible to organization members (and potentially to the attacker if they also compromised org access).
  • Financial Impact: Not quantified publicly — dependent on what secrets were exposed and whether attackers actively harvested and used them.
  • Systemic Impact: The incident became a widely-cited case study for the risks of mutable version tags in GitHub Actions and accelerated industry adoption of SHA pinning and Action signature verification.
  • CISA: Published an alert on 18 March 2025 covering both compromised actions, and added CVE-2025-30066 to the Known Exploited Vulnerabilities catalog. The KEV listing is the operative part: it obliges US federal civilian agencies to remediate within the BOD 22-01 deadline, turning advice into a requirement.
  • NIST NVD: CVE-2025-30066 and CVE-2025-30154 catalogued with CVSS scoring.
  • GitHub: Published GitHub Security Advisory GHSA-mrrh-fwg6-7kvq; sent Dependabot alerts to all affected repositories; accelerated roadmap for Action signature verification and SHA pinning enforcement.
  • No criminal proceedings publicly announced as of publication — no attribution to a specific individual or group.

Lessons and Defensive Recommendations

For Developers and DevOps Engineers

  1. Pin Actions to Commit SHA, Not Tags:

    • Bad: uses: tj-actions/changed-files@v44
    • Good: uses: tj-actions/changed-files@a29e8b565651ce417abb8de9eb4b09593dc2b5f4
    • Tags are mutable — a repo owner (or attacker with a token) can silently redirect them
    • Commit SHAs are immutable — a specific SHA always resolves to the same code
  2. Rotate All Secrets Immediately If Exposed:

    • If your workflows used tj-actions/changed-files@vX (tag-pinned) between March 12–15, 2025: treat all secrets in those workflows as compromised
    • Rotate: AWS keys, GitHub tokens, npm tokens, SSH keys, any other secrets in scope
    • Audit: CloudTrail / GitHub Audit Log for unauthorized usage
  3. Apply Least-Privilege to Workflow Secrets:

    • Use OIDC federation for cloud access (AWS, GCP, Azure) instead of long-lived API keys
    • Scope the GITHUB_TOKEN permissions explicitly (permissions: contents: read)
    • Pass secrets only to the specific job steps that need them
  4. Audit Third-Party Actions Regularly:

    • Maintain an inventory of all Actions used across your organization
    • Subscribe to GitHub Security Advisories (Dependabot alerts) for Action advisories
    • Prefer Actions from verified publishers or with high community scrutiny

For Security Teams

  1. Monitor CI/CD Logs for Credential Patterns:

    • Implement log scanning for credential-like strings appearing in workflow output
    • Alert on unexpected subprocess execution within GitHub Actions steps
    • Stream GitHub Audit Logs to your SIEM
  2. Enforce SHA Pinning via Policy:

    • Use GitHub's Actions policy (Enterprise Cloud) to require SHA pinning
    • Implement pre-commit hooks or CI checks that fail on mutable tag references in workflows
    • Tools like pin-github-action or zizmor can automate SHA pinning
  3. Include CI/CD Supply Chain in Threat Model:

    • Third-party Actions run with the same trust level as your own code
    • A compromised Action is equivalent to a malicious insider with access to all workflow secrets
    • Red team exercises should include CI/CD supply chain attack scenarios

For Platform Providers (GitHub, GitLab, etc.)

  1. Action Signature Verification: Implement and enforce cosign/sigstore signing for Marketplace Actions
  2. Immutable Tags Option: Provide a mechanism for Action publishers to lock tags as immutable after release
  3. Bot Token Scope Restriction: Enforce principle of least privilege for machine tokens — separate read/write permissions for tags vs. code
  4. Anomaly Detection: Alert on mass tag rewrites from bot accounts

Sources

  1. GitHub Security Advisory. "GHSA-mrrh-fwg6-7kvq: tj-actions/changed-files vulnerable to arbitrary code execution". March 2025.

  2. NIST NVD. "CVE-2025-30066".

  3. NIST NVD. "CVE-2025-30154 (reviewdog/action-setup)".

  4. Sysdig. "GitHub Actions Supply Chain Attack: tj-actions/changed-files". March 2025.

  5. Wiz Research. "tj-actions/changed-files supply chain attack: what you need to know". March 2025.

  6. StepSecurity. "How the tj-actions/changed-files attack works". March 2025.

  7. Harness. "CVE-2025-30066 and CVE-2025-30154: GitHub Actions Supply Chain Attack Analysis". March 2025.

  8. Snyk. "Understanding CVE-2025-30066: tj-actions/changed-files". March 2025.

  9. CISA. "Supply Chain Compromise of Third-Party tj-actions/changed-files (CVE-2025-30066) and reviewdog/action-setup@v1 (CVE-2025-30154)". 18 March 2025.

  10. SentinelOne. "GitHub Actions Supply Chain Attack Analysis". March 2025.

  11. MITRE ATT&CK. "Supply Chain Compromise: T1195".


Corrections log — 2 September 2026: The CISA response was correctly reported but not correctly cited — the Sources list pointed at the bare cisa.gov homepage, and the timeline dated the guidance to 15 March 2025. CISA published its alert on 18 March 2025 and added CVE-2025-30066 to the Known Exploited Vulnerabilities catalog the same day. The citation now resolves to that alert, the date is corrected, and the KEV listing is noted because it is what makes remediation binding on US federal civilian agencies under BOD 22-01.

Original Incident Report →

Related Research

Between late 2025 and mid-2026, the software supply chain threat landscape underwent a fundamental paradigm shift with the emergence of the Shai-Hulud malware lineage. Culminating in the highly...

MalwareSupply Chain Attack

A North Korean-linked actor compromised Trading Technologies' X_TRADER, used it to breach 3CX, and shipped signed, trojanised VoIP clients to its customers — the first documented case of one software supply chain attack causing another.

Supply Chain AttackState-Sponsored

Between mid-2025 and August 2026, a cybercriminal collective operating primarily under the ShinyHunters brand—alongside associated activity clusters tracked as UNC6040, UNC6240, UNC6395, UNC6661, and...

Data BreachSupply Chain Attack