Breachwire.riscent

Breach report

tj-actions/changed-files: a retagged GitHub Action leaked CI secrets from 23,000 repos

Web Application BreachesHigh (CVSS 8.6)CVE-2025-300662025-03
The bottom lineA widely used GitHub Action was compromised so that its version tags pointed to malicious code that dumped CI/CD secrets into build logs, exposing secrets across an estimated 23,000 repositories.
Category
Web Application Breaches
Type
CVE · CI/CD supply-chain compromise
Date
2025-03
Severity
High (CVSS 8.6)
OWASP
Web A03 Software Supply Chain Failures
CWE / CVE
CWE-506 CVE-2025-30066

What happened

In March 2025, the popular GitHub Action tj-actions/changed-files was compromised. On March 14–15, the attackers modified the Action's version tags — v1 through v45.0.7 — so that they pointed to a single malicious commit. Any CI/CD pipeline that referenced those tags began running attacker code, which printed the repository's secrets into the publicly readable build logs. Because the Action was used across an estimated 23,000 repositories, the exposure was broad and immediate.

Tracked as CVE-2025-30066 with a CVSS score of 8.6 (High), the flaw was published on March 15, 2025, and CISA added it to the Known Exploited Vulnerabilities catalog on March 18 with a remediation deadline of April 8. A related compromise of a reviewdog Action was reported in the same window.

Root cause

This was embedded malicious code (CWE-506) delivered through the software supply chain, made possible by a common but dangerous practice: referencing third-party Actions by a mutable tag such as @v45 rather than a pinned commit hash. When the attacker retagged those versions to the malicious commit, every consumer silently pulled the poisoned code on their next run. The secrets themselves leaked through unredacted build logs (CWE-532).

How it would have been caught

A policy check that fails any workflow referencing an Action by a floating tag instead of a full commit SHA would have blocked the exposure entirely. Scanning build logs for secret-shaped strings catches the exfiltration in progress. A reproduction runs the poisoned tag in a throwaway pipeline with a canary secret and confirms the canary appears in the logs.

How to prevent it

  • Pin every third-party Action to a full commit SHA, not a mutable tag, and review changes before bumping.
  • Scope CI tokens to least privilege and short lifetimes so a leak has minimal blast radius.
  • Enable secret masking and audit build logs for accidental secret exposure.
  • Rotate any secret that could have been exposed during the compromise window.

The Breachwire test (red → green)

Reference the compromised tag in a test pipeline seeded with a canary secret and confirm the canary is printed into the build log — the RED control. Repin the workflow to a clean commit SHA (or the fixed v46+), rerun, and confirm the canary never appears in the logs, while the Action still performs its legitimate changed-files function.