March 2025 zero-day report: GitHub Actions supply-chain compromise
tj-actions/changed-files was compromised in March 2025 and used to leak CI secrets across thousands of repositories. Plus Q1 2025's other actively-exploited zero-days, what was chained with what, and what defenders should patch first.
Executive summary
Q1 2025 was dominated by a single supply-chain compromise that affected thousands of CI pipelines, alongside two perimeter-appliance zero-days actively exploited by suspected nation-state actors. The dominant theme - again - was the chaining of access-control flaws with credential theft in widely-deployed infrastructure.
This report focuses on disclosures we believe most defenders should prioritise this quarter - and the patterns underneath them. Every CVE referenced below is in the CISA Known Exploited Vulnerabilities catalogue.
If you patch nothing else this month: rotate any secret that was visible to a GitHub Action runner since March 11, 2025 (the compromise window of tj-actions/changed-files), patch Ivanti Connect Secure to the version listed in the Jan-Feb advisories, and update FortiOS to fix CVE-2024-55591.
These three account for the majority of in-the-wild exploitation we and other vendors observed in Q1.
The four critical disclosures
| CVE | Affects | CVSS | Severity | Status |
|---|---|---|---|---|
| CVE-2025-30066 | tj-actions/changed-files (GitHub Action) | 8.6 | CRITICAL | In the wild |
| CVE-2025-0282 | Ivanti Connect Secure / Policy Secure / ZTA | 9.0 | CRITICAL | In the wild |
| CVE-2024-55591 | Fortinet FortiOS / FortiProxy | 9.6 | CRITICAL | In the wild |
| CVE-2025-23006 | SonicWall SMA1000 Appliance Mgmt Console | 9.8 | CRITICAL | In the wild |
CVE-2025-30066: the GitHub Actions supply-chain compromise
On March 14, 2025, the popular GitHub Action tj-actions/changed-files - used in roughly 23,000 public repositories at time of compromise - was modified to print CI runner secrets into workflow logs. Every tag of the action, including pinned tags, was force-updated to point at a malicious commit. Any workflow that ran after the change and uploaded its logs to a public location (the default for forks) leaked its secrets.
The compromise was traced back to a compromised personal access token belonging to a maintainer. The chain underneath was the standard one: maintainer token → tag force-update → log exfiltration.
Initial access
A maintainer's personal access token was compromised - the root cause remains under investigation, but the working theory is upstream supply chain (a downstream action used by the maintainer's workflow).
Tag manipulation
The attacker rewrote every existing tag of tj-actions/changed-files to point at a single malicious commit. This bypassed the conventional "pin to a specific version" defence because the tag itself was the moving target.
Secret exfiltration
The malicious code base64-decoded the runner's memory, extracted environment variables and the runner's GITHUB_TOKEN, and printed them to stdout - which ends up in the workflow log, which is public for fork PRs by default.
Downstream impact
Researchers at Wiz and StepSecurity catalogued thousands of repositories that ran the action during the compromise window. Any secret exposed to those workflows must be considered leaked.
# Recommended remediation - pin to a known-clean commit SHA
- uses: tj-actions/changed-files@<sha-from-pre-compromise>
# Better: vendor the action's logic into your own internal action
# Best: rotate every secret that was visible to a runner since 11 Mar 2025
CVE-2025-0282: Ivanti Connect Secure stack overflow
Ivanti disclosed CVE-2025-0282 on January 8, 2025 - a stack-based buffer overflow in Ivanti Connect Secure (ICS), Ivanti Policy Secure, and Ivanti Neurons for Zero Trust Access. Google Threat Intelligence Group attributed in-the-wild exploitation to a suspected China-nexus actor tracked as UNC5337 (with operational overlap to UNC5221).
The pattern was the same one we covered in our 2024 retrospective: edge-appliance pre-auth RCE, followed by web-shell deployment, followed by credential harvesting from the appliance's configured identity stores.
CVE-2024-55591: FortiOS authentication bypass
Fortinet disclosed CVE-2024-55591 on January 14, 2025, after Arctic Wolf had been tracking active exploitation since November 2024. The CVE allows a remote, unauthenticated attacker to gain super-admin privileges via crafted requests to the node.js websocket module on FortiOS and FortiProxy.
The lesson is the same lesson Fortinet customers have been re-learning every six months: management plane access from the public internet is not a "small risk for convenience" - it is a credential-leak primitive.
CVE-2025-23006: SonicWall SMA1000
SonicWall published a high-severity advisory on January 22, 2025 for CVE-2025-23006 in the SMA1000 Appliance Management Console - a pre-authentication deserialisation vulnerability with confirmed in-the-wild exploitation prior to disclosure.
Pattern observation: all four critical disclosures targeted code paths on devices designed to sit at the perimeter. The "perimeter" has been the same set of vendor appliances for two years running. If your defence model still treats Ivanti, Fortinet, SonicWall, and similar appliances as trusted, the model needs an update.
Disclosure timeline
- 2025/Jan/08
CVE-2025-0282 disclosed (Ivanti)
Ivanti publishes advisory after Google TIG flags in-the-wild exploitation. Mandiant attributes to UNC5337.
- 2025/Jan/14
CVE-2024-55591 disclosed (Fortinet)
Fortinet publishes FG-IR-24-535. Arctic Wolf publishes evidence of exploitation dating to Nov 2024.
- 2025/Jan/22
CVE-2025-23006 disclosed (SonicWall)
SonicWall publishes advisory. CISA adds to KEV catalogue within 48 hours.
- 2025/Mar/11
tj-actions/changed-files compromised
Malicious commit pushed; all existing tags rewritten to point at it. No public disclosure yet - secret exfiltration begins.
- 2025/Mar/14
Compromise detected and reported
StepSecurity's Harden-Runner observed the anomalous behaviour. GitHub revokes the action; Wiz publishes the root-cause analysis. CVE-2025-30066 assigned.
- 2025/Mar/18
Mass-rotation guidance issued
GitHub, Wiz, StepSecurity converge on the recommendation: rotate every secret visible to a runner that executed the action since Mar 11.
The supply-chain attack on tj-actions is not an outlier. It is the predictable consequence of pinning to tags rather than to immutable commit SHAs. Anyone whose CI configuration uses
- Staatse incident response retrospective, Q1 2025@v-style references has chosen "convenience" as a security boundary - and the threat actor noticed.
What defenders should do now
If you're triaging this report against a limited maintenance window, here's the order we recommend.
- Rotate every secret available to CI runners that executed
tj-actions/changed-filesbetween 11 Mar and 15 Mar 2025. - Patch Ivanti Connect Secure to the version specified in their January advisory; assume any unpatched appliance was compromised.
- Patch FortiOS/FortiProxy to the versions specified in FG-IR-24-535; pull the FortiGate management plane off the public internet.
- Patch SonicWall SMA1000 per the January 22 advisory.
- Audit your GitHub Actions usage - pin every third-party action to a 40-character commit SHA, not a tag.
- Add detection for outbound traffic to the cloud metadata IP from any service that is not your orchestrator. (Standing recommendation from prior quarters.)
Key takeaways
- Tag-pinning is no longer a defence for third-party GitHub Actions - pin to commit SHA only.
- Edge appliance pre-auth RCE remains the dominant attacker entry point - if you operate Ivanti, Fortinet, SonicWall, or similar, your management plane should not be on the public internet.
- The median patch-to-exploit window in Q1 was 14 days for actively-exploited CVEs - your maintenance window has to be tighter than that.
- Every CVE in this report is in CISA KEV. If you're a US federal contractor, BOD 22-01 already requires the patches.
Outlook for Q2
Expect at least one more CI/CD supply-chain compromise before the end of Q2 - the tj-actions attack pattern is too cheap to abandon, and the GitHub Actions ecosystem is still under-pinned. Expect at least one more Ivanti or Fortinet zero-day - both vendors have unresolved structural issues in their management plane that drive recurring critical findings.
Our recommendation: invest the quarter in CI/CD pipeline hardening and cloud identity boundary reviews - not headline-driven patching.
If you'd like a tailored briefing for your environment, we're happy to walk your team through the report on a call. Get in touch.
References & further reading
- GitHub SecuritySecurity advisory: tj-actions/changed-files compromise (CVE-2025-30066)
- NVDCVE-2025-30066 - tj-actions/changed-files allows information disclosure
- NVDCVE-2025-0282 - Ivanti Connect Secure stack-based buffer overflow
- IvantiSecurity advisory: Ivanti Connect Secure, Policy Secure and ZTA Gateways
- NVDCVE-2024-55591 - Fortinet FortiOS authentication bypass
- Fortinet PSIRTFG-IR-24-535: Authentication bypass in node.js websocket module
- CISA KEVKnown Exploited Vulnerabilities catalog
- StepSecurityHarden-Runner detection: tj-actions/changed-files action is compromised
- Wiz ResearchGitHub Action tj-actions/changed-files supply chain attack: from CVE-2025-30066 to root cause
- Mandiant / Google TIGSuspected China-nexus actor exploiting Ivanti Connect Secure (UNC5337)