What happened
The attack began upstream. Attackers compromised reviewdog/action-setup and stole a PAT belonging to a tj-actions maintainer. With that PAT, they force-pushed all version tags (v1 through v45) to a single malicious commit (0e58ed8).
The injected payload executed a Python script that read /proc/<pid>/mem on the Runner.Worker process, extracting every secret GitHub had injected into the runner. Secrets were double-base64 encoded and printed to workflow logs. On public repositories, anyone with read access could decode them. CVE-2025-30066 was assigned. The initial payload targeted Coinbase's agentkit repository specifically before pivoting to the wider campaign.
The discourse
StepSecurity detected the anomaly first on March 14 via Harden-Runner. Wiz and Unit 42 traced the chain from reviewdog to tj-actions. Endor Labs quantified the blast radius: approximately 218 confirmed secret exposures during the 24-hour window. The incident became a canonical example of the mutable tag problem in GitHub Actions.
What Garnet observed
1runner → tj-actions/changed-files (tag → malicious commit 0e58ed8)2 → node index.js3 → python3 -c "import base64, os; ..."4 → open("/proc/<pid>/mem", "rb") # Runner.Worker memory read5 → sys.stdout.write(b64encode(...)) # Secrets dumped to log
Garnet records the process lineage from the action's node entrypoint spawning a Python subprocess that opens /proc/<pid>/mem on the Runner.Worker. This is not normal behavior for an action that lists changed files.
Unlike the TeamPCP campaign, this attack exfiltrated via the workflow log itself — no external C2. Secrets were double-base64 encoded and written to stdout. On public repositories, every secret became recoverable by anyone who read the logs. Egress controls alone would not have caught it.
Assertions fired:
process_memory_read(Python subprocess accessing/proc/*/memfrom action context),exec_from_unusual_dir(Python spawned from node action runtime),unexpected_interpreter_chain(node → python3 with memory access pattern).
Real-world impact
Over 23,000 repositories referenced the action. During the 24-hour window, any workflow that ran under a mutable tag pulled attacker-controlled code. Exposed secrets included GitHub PATs, cloud credentials, npm tokens, and SSH keys. The incident forced ecosystem-wide credential rotation and accelerated adoption of SHA-pinned action references.
/proc/*/mem reads from action subprocesses.