Researchers at Aikido, SafeDep, StepSecurity and OX Security report that, starting around 12:45 UTC on 10 November 2026 (14:45 Asia/Jerusalem), an attacker used stolen credentials for thousands of GitHub accounts to push a credential-stealing script into repositories those accounts could write to. Aikido, which named the campaign wfx-loot, counts 4,837 compromised accounts that opened probe pull requests in 61,764 repositories, and says the stealer ran in at least 1,806 of them. The stealer targets the secrets and cloud credentials that GitHub Actions workflows can reach, and sometimes runs on developer machines through an npm postinstall hook.
How the accounts were compromised is unconfirmed: Aikido's analysis does not explain how the credentials were obtained, and StepSecurity says the attacker "does not exploit a bug in GitHub Actions" but uses valid tokens for real developer and bot accounts. GitHub has not published a statement on the campaign on its blog or changelog as of 13 November 2026, 08:25 Asia/Jerusalem UTC+2. StepSecurity traced 173 probe pull requests to tokens issued to the Fly.io GitHub App and said it had no evidence of a breach of Fly.io's own infrastructure. Fly.io later stated that its systems were not breached: the tokens were read from .git/config files that some customer apps were serving publicly, and Fly.io has begun revoking every user token issued to its GitHub App. Researchers say the campaign was still active on 12 November.
Technical Information
The researchers describe three steps. First, a probe: a pull request titled docs: dependency audit notes from a wfx-docs branch that confirms the token can write to the repository. Aikido, SafeDep and StepSecurity all say a probe pull request on its own means the account that opened it is compromised, even if nothing followed. Second, the payload: a plain, unobfuscated shell script of about 1,500 lines, delivered by adding steps to an existing workflow (ci: refresh build cache), adding a .ci-xxxxxx.sh script plus an npm postinstall hook (chore: add ci helper), or adding a new workflow file on a short-lived chore/ branch. Third, cleanup: the attacker reverts with ci: restore or ci: cleanup within minutes and deletes the workflow run and its logs. Aikido and StepSecurity say a missing run number in the Actions history right after the attacker's commit is often the most reliable remaining trace.
According to Aikido and SafeDep, the script collects repository secrets and variables, the workflow GITHUB_TOKEN, OIDC and Actions runtime tokens, cloud and registry credential files, AI-provider keys, and tokens in runner process memory. It requests GitHub OIDC tokens for AWS, Azure and GCP and tries to exchange them for cloud sessions. The researchers describe persistence designed to survive secret rotation: creating AWS access keys, rewriting AWS role trust policies, and adding Entra ID federated credentials named wfx-ci-*.
Stolen data went by HTTP POST to port 8080 on collection servers. StepSecurity and OX report that from about 05:30 UTC on 12 November new copies sent data only to a Telegram chat, so blocking the published IP addresses alone is no longer enough.
On scale, each figure is the researcher's own, from public data:
- Aikido: 4,837 accounts; 61,839 probe pull requests between 10 November 12:45 UTC and 11 November 15:00 UTC; 10,431 reached repositories the account does not own through collaborator or organisation access; at least 50 compromised users appear to publish packages to npm, Go, Packagist, PyPI or crates. (Aikido's summary says 1,835 repositories ran the payload; its detailed section says at least 1,806.)
- SafeDep: 8,093 repositories received malicious commits between 10 November 12:46 UTC and 12 November 04:36 UTC — 7,309 via workflow injection, 771 via npm
postinstallhooks and 16 via new workflow files. That counts commits, not confirmed executions, and covers only default branches of public repositories. - StepSecurity / OX: more than 63,000 probe pull requests by 07:40 UTC on 12 November (StepSecurity); more than 66,200 later that day (OX).
Aikido notes overlap with accounts hit in October's GhostAction wave but assesses them as distinct campaigns, likely by different actors.
Affected Product Versions
There is no product vulnerability or CVE. In scope are repositories a compromised account or token could write to, and the secrets and cloud roles their workflows reach. Researchers also identified poisoned releases from automated publishing:
| Package | Versions named by researchers | Notes |
|---|---|---|
Packagist digitalelvis/neuronai-studio |
3.14.3 | Aikido, SafeDep, OX. Flagged as malware on Packagist; 3.14.4 published 12 Nov. SafeDep: composer install does not run it; npm install inside the package's vendor directory does. Pin 3.14.2 or earlier, or, per OX, move to 3.14.4. |
Go github.com/onuragtas/docker-env (renamed redock) |
v1.0.278, v1.0.280; SafeDep and OX add v1.0.282 | Payload only in a workflow file; Go builds do not run workflow files. Researchers still advise removing them. |
Go github.com/vkuznet/gocurl |
v0.0.0-20261111095532-8d5aad0cb0da | SafeDep and OX. SafeDep says the workflow never ran; block the pseudo-version. |
SafeDep checked 218 npm, Go and Packagist packages whose source repositories received malicious commits and found no other poisoned version; PyPI and other registries were not checked.
Workaround and Mitigation
- Check every repository you can write to from 10 November onward for the probe pull request,
wfx-docs,chore/+ 8 characters orci-check-+ 4 digits branches, and the commit messages above. Review git history, since the attacker reverts, and look for gaps in workflow run numbers and deleted runs in the audit log. - If a probe appears, treat the account as compromised. Revoke its personal access tokens, OAuth app grants, SSH keys and sessions, and enforce 2FA (SafeDep).
- If a malicious commit landed where Actions is enabled, rotate every repository, environment and organisation secret and variable the workflow could read, even if no run is visible. Anyone who ran
npm installon an affected commit should treat that machine as compromised. - Hunt for cloud persistence, because rotation does not remove it: Entra ID federated credentials named
wfx-ci-*; AWS CloudTrailAssumeRoleWithWebIdentityorAssumeRolesessions namedwfx-*followed byCreateAccessKeyorUpdateAssumeRolePolicy; GCPGenerateAccessToken/SignJwtfrom the GitHub workload identity pool; Vault JWT logins from the GitHub OIDC issuer. - If you connected GitHub to Fly.io, reconnect and check the repositories its app can access, per Fly.io.
- Harden for next time using GitHub's public guidance: give
GITHUB_TOKENleast-privilege permissions, scope cloud OIDC trust to specific repositories and branches, and pin third-party actions to full-length commit SHAs. Where builds do not need lifecycle scripts, npm'signore-scriptssetting stopspostinstallhooks from running. Neither stops an attacker who already holds a write token.
Indicators of Compromise
Published by the researchers as hunting leads, not standalone proof:
| Type | Indicator | Source |
|---|---|---|
| PR title / branch | docs: dependency audit notes / wfx-docs; file docs/wfx-audit.md |
Aikido, SafeDep, StepSecurity, Fly.io |
| Branch patterns | chore/[a-z0-9]{8}, ci-check-[0-9]{4} |
Aikido (SafeDep did not see these in its samples) |
| Commit messages | ci: refresh build cache, chore: add ci helper, chore: add dependency audit workflow, ci: restore, ci: cleanup |
Aikido, SafeDep |
| SHA-256 (stealer script) | 89695abb392d5cfd4972672961e644bb46baa98aa1ed7173c2a2816c762735cf | Aikido, OX |
| Collection endpoints | 194.150.166[.]244:8080/exfil, 18.143.168[.]96:8080/exfil, 153.75.82[.]159:8080 | Aikido, SafeDep (third IP); cloud-hosted IPs may be reassigned |
| Telegram | api.telegram[.]org sendDocument to chat -1004340163187 |
SafeDep, StepSecurity, OX |
| Campaign token | b42d70a7aab9140ca19e8249 | Aikido, SafeDep |
What to Ask Your Suppliers Today
Ask software suppliers, SaaS providers and MSPs whose CI pipelines handle your data or credentials:
- Have you searched every repository and organisation you control for the wfx-loot indicators since 10 November? Yes/no, scope (public and private), and named owner.
- Did any account in your organisation, including bot accounts, open a probe pull request or author a malicious commit? If yes, which tokens were revoked and when.
- Have you rotated every CI secret and cloud role reachable from affected workflows, and checked AWS, Azure, GCP and Vault for the persistence researchers describe? Completion date.
- Did you publish any package or release between a malicious commit and its revert? Which versions were pulled or re-published.
- Do your GitHub Actions hold credentials we issued you, and what controls limit CI token scope and catch unreviewed pushes? Token lifetimes, branch rules for bot accounts, OIDC trust conditions, and whether we should rotate on our side.
Track incomplete answers to closure. These are qualitative TPRM follow-ups, not a prevalence claim.
Need help working through software and SaaS suppliers whose CI pipelines may have been touched by wfx-loot? Our team can help you prioritize them and track their answers. Talk to an expert
Sources
- Aikido, 12 November 2026 — primary research; figures; no credential origin; no GhostAction attribution.
- SafeDep, 12 November 2026 — 8,093 repositories; package impact; remediation.
- StepSecurity, 12 November 2026 — not a GitHub Actions bug; Fly.io app tokens; no evidence of a Fly.io breach.
- OX Security, 12 November 2026 — campaign ongoing; IOCs.
- Fly.io community, 13 November 2026 — systems not breached; token revocation initiated.
- Packagist: digitalelvis/neuronai-studio — malware flag; v3.14.4 published 12 November.
- BleepingComputer, 13 November 2026 and The Hacker News, 12 November 2026
- GitHub guidance: Secure use of Actions, OIDC in AWS; npm
ignore-scripts.



