At 13:20:36 UTC on October 8, a commit titled "Add security audit workflow" landed on the default branch of pyxel, the retro game engine with roughly 18,400 stars. It was signed by nobody, but it carried the real identity of its author, Takashi Kitao. Over the next 24 minutes the same account pushed the same file to 27 repositories. Eight hours later, at 21:10, a second account belonging to Henry Wu, original author of Uber's athenadriver, started its own run. In 16 minutes it touched 318 repositories: 39 source repos and 279 forks. The last commit hit uber/athenadriver at 21:25:54.
That's the timeline StepSecurity published on October 9 in its write-up titled "GhostAction Returns." GitGuardian's update the same day counted 346 repositories rather than 345, a one-repo difference that doesn't change anything. The Hacker News and GBHackers both carried the numbers, and both attributed a much larger figure to Socket: more than 500 compromised GitHub accounts and tens of thousands of repositories since October 7. I'd treat that second number as an upper bound until Socket publishes its methodology. The 345 is the number with commit timestamps behind it.
I want to spend this post on one design choice in the payload, because it changes what "incident response" means for anyone who has ever committed a key and then deleted it.
The file that reads your past
The 2025 GhostAction campaign, documented by GitGuardian at 817 repositories, 327 users and 3,325 stolen secrets, did something fairly simple. A workflow called github_actions_security.yml POSTed the repository's named Actions secrets to a collection server. If you rotated those secrets, you were mostly done.
The 2026 variant, .github/workflows/security-audit.yml, does four things in a single step, according to StepSecurity's teardown:
- Appends whatever named Actions secrets the attacker found while doing recon on your existing workflows.
- Scans the working tree for 13 credential patterns.
- Runs
git log -p --alland scans the entire history with the same 13 patterns. - For every AWS key ID starting with
AKIAorASIA, grabs two lines either side so the matching secret key comes along too.
The checkout uses fetch-depth: 0, so the runner pulls every branch and every tag. GBHackers, summarizing Socket, adds that the history buffer is capped at 200,000 lines, which tells you the author tested it against big repos and hit limits.
The pattern list is a decent snapshot of what's worth stealing from a developer in late 2026: AWS access keys and session tokens, Anthropic, OpenAI and OpenRouter API keys, GitHub and GitLab tokens, Google and Firebase keys, Slack tokens, and SendGrid keys. AI provider keys are now first-class targets. That lines up with what we saw when METR's agent handed over its own API key and ran up $600,000 in three weeks. Those keys turn into money faster than almost anything else in a repo.
Step three is the part that matters. Every repo has a commit somewhere, often from year one, where someone pasted a key into a config file, noticed, and removed it in the next commit. The team marked it as fixed. The key might even have been rotated. Or it might not, because whoever pasted it left the company and nobody knew which service it belonged to.
git log -p --all doesn't care what you fixed. It prints every diff, including the removed lines, and the regex catches them.
Why the markers tell you more than the payload
StepSecurity found the workflow tagging its exfiltration with URL parameters. ?c=monami means named Actions secrets were found and sent. ?c=new means only the history sweep produced anything. The POST body carries REPO=, then AKIA_CTX_START and AKIA_CTX_END around the captured AWS context.
As of October 9, StepSecurity's code search found 378 repositories still carrying a live copy of the workflow on their default branch. Of those, 182 contained the AKIA_CTX_START history-mining marker and 88 carried ?c=monami. Those counts exclude forks and move daily.
Read that split the way the operator does. The c=new bucket is the interesting one for them: repos where the Actions secrets were empty or locked down, but history still paid out. Someone built a telemetry field specifically to measure how often your old commits are worth more than your current config. That's a business metric, and it means the history sweep is staying in future versions.
The forensics show a human at the keyboard
This wasn't fire-and-forget automation. On pyxel, the malicious workflow ran five times, all successful. Two of those were manual workflow_dispatch triggers at 13:36:32Z and 13:42:35Z, two seconds after the second and third commits to the file. Someone was editing the payload, pushing, and re-running it by hand while watching the result.
On uber/athenadriver, run 37846728441 shows the collection server answering "OK" four seconds after the run started. Four seconds from push to your secrets sitting on someone else's box.
Then there's typecho-fans/plugins. On October 7 the xxyangyoulin account pushed an empty commit and then a README edit titled "Trigger security scan," trying to get the workflow to fire. Both runs stalled in action_required and never sent anything. StepSecurity called the approval gate for workflow runs the only control it saw actually stop the campaign that week.
Socket, per GBHackers, says the attackers looked through existing workflows to find which secrets were referenced and dropped those names into the payload. On pyxel that meant CARGO_REGISTRY_TOKEN, PERSONAL_ACCESS_TOKEN, PYPI_PASSWORD and PYPI_USERNAME. That's crates.io, PyPI and GitHub in one sweep. As of both reports, no malicious package had been published. pyxel's last release, v2.9.9, predates the compromise. That's luck and timing, not a control. A stolen PyPI token is good until someone revokes it.
We've seen this shape before. When the sckit worm took MemTensor's publish tokens straight out of its own CI, the gap between theft and a poisoned release was what decided how bad the incident got. GhostAction has the tokens. The release hasn't happened yet.
Three things the advisories gloss over
The StepSecurity and Socket recommendations are solid: delete the workflow from every branch, revoke the PAT or session that pushed it, rotate everything, block 193.32.204.199, restrict runner egress, protect .github/workflows/* with branch protection. Do all of it. But I've run enough of these cleanups to know where teams get stuck.
You can't rotate what you can't list. "Rotate every credential ever committed to any branch, including deleted ones" is the right instruction, and almost nobody can follow it on the first try. You need an inventory of what was in history. The fastest way to get one is uncomfortable: run the attacker's own scan. Clone with full history, run git log -p --all through your secret scanner, and treat the output as the attacker's loot list. If a key shows up and nobody can say what it unlocks, that's not a reason to skip it. It's the one most likely to still work.
Forks are their own incident. Henry Wu's sweep hit 279 forks. If you forked one of those repos and later turn on Actions in your fork, StepSecurity notes the workflow can run in your account's context. Nobody on your team pushed anything. You just clicked "enable workflows" on a fork you made two years ago.
No DNS means no DNS detection. The payload uses curl over plain HTTP straight to a raw IP on port 80 or 3000. If your egress monitoring for CI runners is based on domain reputation or DNS logs, this traffic never shows up. StepSecurity also lists earlier collection IPs, 45.139.104.115 and 170.39.218.2, plus *.oast.fun. Check runner telemetry back to August 31, which is the start date GitGuardian uses for the 2026 wave. Its own count for August 31 to September 30 is 772 public repositories across 373 users and organizations, with 2,577 secrets targeted. That was before the October 8 sweeps.
The detection angle nobody's using: let history lie for you
Here's my actual opinion. Every guide to this campaign is about cleaning up after it. Very few talk about what history is good for once you accept that attackers will read all of it.
A git history is the perfect place for a honeytoken. Think about what the payload does. It walks every diff, matches an AKIA pattern, grabs two lines either side to pair the secret key, and ships the pair to a server. Its job is to find exactly the kind of credential a developer "accidentally" committed and "removed" in 2023. So put one there.
A decoy AWS key pair, committed in a plausible config file and removed in the next commit, sits in history doing nothing. No legitimate system will ever use it. A developer cloning the repo won't trip over it unless they go looking. A secret scanner will flag it, and you allowlist it once. The only thing that will ever pick it up and call AWS with it is something that went looking through deleted lines for keys to use.
That last step matters. Exfiltration alone doesn't fire a honeytoken. Use does. But harvesters validate what they steal. When we looked at the agentic harvester that checks every key it steals, validation was step one after collection, because a valid key is worth more than a list of maybes. The first sts:GetCallerIdentity against your decoy is an alert with no false positives, because no legitimate process ever had a reason to touch that key. And it fires on the attacker's schedule, which might be days before you'd otherwise find the workflow in a repo you don't watch closely.
Some practical details from setting these up:
- Match the payload's context window. The workflow captures two lines either side of the key ID. Put the decoy secret key on the line directly after the
AKIAID, the way real configs do, so the pairing logic picks up both. A lone key ID with no secret nearby is worth less to an attacker and gets validated less. - One decoy per repo, uniquely tagged. When it fires, you want to know which repo's history leaked. That turns "we were probably in the 345" into "pyxel-fork-ci leaked at 21:24, rotate that repo's real secrets first."
- Use a plausible commit. "Remove hardcoded creds" with an author who actually works on the repo. The history is the bait, so it should look like every other embarrassing commit from year one.
- Put an AI key next to it. The 2026 pattern list added Anthropic, OpenAI and OpenRouter keys. A decoy in that format, routed to something you control, covers the bucket attackers are clearly most hungry for right now.
This is the same lesson from Storm-3168 finding a service principal secret in a GitHub edit history and reaching 100 storage accounts in seven minutes. Attackers read history because defenders treat it as already handled. That blind spot works both ways. If they're going to read every deleted line you ever wrote, some of those lines should be yours on purpose.
The same thinking extends past git. Decoy cloud credentials on build hosts, fake registry tokens in a CI variable nobody references, a canary .env in a fork. Our approach to deception across identity, cloud and network is built around this: put things in places where only an intruder would touch them.
What to do this week
If any repo you maintain gained security-audit.yml or github_actions_security.yml after August 31, treat it as a confirmed breach. Search your org's workflows for 193.32.204.199, AKIA_CTX_START and c=monami. Audit every completed "Security Audit" or "Github Actions Security" run, because each one counts as exfiltration. Don't cut a release until the repo is clean and the publishing tokens are new. Turn on approval for workflow runs from contributors, since that was the one control that stopped the campaign. Then run the history scan yourself and rotate what it finds, starting with anything AWS, any AI provider keys, and registry tokens.
And while you're in that history, leave something behind for the next GhostAction run to find. If you want to see how a decoy AWS key pair in a deleted commit turns into an alert the moment someone tries it, book a Mine2 demo and we'll plant one in a test repo with you.
Arjun
Lead Detection Engineer, Mine2
Arjun builds detection logic at Mine2, focusing on the blind spots EDR and SIEM leave behind and how honeytokens close them.
Latest Articles
'Engage With Us, or We Will Leak It': The ASOS Breach Arrived Through Its Own App
Nearly 20 Million Patients Exposed: Stolen Credentials Unlocked Oracle Health's Unmigrated Cerner Servers
Vouched For by a Stranger: How a Lenovo ID Flaw Opened 5,000 Dropbox Accounts
The Committee That Didn't Exist: TA419's AI Policy Lure and the Kit That Clicks 'Stay Signed In' for You
Need Security Help?
Protect your organization with MINE2's cyber deception platform.
