On 2026-10-08, two hijacked GitHub accounts pushed a "security audit" workflow to 345 repositories, 279 of them forks, in two bursts of 24 and 16 minutes. Nobody reviewed it. It went straight onto the default branch under the owners' own names. The workflow didn't audit anything: it collected the repo's Actions secrets, read the entire git history for API keys, and sent it all over plain HTTP to a raw IP address.
That's the StepSecurity write-up of the GhostAction return, published 2026-10-09. Within a week the same campaign showed up in a different shape (first reported 2026-10-19): a .vscode/tasks.json that runs when you open the folder, a "font" file that isn't a font, and a backup workflow with a boring name.
If you build with AI tools, your repos are full of exactly what it was hunting for: OpenAI, Anthropic, OpenRouter and Firebase keys, some of them committed once and "deleted" later.
TL;DR
Stage one (from 2026-10-08): a workflow you didn't write, named security-audit.yml, github_actions_security.yml or security-check.yml, that sends secrets to 193.32.204.199. Stage two (reported 2026-10-19): a .vscode/tasks.json with runOn: folderOpen that launches public/fonts/fa-solid-400.woff2, plus a fallback workflow with an ordinary name like lint.yml or ci-check.yml. Filenames alone won't clear you: look for any workflow you didn't write. If anything ran, rotate every Actions secret and every key ever committed to that repo, on any branch.
Why a "deleted" key still counts
Most people's mental model is "the key was in the repo for an hour in March, then I removed it." Git doesn't work that way, and this campaign was built around that gap.
StepSecurity calls the history mining the new part of this wave: the workflow ran git log -p --all with fetch-depth: 0, which prints every change to every file on every branch, and grepped it for credential patterns. It even kept two lines of context around AWS key IDs so it could pair each ID with its secret. The list of patterns it looked for reads like an AI app's .env file:
- AWS access keys, secret keys and session tokens
- Anthropic, OpenAI and OpenRouter API keys
- Google / Firebase API keys
- GitHub classic and fine-grained tokens, GitLab tokens
- Slack bot tokens and SendGrid keys
AI coding agents commit fast and often, and "I'll move it to an env var later" is a very normal first draft. If a key was ever in a commit, assume it's in scope.
The two-stage timeline
| Date (2026) | What happened | Source |
|---|---|---|
| Oct 8 | Two maintainer accounts push "security audit" workflows to 27 and 318 repos | StepSecurity |
| Oct 9 | StepSecurity counts 378 repos with the live workflow; GitHub starts blocking it | StepSecurity, The Hacker News |
| Oct 10, 12 | Further workflow waves extract no secrets | The Hacker News |
| ~Oct 15 | Second stage arrives "six days after the block": .vscode/tasks.json launcher, fake font payload, and a fallback workflow | The Hacker News, citing OpenSourceMalware |
| Oct 19 | Second stage first reported, in 94 repos | The Hacker News |
| Oct 19-21 | Attackers "went back to CI with a different goal"; GitGuardian counts five payload families, including ones aimed at self-hosted runners and AWS roles reachable over OIDC | The Hacker News, citing OpenSourceMalware and GitGuardian |
| Oct 26 | Count reaches 1,230 repos across 391 accounts | The Hacker News |
The Hacker News also cites GitGuardian counting more than 72,000 commits to 22,964 public repos between October 13 and 21. Counts across researchers don't line up neatly, and StepSecurity's own figure was "approximate," so treat these as orders of magnitude.
How the attackers got into the accounts isn't settled. StepSecurity's best guess for the October 8 accounts is a personal access token leaked through infostealer logs, and it labels that an inference. The Hacker News also describes a phishing page, sent as a fake GitHub security alert, that captured passwords and 2FA codes and then quietly approved a GitHub OAuth device flow with repo, workflow and read:org scopes. Researchers say that page points at the same IP that receives the stolen data, but haven't tied it directly to GhostAction.
Check your repos (five commands)
Run these from a clone of each repo you own. They're read-only.
Look for workflows you didn't write, on every branch, including deleted ones.
git fetch --all
# Every workflow file added since the campaign started, with author and date
git log --all --since=2026-08-31 --diff-filter=A \
--format='%h %an %ad %s' --date=short --name-only -- .github/workflows/
git log --all --oneline -i --grep="security audit"
Read every file in that list you don't recognise. Stage one used security-audit.yml, github_actions_security.yml and security-check.yml. The stage-two fallback, per The Hacker News, used lint.yml, ci-check.yml, build-check.yml, repo-health.yml, audit.yml, code-review.yml, test-suite.yml or cache-cleanup.yml. Several of those are names real projects use, so open each one rather than going by the name.
Search for the campaign's markers. StepSecurity published the C2 address and a marker string. The second grep searches history too.
grep -rnE "193\.32\.204\.199|AKIA_CTX_START|c=monami" .github/ 2>/dev/null
git log --all -p -S "193.32.204.199" --oneline | head
Look for the stage-two launcher and the fake font. These are the files that run on a developer's machine.
git log --all --oneline -- .vscode/tasks.json public/fonts/fa-solid-400.woff2
grep -n "folderOpen" .vscode/tasks.json 2>/dev/null
# A real WOFF2 font starts with the bytes "wOF2"
head -c 4 public/fonts/fa-solid-400.woff2 2>/dev/null; echo
That filename is a small giveaway. Font Awesome's solid icon set ships as fa-solid-900.woff2, because solid is the 900 weight. A file called fa-solid-400 sitting next to a brand-new tasks.json deserves a hard look. If the first four bytes aren't wOF2, it isn't a font.
If you (or a teammate) opened a repo with these files in a trusted editor, treat that machine as compromised too. The Hacker News says the stealer installs a cron job that runs attacker code every five minutes, so check crontab -l for entries you didn't add, and rotate what that machine could reach, not just the repo's secrets.
Check whether anything actually ran. In GitHub, open your repo's Actions tab and look for runs named "Security Audit", runs of any workflow from step 1, and anything triggered by push or workflow_dispatch that you didn't start. If you use self-hosted runners, check those too: one payload family targets them. StepSecurity recommends auditing runs back to August 31, 2026.
Check your account, not just your repos. Go to Settings, Applications, Authorized OAuth Apps and revoke anything you don't recognise, especially an app holding repo and workflow scopes. Then Settings, Developer settings, Personal access tokens: delete tokens you aren't using and anything with no expiry. Finally, check your gists for secret gists you didn't create: the stage-two workflow falls back to uploading what it finds to one.
If you find it
Order matters. Rotating keys while the attacker still holds your GitHub session just hands them the new ones.
- Revoke GitHub access from a clean device. Sign out other sessions, revoke PATs and OAuth grants, change your password, and move 2FA to a passkey or security key. The phishing page reported alongside this campaign relayed one-time codes in real time, and a passkey shuts that out.
- Rotate every Actions secret in the affected repos.
- Rotate every credential that was ever committed to any branch, even ones removed long ago. Our key rotation guide covers the usual suspects.
- Delete the workflow and the tasks file from every branch, not just
main. Check your forks too: one of the October 8 accounts pushed to 279 forks. - Hold off on releases until it's clean. StepSecurity's advice is to assume publishing secrets (npm tokens and similar) are exposed.
- Tell anyone who cloned the repo. Stage two runs on their machine when they open it in a trusted editor.
Rewriting history with BFG or git filter-repo doesn't un-leak a key. If it was ever pushed to GitHub, rotate it. Clean the history afterwards if you want to, using our guide to removing secrets from git history.
Make the next one bounce off
Each of these would have blunted a specific part of this campaign:
- Protect the default branch. Require a pull request to merge into
main. The stage-one commits were pushed directly to default branches with no PR. - Require approval for workflow runs. StepSecurity notes one repo that required approval stopped an exfiltration attempt. It won't stop a push made with your own hijacked account, which is why branch protection comes first.
- Use fine-grained tokens with an expiry, scoped to the repos that need them, instead of a classic PAT that reaches everything you own.
- Don't trust a cloned repo by reflex. When your editor asks whether you trust a folder's authors, a template or "example project" from a stranger is exactly when to say no and read
.vscode/first.
Where CheckYourVibe fits
Our scanner looks at your deployed app from the outside, not at your GitHub account, so it won't find a malicious workflow. What it does find is the other half of the same problem: API keys that have already left the building. The OpenAI, Anthropic and Firebase keys GhostAction mined from git history are the same ones we routinely find shipped inside JavaScript bundles. If you're rotating anyway, scan your live app afterwards to make sure the new keys didn't end up in the frontend.
I found a security-audit.yml in my repo that I didn't add. What do I do?
Don't just delete it. First check its git log entry and whether it ever ran in the Actions tab. If it did run, assume every Actions secret in that repo and every credential ever committed to any branch was sent to the attacker. Revoke your GitHub tokens and sessions from a clean device, rotate those credentials, then remove the file from every branch.
Why does it matter if a key was deleted from my repo years ago?
The October 2026 GhostAction workflow ran git log -p --all with full fetch depth, which reads every version of every file on every branch. A key you removed in a later commit is still in history, and this campaign mined history for it on purpose.
Can just opening a cloned repo infect me?
With the second GhostAction stage, yes. It added a .vscode/tasks.json with a runOn: folderOpen task, so a VS Code-based editor runs it when the folder opens in a trusted workspace. The task launched a payload disguised as public/fonts/fa-solid-400.woff2.
Did GitHub stop this?
Partly. According to The Hacker News, GitHub began blocking the malicious workflow on October 9, 2026, and waves on October 10 and 12 extracted no secrets. The second stage, which arrived about six days after the block, added a launcher that runs on developers' machines when they open the repo, plus a fallback workflow under ordinary names like lint.yml or ci-check.yml. So the block didn't end it.
How did attackers get into the accounts?
Not fully confirmed. StepSecurity's most plausible explanation for the October 8 accounts is a personal access token leaked through infostealer logs or credential dumps. The Hacker News also describes a phishing page that captured passwords and 2FA codes and silently approved a GitHub OAuth device flow with repo, workflow and read:org scopes, though researchers haven't tied that page directly to GhostAction.
Rotated your keys? Make sure they stayed secret
CheckYourVibe checks your live app for API keys in the frontend bundle, open configs and other leaks, in plain English.