wfx GitHub Actions Secret Stealer: How to Hunt for It When Rotating Keys Isn't Enough
The wfx GitHub Actions secret stealer used stolen but valid tokens for real developer and bot accounts, opening pull requests and pushing commits the way a developer would. Here is why rotating keys won't close the compromise, and the order to hunt in across GitHub, Entra, AWS and AI providers.
On 10 November 2026, a credential theft campaign researchers are calling wfx (also reported as wfx-loot and WFX Phantom) started pushing CI secret stealers into GitHub repositories at scale. SafeDep's data shows malicious commits arriving from 12:46 UTC on 10 November.
The reflex response is to rotate everything. You should rotate, but rotation on its own can leave the attacker a working route back in through trust settings that no secret controls.
What wfx is, and why it looks like normal developer work
There is no GitHub Actions bug at the center of this. StepSecurity's analysis states that the attacker holds valid tokens for real developer and bot accounts and uses them the way a developer would, by opening pull requests and pushing commits. Nothing in your activity feed looks like an exploit. It looks like a colleague, or a bot, doing routine work.
The scale is large. Aikido reports that 4,837 compromised accounts opened probe pull requests in 61,764 repositories, and that at least 1,835 repositories ran the payload and had credentials exfiltrated. SafeDep independently counted 61,879 probe pull requests in 61,734 repositories from 4,833 accounts, with 91% still open. StepSecurity reported more than 63,000 probe pull requests as of 07:40 UTC on 12 November, about 90% of them still open, with new ones appearing every few minutes.
Why the researchers' numbers differ
Each count measures something different, taken at a different moment, so the figures sit alongside one another rather than competing. SafeDep counted 8,093 repositories that received malicious commits between 12:46 UTC on 10 November and 04:36 UTC on 12 November, and the campaign was still active when that search ran. SecurityWeek notes that the commit figure does not necessarily indicate successful execution, while Aikido's figure of more than 1,800 repositories reflects signs that the stealer actually ran. GitGuardian's own dataset holds 28,500 payload patches from 2,367 accounts across 17,715 repositories.
A probe pull request means an account tried to get in, a malicious commit means it had write access, and confirmed execution means secrets probably left. Which of those three applies to you should shape what you do next, and only your own logs can tell you which one it is.
How the stealer reaches CI secrets
Probe pull requests test access
We suggest treating any probe pull request as a sign that someone tested what a stolen token could reach. Help Net Security reports that 10,431 of the probe pull requests went into repositories the account did not own, reached through collaborator or organization access, so one stolen token exposes every project its owner can write to, whoever owns the repository.
Workflow injection was the main delivery route
Once access is confirmed, the usual next move is to inject the stealer into an existing workflow. StepSecurity found more than 21,000 commits with the message ci: refresh build cache between 10 and 12 November. SafeDep found 1,343 repositories where the malicious commit author was an account other than the owner, such as a collaborator or a bot. That second figure matters for scoping, because when a collaborator's or bot's token is stolen, the malicious commit lands in your repository under their name, and a review that only looks at the owner's activity will miss it.
GitHub's hold stopped one variant but not the other
GitGuardian reports that every November payload run it could still observe from workflow file changes was put in action_required and never started. The npm-hook variant was not held: in a sample of 19 repositories where the script executed, 18 reported a successful exfiltration. Our reading is that a dependency hook rides on a workflow that already exists rather than arriving as a workflow file change, so a review process that focuses only on workflow files may not flag it. For defenders, this means reviewing dependency manifests with the same suspicion as workflow files.
Other routes: GitHub Apps and Telegram exfiltration
Not every stolen token was a personal one. StepSecurity found that 173 probe pull requests, opened from 19 accounts, were made through the Fly.io GitHub App (app ID 34557). Your scoping has to cover OAuth grants and GitHub App installations as well as personal access tokens. Exfiltration has shifted too. Early copies sent data to specific IP addresses, and StepSecurity reports that the switch to Telegram means blocklists built from the 10 November IP addresses miss the newest copies. A hit against those addresses is still worth investigating, but an empty result from the blocklist tells you very little about whether data left.
Why rotating keys does not end the compromise
GitHub built its OIDC integration to limit damage. GitHub's documentation explains that the cloud provider issues a short-lived access token that is only valid for a single job and then expires. A stolen OIDC token on its own isn't worth much, so an attacker who wants to stay has to turn that short window into a trust relationship that lasts.
Entra federated identity credentials as a backdoor
On Azure, the federated identity credential is the obvious tool for that. Microsoft describes it as a credential that creates a trust relationship between an application and an external identity provider. Aikido reports that once this backdoor is in place, any workflow in that repository can authenticate to Azure without a stored secret, even after every token has been rotated.
Loosely scoped AWS trust policies for GitHub OIDC
On AWS, the exposure sits in role trust policies. AWS warns that if you do not limit the condition key token.actions.githubusercontent.com:sub to a specific organization or repository, GitHub Actions from organizations or repositories outside your control can assume roles associated with the GitHub identity provider in your account.
Rotation replaces the stolen secrets but leaves the trust configuration exactly as the attacker set it, and that is the point leadership most needs to hear before signing off on a response as complete.
The wfx hunt: an order of operations
Step 1: Scope identities
List every human account, bot and GitHub App with write access across your organizations, outside collaborators included. Any account that shows up in probe pull requests is high risk. Also flag accounts hit in the October GhostAction wave: Aikido found those accounts were significantly more likely than baseline to be affected by wfx, and GitGuardian found 431 wfx accounts, about 20%, had already been compromised in GhostAction.
Step 2: Search GitHub
Search every repository your accounts can write to, not just the ones you own. Look for:
- Probe pull requests, open or closed, from accounts you wouldn't expect.
- Commits titled
ci: refresh build cache, on default and non-default branches. - Changes to files under
.github/workflows/since 10 November. - Changes to
package.jsonlifecycle scripts such aspreinstall,installandpostinstall.
Step 3: Check workflow run history
We suggest comparing workflow run history against your organization audit log and noting any runs that were deleted, who deleted them and when. Where execution is confirmed, assume every secret available to that job was exposed.
Step 4: Review Microsoft Entra federated credentials
We suggest listing the federated identity credentials on every app registration and on every user-assigned managed identity. Investigate anything you didn't create, any unexpected issuer or subject, and any subject pointing at a repository, branch or environment you don't recognize. We have not found a named vendor source confirming a specific naming pattern for rogue credentials, so treat any names circulating informally, such as wfx-ci-*, as unverified leads rather than indicators, and remember that a renamed credential would not match in any case. We suggest using your audit logs to establish when each credential was added and by whom, which in our view is a more dependable test than any name.
Step 5: Review AWS trust policies
Review every IAM role that trusts the GitHub OIDC provider. The sub condition should be restricted to specific organizations and repositories, and ideally to specific branches or environments. A tightly scoped condition looks like this:
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:your-org/your-repo:ref:refs/heads/main"
}
}We suggest then reviewing your cloud audit trail for recent trust policy edits and newly created roles, and for role assumptions from repositories you don't expect.
Step 6: Review AI provider usage
For every OpenAI, Anthropic and Gemini key that CI could reach, review usage and billing. You're looking for spend, models, regions or request patterns that don't fit your workloads. For the broader questions to ask when AI keys may have been abused, our inference-provider risk checklist may help.
Step 7: Preserve evidence before you change anything
Export audit logs, workflow run records, pull request and commit metadata, Entra audit entries and CloudTrail events before cleanup begins. If you delete a malicious pull request or credential without keeping a record, you lose the timeline you'll need for scoping, reporting and any regulatory notification.
Containment and recovery, in sequence
Sequence matters because a rotated secret can be fetched again through a trust path that is still live: while a rogue federated credential or a loose trust policy keeps working, a workflow the attacker controls can reach the new values as easily as the old ones. The sequence we suggest:
- Remove the attacker's standing access first. Delete rogue federated credentials and tighten AWS trust policies before rotation, or at the same time.
- Revoke GitHub access. Revoke compromised personal access tokens, OAuth grants and GitHub App installations, including third-party apps like the one StepSecurity identified.
- Rotate secrets. That means Actions secrets, cloud keys, package registry tokens and AI provider keys.
- Clean the code. Close or delete probe pull requests and revert injected workflow and package changes on default and other branches. Any probe pull request left open in a review queue is a chance for a maintainer to merge it by mistake.
- Finish GhostAction cleanup. Aikido found more than 100 repositories where wfx was injected into GhostAction workflow files. If October's cleanup was only partial, finish it now.
- Monitor. Use the hunt results as a baseline, and alert on new federated credentials, trust policy edits and workflow file changes from now on.
Hardening AI provider keys in CI
In our view, AI provider keys deserve an explicit place in any rotation plan alongside cloud credentials. The Cloud Security Alliance recommends placing AI keys behind per-project spending caps and usage anomaly alerting, preferring short-lived or proxy-brokered credentials over static keys in CI, and including AI providers in incident rotation runbooks alongside cloud and registry credentials.
In practice, give each project its own key with its own cap, so a single leak can't drain a shared budget. Where you can, route CI calls through an internal proxy that holds the real key, so the workflow never sees it; our guide on how a credential proxy keeps API keys out of AI agents walks through that pattern. The same discipline applies upstream of CI. We suggest checking developer machines too, since local agent configuration files may hold live credentials; our walkthrough on auditing local agent settings and rotating exposed keys covers that check.
Common mistakes in wfx response
- Treating rotation as the finish line. Fix trust configuration first (containment step 1).
- Relying on 10 November IP blocklists. They miss the Telegram-era copies.
- Assuming GitHub's hold protected you. Check
package.jsonhooks, not only workflow files. - Checking only repositories you own. Scope by write access, including collaborator and organization rights.
- Reading public counts as your verdict. Public figures can't tell you either way whether you were hit; your own logs can.
- Leaving GhostAction cleanup unfinished. Recheck October's accounts and workflow files.
Caveats and the limits of what we know
The public counts come from GitHub search at specific moments while the campaign was still running, so they are snapshots taken mid-campaign rather than final totals. They also measure different things: pull requests opened, commits received and confirmed execution are not interchangeable, and SafeDep's commit count does not necessarily mean the payload ran.
We suggest not assuming that external datasets reflect what happened in your private repositories or enterprise instances. For most organizations, your own audit logs, Entra logs and CloudTrail are the primary evidence, and the public research is context.
Indicators have already shifted once, as the move from fixed IP addresses to Telegram shows. Commit messages and credential names could shift too, so check the latest vendor IOCs before leaning on any single pattern.
The Cloud Security Alliance, citing GitGuardian, reports that GhostAction used about 1,900 compromised accounts to target more than 30,000 repositories in October. Set beside Aikido's count of 61,764 repositories for wfx, that gives two waves about a month apart, the second roughly twice the size by repositories targeted. Two data points are not enough to call a trend, though they are reason enough to plan for another wave.
This guide doesn't replace a formal incident response engagement when regulated data or production cloud access is involved.
Key Takeaways
- 1The wfx GitHub Actions secret stealer did not exploit a GitHub bug. It used stolen but valid tokens for real developer and bot accounts, so the activity looks like normal work.
- 2Public counts differ because they measure different things: Aikido reports at least 1,835 repositories where the payload ran, while SafeDep counted 8,093 repositories that received malicious commits.
- 3One stolen token exposes every repository its owner can write to. Scope by account permissions and app grants, not by repository ownership.
- 4GitHub held workflow-file payloads in action_required, but the npm-hook variant got through: 18 of 19 sampled repositories reported successful exfiltration.
- 5Rotation alone is not enough. Rogue Entra federated credentials and loosely scoped AWS trust policies can let the attacker back in after every token is rotated.
- 6Fix trust configuration first, then revoke GitHub access, then rotate. Preserve evidence before any cleanup.
- 7Put AI provider keys behind per-project spending caps and anomaly alerts, prefer short-lived or proxy-brokered credentials, and add them to rotation runbooks.
Conclusion
wfx did not need a flaw in the pipeline; it worked through the identities and trust settings around it. The attacker held valid tokens for real developer and bot accounts and used them the way a developer would, opening pull requests and pushing commits. On Azure, Aikido reports that a federated identity backdoor lets any workflow in an affected repository authenticate without a stored secret, even after every token has been rotated. That's why a rotation sprint can feel like progress while a rogue federated credential or a loose trust policy still works.
A sound response runs in a clear order: scope every account and app that can write to your code, hunt in GitHub for probe pull requests, injected commits, hook changes and suspicious workflow run history, and check Entra federated credentials and AWS trust policies before you rotate anything. Review AI provider usage, keep a record of the evidence, and finish any outstanding GhostAction cleanup. Treat the public numbers as context rather than a verdict on your own exposure. If the hunt turns up trust changes you can't explain, or regulated data is involved, bring in formal incident response support.
Frequently Asked Questions
How do I know whether my organization was affected by the wfx campaign?
Search every repository your accounts can write to for probe pull requests from unexpected accounts, commits titled 'ci: refresh build cache', and changes to workflow files or package.json lifecycle hooks since 10 November. StepSecurity found more than 21,000 commits with that message between 10 and 12 November. We also suggest comparing workflow run history against your audit log, including any runs that were deleted.
Why isn't rotating all my secrets enough to remove the attacker?
The attacker may have set up a trust path that doesn't depend on any secret. Aikido reports that once an Azure federated identity backdoor is in place, any workflow in that repository can authenticate to Azure even after every token has been rotated. On AWS, a role trust policy that doesn't restrict the sub condition lets workflows outside your control assume the role. Fix those trust settings first, then rotate.
How should an AWS IAM trust policy for GitHub OIDC be scoped?
AWS warns that if you do not limit token.actions.githubusercontent.com:sub to a specific organization or repository, GitHub Actions from outside your control can assume the role. Restrict sub to specific repositories, ideally to specific branches or environments too, and check the aud value. Then review CloudTrail for recent trust policy edits.
Did GitHub block the attack?
Partly. GitGuardian reports that every November payload run it could still observe from workflow file changes was held in action_required and never started. The npm-hook variant was a different story: in a sample of 19 repositories where the script ran, 18 reported successful exfiltration. Held workflow changes don't mean you're safe.
We cleaned up after GhostAction. Are we safe?
Not necessarily. GitGuardian found that 431 wfx accounts, about 20%, had already been compromised in GhostAction, and Aikido found more than 100 repositories where wfx was injected into GhostAction workflow files. Recheck those accounts and repositories as part of this hunt.
How should AI provider keys used in CI be protected after wfx?
The Cloud Security Alliance recommends per-project spending caps and usage anomaly alerting, short-lived or proxy-brokered credentials instead of static keys in CI, and including AI providers in incident rotation runbooks alongside cloud and registry credentials. Review usage and billing for every OpenAI, Anthropic and Gemini key that CI could reach.
Sources
- https://www.aikido.dev/blog/compromised-github-accounts-push-ci-secret-stealer-to-tens-of-thousands-of-repositories
- https://www.stepsecurity.io/blog/wfx-phantom-the-github-actions-secret-stealer
- https://labs.cloudsecurityalliance.org/research/csa-research-note-wfx-github-ci-secret-stealer-20261112-csa/
- https://safedep.io/blog/github-actions-wfx-credential-stealer
- https://blog.gitguardian.com/wfx-loot-a-ci-secret-stealer-pushed-with-stolen-github-credentials/
- https://www.securityweek.com/attacker-targets-60000-github-repositories-in-credential-theft-campaign/
- https://www.helpnetsecurity.com/2026/11/12/wfx-loot-github-actions-secret-stealer/
- https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust
- https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-idp_oidc.html
- https://docs.github.com/en/actions/concepts/security/openid-connect
Written by
Hamza DiazHamza Diaz is the founder of Optijara, where he builds practical AI agents, automation systems, and Copilot workflows for service businesses. He writes about AI operations, agent strategy, and real-world implementation for teams that want usable systems instead of hype.
