wfx-loot Turns Stolen GitHub Access Into a CI Secret-Stealing Supply-Chain Attack

wfx-loot Turns Stolen GitHub Access Into a CI Secret-Stealing Supply-Chain Attack
The active wfx-loot campaign is using stolen GitHub credentials to reach tens of thousands of repositories, inject malicious GitHub Actions code, and steal the secrets exposed to automated builds. This is not a GitHub Actions vulnerability: the attackers are signing in with valid accounts that already have write access.
That distinction matters. A workflow can pass normal authentication checks and still become an attacker-controlled credential broker when a developer token, collaborator account, or machine identity is compromised.
What happened in the wfx-loot campaign
Aikido reported that, beginning on November 10, attackers used 4,837 compromised GitHub accounts to open probe pull requests in 61,764 repositories. The pull requests commonly used the title docs: dependency audit notes and a branch named wfx-docs. The probe tested whether the stolen account could write to a repository; it was not necessarily the payload itself.
Aikido identified at least 1,835 repositories where the malicious code ran and credentials were exfiltrated. The number may be understated because the campaign reverted changes and deleted workflow runs, sometimes within about a minute. A missing run number or a short-lived branch may therefore be more useful than a visible malicious commit.
The campaign used three main delivery paths:
- It modified an existing GitHub Actions workflow with roughly 1,500 lines of credential-stealing code.
- It added a hidden
.ci-xxxxxx.shscript and apostinstallhook to run when a package was installed. - It created a temporary workflow file on a disposable branch.
The code searched for GitHub Actions secrets, workflow tokens, AWS, Azure and Google Cloud credentials, Docker and Kubernetes configuration, SSH keys, .env files, package-manager credentials, Terraform and Vault data, shell histories, and AI-provider API keys.
Why this is a supply-chain attack
The initial compromise is an identity event, but the blast radius is a software supply chain problem. A stolen GitHub account can write to repositories the user does not own, trigger CI jobs, access secrets injected into those jobs, and potentially reach release or package-publishing workflows.
Aikido observed the activity entering published packages through automated publishing triggers, including a Packagist package and two Go module versions. The researchers said this may be a side effect of abusing publishing automation rather than the campaign’s primary objective. That nuance is important: defenders should not assume that every affected package was intentionally selected, but they should still treat package provenance and downstream builds as investigation targets.
The trusted path is the attack surface. GitHub authenticates the account, Actions executes the workflow, cloud identity systems honor the resulting token or role, and package registries may accept the automated release. Each component can behave as designed while the combined chain delivers attacker access.
The secrets are only the beginning
The payload did more than collect static files. Reporting based on the research says the attackers exchanged stolen tokens for cloud sessions, attempted to impersonate service accounts, created new credentials, and changed AWS or Azure configuration to preserve access after victims rotated exposed secrets.
That means “we rotated the GitHub token” is not a complete response. If an affected workflow could assume a cloud role, read a deployment secret, publish an artifact, or access a Kubernetes cluster, those downstream identities and actions need separate review.
Teams should also distinguish between a secret being read and a secret being used. A workflow log may show the first event, while cloud audit logs, package registry activity, identity-provider logs, and deployment telemetry reveal the second.
What defenders should do now
1. Search GitHub history and workflow metadata
Review repositories writable by affected users and organizations from November 10 onward. Search for:
- Pull requests titled
docs: dependency audit notes. - The
wfx-docsbranch or short-livedchore/xxxxxxxxbranches. - Commits titled
ci: refresh build cache,chore: add ci helper, orchore: add dependency audit workflow. - Unexpected
.ci-*.shfiles, new workflow files, andpostinstallchanges inpackage.json. - Gaps in workflow run numbers or deleted runs during the campaign window.
If the probe reached a repository, treat the associated account as compromised even when no workflow appears to have executed. If the payload ran, assume every secret and cloud role available to that job is exposed.
2. Rotate from a clean administrative path
Revoke and replace GitHub tokens, Actions secrets, cloud keys, package credentials, SSH keys, AI-provider keys, and registry tokens that the affected workflows could access. Perform rotation from a clean machine and preserve evidence first where possible.
Then inspect AWS IAM access keys, role trust policies, Azure federated credentials, service principals, Kubernetes tokens, and newly created identities since November 10. Rotation does not remove a backdoor trust-policy change or a credential the attacker created independently.
3. Review downstream activity
Look for unusual cloud sessions from build identities, new role assumptions, access-key creation, trust-policy updates, package publication, workflow-triggered deployments, and Kubernetes secret reads. Compare the actor’s source location and behavior with the normal baseline for each CI identity.
For package consumers, review lockfiles and build logs around the campaign period. Do not infer that a clean source tree proves a clean build: a temporary workflow or install hook may have executed and then disappeared.
4. Reduce the next token’s reach
Use short-lived, narrowly scoped credentials for CI. Separate build, test, release, and deployment roles. Require approval for production publishing, restrict workflow permissions with permissions:, pin third-party Actions to reviewed commit SHAs, and prevent untrusted pull requests from receiving privileged secrets.
The goal is not merely to detect the next malicious workflow. It is to ensure that a stolen developer or CI identity cannot turn one repository write permission into organization-wide cloud access.
Bottom line
wfx-loot shows how modern supply-chain attacks can move without exploiting a software defect. Valid GitHub credentials, repository write access, permissive workflows, and long-lived cloud trust can combine into a fast credential-theft chain that erases much of its own evidence.
If your repositories were writable by an account touched by this campaign, investigate the account, the workflow, and every downstream identity it could reach. Search for the campaign’s probe markers, rotate secrets from a clean path, review cloud and registry logs, and close the permission gaps that made CI a high-value pivot point.
Sources
- Aikido: wfx-loot campaign pushes CI secret stealer to tens of thousands of repositories
- SailPoint: wfx-loot turned stolen GitHub tokens into cloud access
- TechRadar: Thousands of GitHub repositories targeted in widespread attack
References
FAQ
The active wfx-loot campaign is using stolen GitHub credentials to reach tens of thousands of repositories, inject malicious GitHub Actions code, and steal the secrets exposed to automated builds. This is not a GitHub Actions vulnerability: the attackers are signing in with valid accounts that already have write access.
Review repositories writable by affected users and organizations from November 10 onward. Search for: