An attacker holding stolen credentials for 4,837 GitHub accounts has used them to probe 61,764 repositories and plant a CI secret stealer that ran in at least 1,806 of them, according to research published on November 12 by Aikido Security. The firm is tracking the operation as wfx-loot, after the name the malware gives itself and the word it uses for stolen secrets.
The campaign started at about 12:45 UTC on November 10 (7:45 AM ET) and was still active on November 12. StepSecurity reported that GitHub search returned more than 63,000 of the attacker’s probe pull requests as of 07:40 UTC that day, with about 90% still open and new ones appearing every few minutes.
How the attack works
No flaw in GitHub Actions is involved. The attacker signs in as real developers and bot accounts, then works through every repository each stolen token can write to. Many of the targets belong to other people: Aikido counted 10,431 pull requests that landed in repositories the account does not own, reached through collaborator or organization access.
Each attack follows three steps:
- Probe. A pull request titled
docs: dependency audit notesfrom awfx-docsbranch adds a two-line file,docs/wfx-audit.md. It does nothing harmful but confirms write access. - Payload. The attacker pushes a shell script of about 1,500 lines. It is added to an existing workflow (
ci: refresh build cache), dropped as a hidden.ci-xxxxxx.shfile run by apostinstallhook inpackage.json(chore: add ci helper), added as a newbuild-audit-xxxxxx.ymlworkflow on a throwawaychore/branch, or pasted into a shell script that CI already runs. - Cleanup. A revert commit (
ci: restoreorci: cleanup) usually follows within a minute, and the workflow run and its logs are deleted. A missing run number in the Actions tab is often the only trace.
Endor Labs, which tracked the payload through 5 versions, said more than 8,500 repositories show payload commits, over 700 of them with install hooks. Commits alone do not prove the stealer ran. Endor also found that 1,838 repositories hit in the first wave were hit again by the newest version, so secrets rotated after the first attack may have been stolen a second time.
What the stealer takes
The script grabs every GitHub Actions secret and variable through ${{ toJSON(secrets) }}, plus the job’s GITHUB_TOKEN and OIDC tokens. It also scans the memory of the runner process for secrets and collects credential files for AWS, Azure, GCP, Docker, Kubernetes, npm, PyPI, SSH and Vault, along with API keys for AI providers and coding tools such as OpenAI, Anthropic, Gemini, Hugging Face, Cursor and Copilot.
It then tries to go deeper. It swaps OIDC tokens for cloud sessions, creates long-lived AWS access keys, rewrites AWS role trust policies to "Principal": {"AWS": "*"} and adds Azure federated identity credentials named wfx-ci-*. Those back doors can survive a normal secret rotation.
Stolen data was first sent by HTTP POST to 194.150.166[.]244:8080/exfil and 18.143.168[.]96:8080/exfil. StepSecurity found that from about 05:30 UTC on November 12, new copies sent data only to a Telegram chat, so blocking those IP addresses no longer stops the newest version.
Known victims and packages
Public victims include nextcloud/docker and webdriverio/webdriverio, where the attacker pushed commits through bot accounts. In the WebdriverIO case, the bot was allowed to bypass branch protection, and a contributor flagged the commits within about 20 minutes. StepSecurity said no WebdriverIO package release was affected.
At least 50 of the hijacked accounts publish packages. Confirmed bad versions so far are Packagist digitalelvis/neuronai-studio 3.14.3 and Go module github.com/onuragtas/docker-env v1.0.278 and v1.0.280. In the Go versions, the payload sits only in a workflow file that normal builds never run.
How the accounts were compromised is not confirmed. One victim reported a leaked GitHub CLI OAuth token. StepSecurity found 173 probe pull requests made through the Fly.io GitHub App and said it has no evidence of a breach of Fly.io’s own systems. Aikido noted overlap with accounts hit in the October GhostAction wave but assesses the two as separate campaigns. GitHub had not published a statement on the campaign at the time of writing.
What to do now
- Search pull requests and commits since November 10 for the titles above and for
wfx-docs,chore/andci-check-branches. A probe pull request means the account that opened it is compromised. - Check the Actions tab for a gap in run numbers right after a suspicious commit.
- If the stealer ran, rotate every secret, registry token and cloud credential the workflow could reach, not just the ones it names.
- Remove persistence: AWS trust policies open to
"AWS": "*", IAM keys created since November 10, and Azure credentials namedwfx-ci-*. - Revoke the account’s tokens, OAuth grants, SSH keys and sessions, and review which bot accounts can bypass branch protection.
Full indicators are available in the Aikido Security report, the StepSecurity analysis and the Endor Labs write-up.
The campaign follows other recent attacks on developer pipelines, including the Mini Shai-Hulud malware that abused trusted CI pipelines and the TeamPCP worm tied to the TeamPCP group. No link between those operations and wfx-loot has been reported.












