GitHub Actions Supply Chain: tj-actions Breach Exposes CI Secrets of 23,000 Repositories
The widely used tj-actions/changed-files GitHub Action was compromised, causing it to print CI/CD secrets — including AWS keys, API tokens, and passwords — to public GitHub Action logs where anyone could read them.
Background
GitHub Actions are reusable workflow components. tj-actions/changed-files was used in over 23,000 repositories to detect which files changed in a pull request. GitHub Actions run in the CI/CD pipeline context with access to all workflow secrets.
The Attack
In March 2023, attackers compromised a personal access token belonging to the maintainer of tj-actions/changed-files. They modified the action to dump the runner's memory to the GitHub Actions log, which included all environment variables and secrets available to the workflow. Because GitHub Actions logs are public for public repositories, anyone could read the extracted secrets. The malicious modification affected all versions of the action via its floating version tags. Researchers traced the attack to a compromised Canonical token in a prior attack.
Response
Researcher Adnan Khan discovered the compromise on March 14, 2023. GitHub immediately suspended the tj-actions account. Thousands of repository owners were notified. Security teams urgently scanned public GitHub Action logs for exposed secrets and rotated credentials.
Outcome
The incident affected over 23,000 repositories. The practice of using floating version tags (v1, v2) for GitHub Actions rather than pinned SHA commits meant a single compromise updated all users simultaneously. The incident drove widespread adoption of pinned action SHA references.
Key Takeaways
- Pin GitHub Actions to specific commit SHAs, never to floating version tags — a floating tag update can immediately affect all users
- GitHub Actions logs are public for public repositories — never allow secrets to be printed to logs
- Personal access tokens for action maintainers are critical infrastructure that need hardware MFA and scope limitations
- Audit public GitHub Action logs for accidentally exposed secrets immediately after any action compromise is announced