Starting Tuesday, an attacker used stolen credentials for 4,837 GitHub accounts to plant a secret stealer in repositories those accounts could write to, according to Aikido Security, a security software company.
The stealer is built to take the secrets and cloud credentials that a repository's CI workflows can reach. It ran in at least 1,806 repositories, where the attacker has likely collected those credentials, the company says.
Each attack started with a pull request titled docs: dependency audit notes, opened from a branch named wfx-docs to test whether the account could write to the repository. These test pull requests were opened in 61,764 repositories, and the stealer followed in some of them.
In a separate analysis, researchers at SafeDep, which sells software supply chain security tools, counted 8,093 repositories that received malicious commits between 12:46 UTC on Tuesday and 04:36 UTC today. That count covers every repository that received malicious commits, not only those where the stealer ran. Their search covered only the default branches of public repositories, so the true total is higher, the researchers say.
In 7,309 of those repositories, the stealer was added to an existing workflow. In 771, it came as an npm postinstall hook, which also runs on a developer's machine during npm install.
After pushing the stealer, the attacker usually reverted the change within minutes. Where the stealer ran, its logs were deleted, usually along with the run itself. In those repositories, every secret and cloud role available to the workflows should be treated as compromised.
More pull requests with the same title were opened early today, after the company's own GitHub search ended on Wednesday, a check by The Hacker News found. Three that were checked, opened between 05:04 and 05:38 UTC, came from wfx-docs branches. It is not clear whether the stealer followed.
Any account that opened one of the attacker's test pull requests is compromised, even if the stealer never ran, Aikido said in its technical analysis. The analysis does not explain how the attacker obtained the credentials.
SafeDep's researchers advise owners of affected repositories to revoke the commit author's tokens, OAuth app grants, SSH keys, and sessions, and to turn on 2FA. Owners should also rotate every secret and variable the repository can read. Anyone who ran npm install on an affected commit should treat that machine as compromised and rotate its keys.
In most other repositories that received a test, nothing was pushed afterward, or the stealer did not run due to the repository's settings or the account's permissions. The figures cover only the public repositories the company could see.
The tests also reached repositories that the compromised accounts did not own. Of the test pull requests, 10,431 were submitted via collaborator or organization access, and 92% of those were still open when the company checked.
Signs a Repository Was Hit
Check for these signs, from Tuesday onward, in any repository you can write to:
- Branch:
wfx-docs - Branch:
chore/[a-z0-9]{8}, short-lived - Branch:
ci-check-[0-9]{4} - Pull request title:
docs: dependency audit notes - Commit message:
ci: refresh build cache, which adds about 1,500 lines to an existing workflow - Commit message:
chore: add ci helper, which adds a.ci-xxxxxx.shscript and apostinstallhook inpackage.jsonthat runs it on any npm install - Commit message:
chore: add dependency audit workflow, which adds.github/workflows/build-audit-xxxxxx.ymlon achore/branch - Commit message:
chore: initial commit, pushed before a new workflow file in an empty repository - Commit message:
ci: restore - Commit message:
ci: cleanup - SHA-256 (stealer script):
89695abb392d5cfd4972672961e644bb46baa98aa1ed7173c2a2816c762735cf - IP:
194.150.166[.]244:8080/exfil - IP:
18.143.168[.]96:8080/exfil - IP:
153.75.82[.]159:8080
A repository can show no wfx-loot artifacts, wfx- cache entries, or WFX-BEGIN step summaries and still have lost data. A missing run number on the attacker's commit is the more reliable sign that the stealer ran.
The stealer sends data by HTTP POST to the addresses above or to a Telegram chat, the SafeDep researchers found. In a sample of 200 payload commits, about a fifth used Telegram only.
The stealer is built to collect credentials from every source on the runner, according to the company. They include GitHub Actions secrets and variables, the workflow's GITHUB_TOKEN, OIDC and Actions runtime tokens, keys for AI services, and secrets in the memory of the runner's own processes. It reads credential files for AWS, Azure, GCP, Kubernetes, npm, PyPI, SSH, and other tools from their usual locations.
It also copies the repository, its last 100 commits, and recent workflow artifacts. On self-hosted runners, it takes cloud credentials from instance metadata as well as Docker container state and systemd units.
The stealer also has settings for private repositories, and the company says that suggests it may be running in them.
The stealer is designed to use those credentials to reach deeper into cloud accounts. It exchanges GitHub OIDC tokens for AWS, GCP, and Azure sessions, and on AWS it can create long-lived access keys for IAM users.
Some of its steps are built to survive credential rotation. It can rewrite an AWS role's trust policy to open the role to any AWS account.
It can also add federated identity credentials with the prefix wfx-ci- to Azure AD applications. Workflows in the compromised repository can then sign in to Azure without a stored secret, even after all tokens are rotated.
To find these backdoors, the researchers suggest checking for:
- Entra ID: federated credentials named
wfx-ci-*that you did not create - AWS CloudTrail:
AssumeRoleWithWebIdentityorAssumeRolesessions namedwfx-*, followed byCreateAccessKeyorUpdateAssumeRolePolicy - GCP:
GenerateAccessTokenandSignJwtcalls from your GitHub workload identity pool - Vault: JWT logins from the GitHub OIDC issuer
The stealer reached at least one Packagist package and one Go module through automated publishing triggers. At least 50 of the compromised users appear to publish packages for npm, Go, Packagist, PyPI, or crates.
The attacker appears to be after CI secrets rather than trying to spread through packages, the company says.
Version 3.14.3 of the Packagist package digitalelvis/neuronai-studio is malicious, and the company advises treating any machine that installed or opened it as compromised. Its package listing shows the version was published on Wednesday. Early today, the version was still listed, under a notice that versions of the package had been flagged as malware.
A normal composer install does not run the stealer, but running npm install inside the package's vendor directory does, the researchers found. Users should block v3.14.3 and pin v3.14.2 or earlier.
Two versions of the Go module github.com/onuragtas/docker-env, v1.0.278 and v1.0.280, carry the stealer only in a GitHub Actions workflow file. The Go code and release binaries are unchanged, and Go builds never run workflow files, so users of the module may not have been affected. The company still recommends removing those versions.
The researchers also found the stealer in another Go module, github.com/vkuznet/gocurl, in pseudo-version v0.0.0-20261111095532-8d5aad0cb0da, inside a workflow that has never run. Users should block that pseudo-version.
The stealer also reached 28 WebdriverIO repositories through commits authored as the bot account wdio-bot. No package release was affected, but the bot's token should be treated as stolen.
The company found that the accounts used this week overlap with those hit in GhostAction's October wave, in which stolen GitHub accounts pushed secret-stealing workflows into repositories.
Accounts hit in October were about 1,000 times more likely than other active accounts to be used this week. In more than 100 repositories, the new stealer was added to October's workflow files, leaving the older step that sends data out in place.
Aikido said, "we don't attribute November to the same actor at this stage," because the infrastructure, tools, and methods differ, and stolen credentials often end up with several attackers.
Correction (November 12, 2026): An earlier version of this article said the stealer sent data only by HTTP POST to two addresses and that the attacker reverted each change within a minute. A second analysis found a third server, a Telegram channel, and changes left in place for longer.
Found this article interesting? Follow us on Google News, Twitter and LinkedIn to read more exclusive content we post.

