Hijacked GitHub accounts pushed a CI secret stealer into your repos (wfx-loot, Nov 2026): find it, revoke, and remove cloud backdoors
For orgs whose members or repos show wfx-docs probe PRs or wfx stealer commits. Built from Aikido's, StepSecurity's and Endor Labs' write-ups. The stealer deletes its run logs and adds cloud persistence, so rotation alone isn't enough.
1. Find exposed repos and accounts2. Lock the compromised accounts3. Treat every secret the workflows could reach as stolen4. Remove cloud persistence5. Check what you published6. Harden and keep watching
Find exposed repos and accounts
Search for the probe first; one open probe PR means that account's token is stolen.
- Search your org for PRs titled 'docs: dependency audit notes' and branches wfx-docs, chore/<8 chars>, ci-check-<4 digits> since Nov 10
- Search commits for 'ci: refresh build cache', 'chore: add ci helper', 'chore: add dependency audit workflow', 'ci: restore', 'ci: cleanup'
- In the audit log, look for workflow-run deletions by the same user right after a push; a missing run number means the stealer probably ran
Lock the compromised accounts
The attacker reused stolen tokens, not a GitHub flaw.
- Have each affected user revoke all PATs, OAuth and GitHub App authorizations and SSH keys, reset the password and re-enroll 2FA from a clean device
- Temporarily remove their write access in your org until done
- Close the probe PRs and delete the attacker branches after preserving them as evidence
Treat every secret the workflows could reach as stolen
Includes org and environment secrets, not only repo secrets.
- Rotate Actions secrets and variables, registry tokens (npm, PyPI, Docker), cloud keys, SSH and signing keys, and AI provider keys (OpenAI, Anthropic, Gemini, Hugging Face, Cursor, Copilot)
- On self-hosted runners, assume instance metadata credentials and anything on the host are stolen; rebuild the runner
- Rotate at the provider, then confirm old keys fail
Remove cloud persistence
The stealer is built to survive token rotation.
- AWS: look for role trust policies with Principal AWS '*', new IAM user access keys, unexpected AssumeRoleWithWebIdentity from the repo
- Azure: list federated identity credentials on Entra apps; remove ones named wfx-ci-… or pointing at affected repos
- GCP, Vault, Kubernetes: review service-account token generation, signJwt calls and logins from GitHub runner IPs since Nov 10
Check what you published
Automated release workflows can ship the payload.
- Compare tags and packages released since Nov 10 against reviewed commits; yank or deprecate any that include attacker commits
- Check branch protection: the payload posts forged success statuses under your required check names; require checks from a specific GitHub App
- Remove .ci-xxxxxx.sh files and package.json hooks the attacker added
Harden and keep watching
New probe PRs were still appearing on Nov 12.
- Block 194.150.166.244, 18.143.168.96 and 153.75.82.159 egress from runners and alert on them
- Prefer short-lived OIDC with tight subject claims over stored cloud keys; scope GITHUB_TOKEN to read by default
- Re-run the searches daily until vendors report the campaign has stopped