tj-actions/changed-files - CVE-2025-30066 - secret leakage

CVE‑2025‑30066: When tj‑actions/changed‑files Leads to Secret Leakage

Secret leakage isn’t always about bad code or vulnerable libraries. Sometimes, it comes down to how we manage secrets during CI runs, and CVE‑2025‑30066 is a textbook example of how that can go sideways. The GitHub Action tj‑actions/changed‑files, widely used to detect changed files in pull requests, became a silent channel for secret leakage. Here’s what happened and how you can lock down your CI/CD secrets pipeline.

What Happened in CVE‑2025‑30066?

In mid‑March 2025, tj‑actions/changed‑files was compromised. The attacker rewrote existing version tags (up to v45.0.7) to point to a malicious commit. This altered the Action’s behavior without developers noticing; no new version was released, just invisible tag tampering.

The payload was straightforward but dangerous: it pulled a remote Base64-encoded Python script that scanned runner memory for credentials, dumping them into logs or exfiltrating them. This wasn’t a logical code flaw in the tj‑actions/changed‑files; it was an abuse of how secret leakage can occur within CI workflows using that reusable Action. CVE‑2025‑30066 wasn’t about buffer overflows; it was about a CI design failure that enabled secrets to leak.

Impact: Any repo using the affected versions of tj‑actions/changed‑files risked secret leakage, especially if sensitive tokens or files were handled insecurely in file patterns or CI outputs.

Why This Affects Workflows Relying on Reusable Actions

DevSecOps workflows heavily rely on tj‑actions/changed‑files to:

  • Automate pull request checks
  • Identify changed files in specific paths
  • Avoid redundant CI jobs

But these workflows often overlook one thing: how glob patterns might include sensitive data. Developers assume that tj‑actions/changed‑files behaves securely by default. However, if you glob configs/** and secrets are stored in configs/secrets.env, you just added a secret file into CI outputs or logs. That’s not a bug in the Action; it’s a CI/CD design failure that leads to secret leakage. CVE‑2025‑30066 is a clear example of this.

How the Secret Leakage Happened (Vulnerability Breakdown)

Let’s unpack the core failure behind CVE‑2025‑30066:

  • Globbing patterns like **/*.env matched secret files unintentionally
  • tj‑actions/changed‑files treated those secrets as changed files
  • Secrets ended up in step outputs, logs, or downstream jobs

This happened because secrets were stored in version-controlled paths (bad idea), and the CI config didn’t explicitly exclude them from globbing (also bad). So it’s not a code bug, it’s poor CI design hygiene causing secret leakage with tj‑actions/changed‑files outputs.

Practical Exploit Path: From CI Job to Credential Exposure

Example CI setup that caused secret leakage through tj‑actions/changed‑files:

yaml
jobs:
  detect_changes:
    runs‑on: ubuntu‑latest
    steps:
      ‑ uses: actions/checkout@v3
      ‑ name: Check changed files
        id: changed
        uses: tj‑actions/changed‑files@v45
        with:
          files: configs/**

If configs/secrets.env changed:

  • It was flagged by tj‑actions/changed‑files
  • It got included in steps.changed.outputs.all_changed_files
  • Later steps logged it or passed it to scripts, leaking secrets

This leak happened because CI logic treated secrets like regular files. That’s where the secret leakage begins, not due to a buffer overflow, but misuse of tj‑actions/changed‑files in a flawed CI design.

Propagation happens with outputs like:

yaml
‑ name: Use changed file list
  run: echo "Changed files: ${{ steps.changed.outputs.all_changed_files }}"

If secrets.env is in that list, its filename and possibly contents may surface in build logs. Even conditional logic like:

yaml
if: contains(steps.changed.outputs.all_changed_files, 'secrets.env')

Can expose sensitive artifacts. This is a CI/CD design failure allowing secret leakage, not a flaw in the Action code.

How to Safely Use Reusable Workflows and Prevent Leakage

You don’t need to abandon tj‑actions/changed‑files. You should use reusable Actions with a secrets-first mindset:

Secrets‑Handling Best Practices

  • Don’t version control secrets, ever
  • Avoid glob patterns that match sensitive paths
  • Use environment-based secrets (GITHUB_ENV, vaults, GitHub Secrets)

CI/CD Configuration Guardrails

  • Always pin Actions to immutable SHAs, not tags (never use @v45)
  • Treat tj‑actions/changed‑files output as tainted, sanitize or filter it
  • Set outputs only if sanitized

⚠️ Unsafe Example:

yaml
jobs:
  detect_changes:
    runs‑on: ubuntu‑latest
    steps:
      ‑ uses: actions/checkout@v3
      ‑ name: Detect all changes
        id: changed
        uses: tj‑actions/changed‑files@v45
        with:
          files: '**/*'  # ⚠️ This glob includes secrets.env, which may leak credentials

