Actively exploited Security news
wfx-loot: attacker uses stolen GitHub tokens to plant a CI secret stealer in thousands of repositories
On 12 November 2026 researchers at Aikido Security and StepSecurity described a campaign that has been abusing stolen GitHub tokens since 10 November. From nearly 5,000 accounts the attacker opened more than 60,000 probe pull requests, then pushed a script that drains GitHub Actions secrets and cloud credentials into every repository the token could write to - and wiped the traces afterwards. Here is how to tell whether you are affected, the indicators, and what to do right now.
Key points
- The campaign started around 12:45 UTC on 10 Nov 2026. According to Aikido, 4,837 accounts with stolen tokens opened 61,839 probe PRs into 61,764 repositories; StepSecurity counted more than 63,000 by the morning of 12 Nov. Nobody yet knows how the tokens were obtained.
- Where the token allowed writes, the attacker pushed a roughly 1,500-line shell script - into an existing workflow, into a script run by npm install, or into a new workflow on a throwaway branch - then reverted within a minute and deleted the run and its logs.
- The script collects GitHub Actions secrets, tokens, environment variables and credential files for cloud, Docker, Kubernetes, npm, PyPI and AI services, uses OIDC to obtain AWS, GCP and Azure sessions, and sets up persistent access.
- Data went to two IP addresses and, from 12 Nov, to Telegram. Packages on Packagist and Go are affected too.
What happened
On 12 November 2026 Aikido Security published an analysis of a campaign it calls wfx-loot, after the name the script uses for itself ("wfx"). Since around 12:45 UTC on 10 November the attacker has been using stolen GitHub tokens: each account first opens a probe pull request to confirm write access, then pushes a script that steals secrets from GitHub Actions.
According to Aikido, 4,837 accounts had opened 61,839 probe PRs into 61,764 repositories by 15:00 UTC on 11 November. More than 10,000 of them targeted repositories the account did not own but could reach as a collaborator or organisation member. Aikido says the payload ran and exfiltrated data in at least 1,806 repositories (elsewhere in the write-up it gives 1,835). StepSecurity counted more than 63,000 probe PRs the same day, about 90% of them still open.
Neither Aikido nor StepSecurity knows how the tokens were stolen. Packages are affected as well: Packagist digitalelvis/neuronai-studio 3.14.3 and Go github.com/onuragtas/docker-env v1.0.278 and v1.0.280, plus, according to StepSecurity, github.com/vkuznet/gocurl (a pseudo-version from 11 Nov).
How the attack works
The script is about 1,500 lines long, unobfuscated, with feature flags that switch individual capabilities on and off. According to Aikido it:
- Collects Actions secrets and variables,
GITHUB_TOKEN, OIDC tokens, the full environment, credential files for AWS, Azure, GCP, Docker, Kubernetes, npm, PyPI, SSH, Vault and Terraform, AI service keys, shell histories and files such as.env,.pemorkubeconfig. It also reads runner process memory. On self-hosted runners it additionally grabs cloud instance metadata credentials. - Escalates: exchanges GitHub OIDC tokens for AWS, GCP and Azure sessions, creates long-lived AWS access keys and obtains Azure Graph and Key Vault tokens.
- Persists: posts forged successful status checks to get past branch protection, rewrites an AWS role trust policy to
"Principal": {"AWS": "*"}(so any AWS account can assume it) and addswfx-ci-…federated credentials to Azure AD applications. - Exfiltrates a compressed archive by HTTP POST to two IP addresses. StepSecurity saw Telegram appear in samples at 01:10 UTC on 12 Nov; from about 05:30 UTC new copies sent data to Telegram only.
How to tell if you were compromised
Indicators published by Aikido and StepSecurity (defanged). StepSecurity warns that hashes are of limited use because every copy embeds its target repository and random names.
Collection servers (HTTP POST, port 8080, path /exfil):
194[.]150[.]166[.]244
18[.]143[.]168[.]96
153[.]75[.]82[.]159 (StepSecurity only)
Telegram: api[.]telegram[.]org (sendDocument)
GitHub:
PR title: docs: dependency audit notes
Branches: wfx-docs, chore/[a-z0-9]{8}, ci-check-[0-9]{4}
File in PR: docs/wfx-audit.md
Commits: ci: refresh build cache | ci: restore | ci: cleanup
chore: add ci helper | chore: add dependency audit workflow
Files: .github/workflows/build-audit-xxxxxx.yml, .ci-xxxxxx.sh
Artifacts/cache: wfx-loot-<run id>, cache keys wfx-*
Cloud:
Azure - federated credentials named wfx-ci-*
AWS - trust policies with "Principal": {"AWS": "*"}, new access keys since 10 Nov
SHA-256 (stealer script, per Aikido):
89695abb392d5cfd4972672961e644bb46baa98aa1ed7173c2a2816c762735cf
Quick checks from our own SOC work:
- Search for probe PRs across your organisation:
gh search prs "docs: dependency audit notes" --owner YOUR-ORG. Do the same for your personal account. - In the Actions tab, look for gaps in run numbers right after a suspicious commit - both Aikido and StepSecurity say this is often the only sign the script ran.
- In the organisation audit log, look for deleted workflow runs and unexpected pushes to
chore/…branches since 10 Nov. - In CloudTrail, look for
CreateAccessKeyandUpdateAssumeRolePolicy; in Azure, look for changes to application federated credentials. - Paste logs and exports into our IOC extractor - it pulls out IPs and hashes entirely in your browser.
What to do
- If your account opened a probe PR, treat it as compromised: revoke personal access tokens (PATs), sign out sessions and review authorised OAuth apps and GitHub Apps. Aikido says this applies even if the script never ran.
- If the script ran in a repository, rotate every secret and credential the workflows could use - Actions secrets, cloud keys, package registry tokens.
- Remove persistence: delete
wfx-ci-*federated credentials in Azure, fix AWS role trust policies containing"AWS": "*", revoke access keys created since 10 Nov and review GCP and Vault logins made through GitHub OIDC. - Packages: remove the listed Packagist and Go versions. Aikido says any machine that installed or opened the Packagist version should be treated as compromised. Developers who ran
npm installin an affected repository during this period should rotate their own credentials too. - Harden CI: restrict runner egress to an allowlist (block the IPs above and
api.telegram.org), give tokens the least privilege possible and review who can bypass branch protection. Our guide to a hacked account covers account recovery more generally.
Timeline
Updates
- 12 Nov 2026 - first version of this article.
FAQ
I only use GitHub for personal projects. Am I affected?
Not unless someone has your token. Still, check whether your account opened a PR titled "docs: dependency audit notes" or created a wfx-docs branch, including in your own private repos. Aikido treats such a probe PR as a sign the attacker holds your token, even if no payload ran.
I don't see anything suspicious in my repo. Am I safe?
Not necessarily. The attacker reverts changes within a minute and deletes workflow runs and their logs. Often the only trace is a gap in run numbers in the Actions tab. Review commit history since 10 Nov, your organisation's audit log and workflow run records.
How did the attacker get the tokens?
Neither Aikido nor StepSecurity knows yet. StepSecurity found that 173 probe PRs were opened through the Fly.io GitHub App from 19 accounts, but has no evidence of a breach of Fly.io's infrastructure. Aikido also notes that accounts hit by October's GhostActions campaign were far more likely to be hit again, while assessing the two as separate campaigns.
Is deleting the malicious commit enough?
No. If the script ran, treat everything the workflow could reach as stolen: secrets, tokens, cloud roles. The script also rewrites AWS role trust policies and adds Azure federated credentials that survive password and secret rotation. You have to find and remove those separately.
Sources
Spotted a mistake? Let us know and we will correct it openly.