What to check now
- Exploited?
- Aikido Security says that starting at approximately 12:45 UTC on November 10, 2026, a threat actor used stolen GitHub credentials to push a CI secret stealer into repositories those accounts could write to, and that it identified indications the payload ran in at least 1,806 repositories (the same post also says at least 1,835). SafeDep and StepSecurity report the same campaign. This is not a bug in GitHub Actions: the attacker uses valid tokens for real developer and bot accounts.
What is affected
| Product | Affected | Status | Source |
|---|---|---|---|
| GitHub repositories that a compromised account or token can write to | Aikido counted 4,837 compromised accounts opening probe pull requests in 61,764 repositories (SafeDep's search found 4,833 accounts), and indications the payload ran in at least 1,806 (the same post also says at least 1,835). SafeDep counted 8,093 repositories that received malicious commits between November 10, 12:46 UTC and November 12, 04:36 UTC, on default branches of public repositories only. | No CVE and no patch: the attacker uses stolen credentials, not a GitHub flaw. Revoke the account's access and rotate every secret the workflows could reach. | Aikido Security (November 12, 2026), checked |
| Packages published from affected repositories | Packagist digitalelvis/neuronai-studio 3.14.3; Go github.com/onuragtas/docker-env v1.0.278 and v1.0.280, plus v1.0.282 and the alias path github.com/onuragtas/redock per SafeDep; Go github.com/vkuznet/gocurl pseudo-version v0.0.0-20261111095532-8d5aad0cb0da per SafeDep and StepSecurity. | Block those versions. For neuronai-studio, pin 3.14.2 or earlier. | SafeDep, wfx: GitHub Actions Credential Stealer Hits 8,000 Repos, checked |
Owner checklist
- Search every repository you can write to, from November 10 onward, for a pull request titled docs: dependency audit notes from a wfx-docs branch, and for commits titled ci: refresh build cache, chore: add ci helper, chore: add dependency audit workflow, ci: restore or ci: cleanup.
- For each hit, open the Actions tab and look for a missing run number right after the attacker's commit. Aikido and StepSecurity say that gap is the most reliable sign the stealer ran.
- Treat the account that opened the probe or pushed the commits as compromised: revoke its personal access tokens, OAuth app grants, SSH keys and sessions, and turn on 2FA.
- Remove the persistence the researchers describe in AWS, Azure, GCP and Vault, because rotation alone does not remove it.
- If the stealer ran, rotate every repository, environment and organization secret the job could reach, npm and other publishing tokens, and cloud credentials, including any reachable through OIDC.
There is no patch
- There is nothing to patch. This campaign uses valid, stolen GitHub credentials. Revoke the compromised account's access, rotate secrets, and remove any cloud persistence. Absence of wfx-loot artifacts, wfx- cache entries or WFX-BEGIN step summaries does not mean data was not taken, Aikido says.
How to check for compromise
- Pull requests titled docs: dependency audit notes from a wfx-docs branch, adding docs/wfx-audit.md (StepSecurity).
- Branches matching chore/ plus eight characters or ci-check- plus four digits (Aikido, StepSecurity); files .ci-<6 characters>.sh and .github/workflows/build-audit-<6 characters>.yml; a package.json script (usually postinstall) that runs a hidden .ci-*.sh file.
- A gap in Actions run numbers right after one of those commits.
- Outbound connections to 194.150.166[.]244:8080, 18.143.168[.]96:8080 or 153.75.82[.]159:8080 (/exfil), or uploads to api.telegram.org from a build job.
- Azure federated identity credentials named wfx-ci-*; AWS role trust policies containing "Principal": {"AWS": "*"}; CloudTrail sessions named wfx-* followed by CreateAccessKey or UpdateAssumeRolePolicy.
TL;DR: Starting at approximately 12:45 UTC on November 10, 2026 (8:45 p.m. Manila), an attacker used stolen credentials for GitHub accounts to push a CI secret stealer into repositories those accounts could write to, Aikido Security reports. Aikido tracks it as wfx-loot and counts 4,837 compromised accounts that opened probe pull requests in 61,764 repositories, and indications the stealer ran in at least 1,806 (the same post also says at least 1,835). SafeDep separately counted 8,093 public repositories that received malicious commits, which is not the same as the stealer running. The campaign was still active as of StepSecurity’s 07:40 UTC check on November 12 (3:40 p.m. Manila). The stealer takes GitHub Actions secrets, cloud credentials and tokens from runner memory, then the attacker reverts the commit and deletes the workflow run. Search your repositories for a docs: dependency audit notes pull request from a wfx-docs branch, look for a missing Actions run number after the attacker’s commit, and if it ran, rotate every secret that workflow could reach.
What happened
This is account hijacking with stolen credentials, not a bug in GitHub Actions. StepSecurity writes that the attacker “has valid tokens for real developer and bot accounts, and it uses them the way a developer would.” None of the three research posts says how the credentials were stolen.
For each repository a stolen token can write to, the researchers describe the same three steps:
- Probe. The attacker opens a pull request titled
docs: dependency audit notesfrom a branch namedwfx-docs. StepSecurity says it adds one file,docs/wfx-audit.md. The pull request does nothing by itself; it confirms the token can write. Aikido and SafeDep both say that if you see one, the account that opened it is compromised, even if nothing else followed. - Payload. The attacker pushes a shell script of about 1,500 lines in one of these forms:
ci: refresh build cache: steps added to an existing workflow. StepSecurity also found the script appended to ordinary shell scripts that a workflow already runs, such asupdate.sh.chore: add ci helper: a hidden.ci-<6 characters>.shfile plus apackage.jsonscript that runs it. In StepSecurity’s samples the hooked script waspostinstall11 times,buildtwice andtestonce. Apostinstallhook also runs on a developer’s machine duringnpm install.chore: add dependency audit workflow: a new.github/workflows/build-audit-<6 characters>.yml, on a throwawaychore/<8 characters>branch per Aikido and StepSecurity. SafeDep says empty repositories first get achore: initial commit.
- Cleanup. The attacker pushes a revert (
ci: restore, sometimes followed byci: cleanup) and deletes the workflow run with its logs. StepSecurity says this happens “usually within a minute.” It is not a hard limit: SafeDep’s example payload stayed in for about four minutes (14:01 to 14:05 UTC), and SafeDep found a few repositories where the payload was still live. A clean default branch is not proof you were missed.
What it steals
All three research teams describe the same script. It collects every GitHub Actions secret and variable, the workflow’s GITHUB_TOKEN, OIDC and Actions runtime tokens, and the memory of the runner’s Runner.Worker and Runner.Listener processes. StepSecurity notes that the memory scan catches decrypted secrets the workflow never referenced. It also reads credential files for AWS, Azure, GCP, Docker, Kubernetes, npm, PyPI, SSH and Vault, plus API keys for AI providers and coding tools. On self-hosted runners it takes cloud instance-metadata credentials too.
It then tries to go deeper and stay. It exchanges GitHub OIDC tokens for AWS, GCP and Azure sessions. On AWS it can rewrite a role’s trust policy to "Principal": {"AWS": "*"} and create long-lived IAM access keys. On Azure it can add a federated identity credential named wfx-ci-… to app registrations, so workflows in the compromised repository can sign in with no stored secret, even after you rotate. Aikido also describes forged “success” status checks that could clear branch protection; StepSecurity says that feature was not switched on in any of the 101 copies it examined, and SafeDep says no sample it analyzed switched it on.
Where the data goes
Aikido’s post lists two HTTP collection servers; SafeDep and StepSecurity found a third, plus Telegram. Stolen data is sent by HTTP POST to port 8080 on 194.150.166[.]244, 18.143.168[.]96 or 153.75.82[.]159, or to a Telegram chat. StepSecurity says copies from about 05:30 UTC on November 12 (1:30 p.m. Manila) send only to Telegram and carry no collection IP at all, so blocklists built from the November 10 addresses miss the newest copies. In SafeDep’s sample of 200 payload commits, about a fifth used Telegram only.
How big it is, by source
The three teams counted different things at different times, so their numbers do not match:
- Aikido: 4,837 compromised accounts opened probe pull requests in 61,764 repositories. GitHub search returned 61,839 probe pull requests opened between November 10, 12:45 UTC and November 11, 15:00 UTC. 10,431 went into repositories the account does not own, through collaborator or organization access, and 92% of those were still open. Aikido’s article body says it identified indications that the payload ran in “at least 1,806 repositories” and that this “may understate impact”; its summary list at the top of the same post says “at least 1,835.” Neither SafeDep nor StepSecurity gives a “ran” count. At least 50 compromised users appear to publish packages for npm, Go, Packagist, PyPI or crates.
- SafeDep: 61,879 probe pull requests in 61,734 repositories, opened from 4,833 accounts, 91% still open. Between November 10, 12:46 UTC and November 12, 04:36 UTC, 8,093 repositories received malicious commits: 7,309 by workflow injection, 771 by
postinstallhook and 16 by a new workflow file. In 1,343 repositories the commit author was an account other than the owner, such as a collaborator or a bot. SafeDep’s search covers only default branches of public repositories, so it says the true total is higher. - StepSecurity: As of 07:40 UTC on November 12 (3:40 p.m. Manila), GitHub search returned more than 63,000 probe pull requests, about 90% still open, with new ones still appearing. Commit search returned more than 21,000
ci: refresh build cachecommits between November 10 and 12.
StepSecurity says the stolen tokens included bot accounts. In WebdriverIO, commits were pushed as the wdio-bot account, which could bypass branch protection; StepSecurity counts 56 chore: add ci helper commits across 28 WebdriverIO repositories, and both StepSecurity and SafeDep say no WebdriverIO package release was affected.
Packages
Where a repository publishes automatically, the stealer reached a release:
- Packagist
digitalelvis/neuronai-studio3.14.3.composer installdoes not run the payload, butnpm installinside the package directory does. Pin 3.14.2 or earlier. - Go
github.com/onuragtas/docker-envv1.0.278 and v1.0.280 (Aikido, SafeDep, StepSecurity). SafeDep adds v1.0.282 and says the module is also served asgithub.com/onuragtas/redock. The payload is only in a GitHub Actions workflow file; Go builds never run workflow files, but block those versions. - Go
github.com/vkuznet/gocurlpseudo-versionv0.0.0-20261111095532-8d5aad0cb0da(SafeDep, StepSecurity). Same: a workflow file only. Block it.
SafeDep says a scan of 218 npm, Go and Packagist packages whose source repositories received malicious commits found no other published version with the payload; PyPI and other registries were not checked.
Link to October’s GhostAction wave
Aikido says accounts hit in the October GhostAction wave were significantly more likely to be hit this time, and that in more than 100 repositories wfx-loot was injected into GhostAction’s leftover workflow files. Aikido still assesses them as distinct campaigns, likely by different actors, because the infrastructure, tooling and tradecraft differ, and StepSecurity says the overlap does not prove a single actor. StepSecurity’s advice: if you were hit in October, check for this wave too. Our GhostAction coverage has the October indicators.
What GitHub has said
As of our check at 5:19 p.m. Manila (UTC+8) on November 12, we found no public GitHub blog post, changelog entry or advisory about this campaign.
Was I hit?
Do this for every repository you, your team or your bots can write to, including repositories you collaborate on and private repositories. The public counts above are only what researchers could see.
- Search pull requests for the title
docs: dependency audit notesand branches namedwfx-docs,chore/<8 characters>orci-check-<4 digits>(the last two patterns are from Aikido and StepSecurity; SafeDep says they did not appear in its own samples), from November 10 onward. A probe pull request alone means the account that opened it is compromised. - Search commits since November 10 for
ci: refresh build cache,chore: add ci helper,chore: add dependency audit workflow,chore: initial commitfollowed by a new workflow,ci: restoreandci: cleanup. Look at who authored them; SafeDep says the commits are authored as real users, with their noreply email and no signature. - Check the Actions tab for a gap in run numbers right after the attacker’s commit. A missing run means the stealer probably ran and the run was deleted. If the run survived, StepSecurity says its log can show the stealer’s notes, such as
archive_bytes. - If you own a GitHub organization, read its audit log for deleted workflow runs and unexpected token activity since November 10.
- Look in the files:
docs/wfx-audit.md,.ci-<6 characters>.shat the repository root,.github/workflows/build-audit-<6 characters>.yml, apackage.jsonscript (postinstall,buildortest) that runs a hidden.ci-*.shfile, unexpected edits to shell scripts your CI already runs, and workflow steps namedPass runtimeandRestore cache <4 characters>orRun audit. Also check git history, not just the current branch, because the attacker reverts. - Check lockfiles (
composer.lock,go.sum) for the package versions above, and any package you published between a malicious commit and itsci: cleanuprevert. - Check network logs for build jobs that reached the three collection IPs above or
api.telegram.org.
Aikido warns that the absence of wfx-loot artifacts, wfx- cache entries or WFX-BEGIN step summaries does not mean data was not taken. Those channels were switched off in this campaign.
What to rotate
If the stealer ran, Aikido’s advice is to “assume every secret and cloud role available to its workflows is compromised.” Work in this order, because rotation alone does not remove the cloud backdoors:
- Lock down the compromised GitHub account first. Revoke its personal access tokens, OAuth app grants and SSH keys, sign out its sessions, and turn on 2FA (SafeDep). For bot accounts, review whether they need to bypass branch protection at all; StepSecurity says stolen bot tokens were used, including
wdio-bot. - Remove persistence that survives rotation.
- Azure / Entra ID: delete federated identity credentials named
wfx-ci-*that you did not create. - AWS: look for role trust policies containing
"Principal": {"AWS": "*"}, IAM user access keys created since November 10, and CloudTrailAssumeRoleWithWebIdentityorAssumeRolesessions namedwfx-*followed byCreateAccessKeyorUpdateAssumeRolePolicy. - GCP: review
GenerateAccessTokenandSignJwtcalls from your GitHub workload identity pool. - Vault and Kubernetes: review JWT logins from the GitHub OIDC issuer (
token.actions.githubusercontent.com).
- Azure / Entra ID: delete federated identity credentials named
- Rotate every GitHub Actions secret and variable at repository, environment and organization level that the job could read. Do not stop at the secrets the workflow names; StepSecurity says the memory scan collects the rest. Then rotate cloud credentials reachable through OIDC trust and any long-lived keys stored as secrets. On self-hosted runners, also rotate the host’s own credentials.
- Rotate package-registry publishing tokens (npm, PyPI, Packagist, crates and similar). Block the known-bad versions above and republish from a clean commit (SafeDep). Our compromised package checklist covers the rebuild.
- Rotate AI-provider and coding-agent keys the runner or a developer machine could reach; Aikido lists OpenAI, Anthropic/Claude, Gemini, Hugging Face and others. Our Claude Code secret-leak fix covers keeping those keys out of repositories.
- Developer machines. If anyone ran
npm install(or the hookedbuildortestscript) on an affected commit, treat that machine as compromised and rotate its local keys, such as SSH keys, git credentials and cloud CLI logins (SafeDep, StepSecurity). - Clean up on GitHub. Delete leftover
wfx-docsandchore/*branches, close the probe pull requests, and check that no commit merged on a forged required check (StepSecurity).
For a step-by-step rotation order for each key (inventory, create new, deploy, then revoke the old), use our leaked-secrets rotation checklist.
Harden for next time
These are general GitHub and npm settings, not steps from the research posts. None of them stops an attacker who already holds a valid token with write access, but they shrink what that token can reach:
- Require 2FA for everyone in your organization, and remove write access that people and bots no longer need.
- Set the default
GITHUB_TOKENpermission to read-only and grant more per workflow. StepSecurity notes the injected workflow addsstatuses: write, so an unexpected permissions change in a diff is worth a look. - Keep cloud and publishing secrets in environments with required reviewers, so a push alone cannot reach them, and prefer short-lived OIDC roles scoped to specific branches over long-lived keys.
- Pin third-party actions to a full commit SHA, not a tag.
- Run
npm ci --ignore-scripts(or setignore-scripts=true) where you can, so apostinstallhook does not run on install. - Restrict egress from build runners where your setup allows it. StepSecurity notes that neither a bare IP nor
api.telegram.orgbelongs in a normal build.
Other alerts are on our security coverage hub.
Updates
- Nov 12, 2026, 5:22 p.m. Manila (UTC+8): Initial report covering Aikido Security’s wfx-loot analysis, SafeDep’s wfx analysis and StepSecurity’s WFX Phantom analysis. Aikido’s and StepSecurity’s posts are dated November 12, 2026. No public GitHub blog post, changelog entry or advisory found as of this check.
Sources & method
- Aikido Security (Oliver Smith), wfx-loot campaign pushes CI secret stealer to tens of thousands of repositories (November 12, 2026) — https://www.aikido.dev/blog/compromised-github-accounts-push-ci-secret-stealer-to-tens-of-thousands-of-repositories
- SafeDep, wfx: GitHub Actions Credential Stealer Hits 8,000 Repos (no publication date shown on the page we read; its counts run to November 12, 04:36 UTC) — https://safedep.io/blog/github-actions-wfx-credential-stealer
- StepSecurity (Owais Shaikh), WFX Phantom: The GitHub Actions Secret Stealer That Deletes Its Tracks (November 12, 2026) — https://www.stepsecurity.io/blog/wfx-phantom-the-github-actions-secret-stealer
- GitHub Changelog (checked for a statement; none found) — https://github.blog/changelog/
Last checked: Nov 12, 2026, 5:19 p.m. Manila (UTC+8). Method: We read the Aikido, SafeDep and StepSecurity posts at about 5:19 p.m. Manila (UTC+8) and checked them against SEO’s fact table, and took every number, name, date and indicator from them, attributed to the team that reported it. The three teams counted different things at different times, so we list each figure with its source instead of merging them. Aikido’s post gives two payload counts, “at least 1,806” in its body and “at least 1,835” in its summary list; we give both. Aikido’s single stealer-script hash is not listed as an indicator because StepSecurity found no two copies share a hash. We found the campaign through The Hacker News but did not use it as a source for any fact. We left out the attacker’s Telegram bot tokens that one research team lists. The hardening section is general GitHub and npm practice, not advice from the research posts. Thumbnail is a reuse-licensed image, credited with its license under the picture. No affiliate links. How we work.
Spotted an error? See our corrections policy and tell us.