The above is exactly the misuse behind secret leakage and CVE‑2025‑30066.

Safe Alternative:

yaml
jobs:
  detect_changes:
    runs‑on: ubuntu‑latest
    steps:
      ‑ uses: actions/checkout@v3
      ‑ name: Detect non‑sensitive file changes
        id: changed
        uses: tj‑actions/changed‑files@<SHA>  # pinned to SHA
        with:
          files: 'src/**'
          files‑ignore: '**/secrets.env'  # ⚠️ Excludes secret file

By doing this, you avoid the CI/CD design failure that leads to secret leakage via tj‑actions/changed‑files.

Additionally:

  • Disable or restrict logging where secrets might appear
  • Use GitHub’s secret masking features
  • Limit access to build logs and artifacts

Quick Secrets‑Safe CI Usage Checklist

Best Practice
Don’t store secrets in version‑controlled files
Use vaults or GitHub Secrets for credentials
Always pin tj‑actions/changed‑files to immutable SHAs
Filter or sanitize outputs from tj‑actions/changed‑files
Never include secret paths in glob patterns
Mask or restrict logs that may expose sensitive data
Audit inherited CI configs often

Xygeni’s Role: CI Secrets Enforcement at Scale

Xygeni secures CI/CD pipelines by focusing on how secrets are handled, used, and exposed in real-world DevOps workflows. It’s not just about scanning code; it’s about enforcing secret management best practices through live pipeline analysis.

Unsafe Output Usage Detection

  • Scans GitHub Actions for uses of echo, run, and outputs where ${{ steps.*.outputs.* }} might include sensitive values
  • Identifies when secrets are referenced or printed directly, intentionally, or by mistake

Leaked Secrets Monitoring

  • Detects high-entropy values (API keys, tokens) inside logs and step outputs
  • Triggers alerts when secrets appear in the pipeline logs, even if masked downstream

Misconfigured Action Usage

  • Tracks all GitHub Actions across pipelines to detect use of compromised versions (e.g., tj-actions/changed-files@v45)
  • Audits file-matching patterns that include potential secrets like **/*.env, *.key, or .env.*

Policy-Based CI Guardrails

  • Enforces SHA-pinning for third-party Actions
  • Blocks use of unsafe file globs that could sweep secrets into logs
  • Prevents pipelines from emitting sensitive values as part of workflow outputs

By treating workflows as part of your threat surface, Xygeni ensures secret hygiene is not just a best practice, it’s a built-in defense.

Conclusion: Secret Leakage Can Start with a Simple Action Misuse

CVE‑2025‑30066 wasn’t a library bug; it was a CI/CD design failure stemming from improper use of tj‑actions/changed‑files. What DevSecOps teams should take away:

  • Treat every glob/file reference in CI as a potential leak point
  • Audit workflows regularly for accidental inclusion of secrets
  • Use secure vaults or environment secrets, never check secrets into version control
  • Sanitize or filter all workflow outputs
  • Log sensitive workflow activity to maintain auditability

CI is code. Workflows are code. Logs and outputs are code. Guard your secrets at every step, or risk a secret leakage scenario that doesn’t need a hacker, just a bad CI/CD design choice.

sca-tools-software-composition-analysis-tools
Prioritize, remediate, and secure your software risks
7-day free trial
No credit card required

Secure your Software Development and Delivery

with Xygeni Product Suite