wfx GitHub Actions Credential Stealer: CI Secret Theft and Cloud Persistence Across 8,000+ Repositories

GitHub Actions credential stealer

Executive Summary

wfx is a GitHub Actions credential stealer spread by an active supply chain campaign. The attacker uses stolen GitHub tokens. With them, they plant the stealer in every repository the hijacked account can write to.

The stealer runs once, in GitHub Actions or during npm install. It collects every secret and cloud credential the CI job can reach. Then it sends the loot to attacker servers or a Telegram chat.

This is not a classic dependency hijack. The attacker wants CI secrets and cloud access, not package installs. In almost every repository the malicious commit is reverted within minutes. Afterwards the branch looks clean.

SafeDep counted 8,093 repositories with malicious commits between November 10, 2026 at 12:46 UTC and November 12 at 04:36 UTC. The campaign was still active when they searched. Aikido Security reported the campaign first. They tracked 4,837 hijacked GitHub accounts and confirmed the stealer ran in at least 1,806 repositories.

The real number is higher. The search covered only default branches of public repositories. Private repos, other branches, and repos that got only the probe pull request are not counted.

The biggest danger is persistence. The payload doesn’t stop at theft. On AWS it creates long-lived access keys and rewrites role trust policies. On Azure it adds a federated identity credential named wfx-ci-* to Entra app registrations. With it, any workflow on the repo’s main branch can sign in to Azure, even after every client secret is rotated.

So rotating repository secrets alone does not remove this attacker.

TL;DR for Engineering Teams

What it is: wfx, a GitHub Actions credential stealer pushed through commits made with stolen tokens. There is no CVE. This is a campaign, not a product flaw. The payload is a shell script or workflow step of about 1,500 lines.

Where it hits: Any public or private repo a hijacked account can write to, including through collaborator or organization access. The stealer runs in GitHub Actions on push. The npm postinstall variant also runs on a developer’s laptop during npm install.

Why it matters: 8,093 repos got malicious commits. The stealer ran in at least 1,806. It takes CI secrets, cloud credentials, API keys from memory, and credential files. Then it plants AWS and Azure backdoors that survive secret rotation.

Patch status: There is no patch. This is about stolen credentials, not a code bug. The fix is GitHub token hygiene and hunting for cloud backdoors.

Do this now: If a repo you own got a wfx-docs probe pull request or a malicious commit, revoke the commit author’s tokens, OAuth grants, SSH keys and sessions. Turn on 2FA. Rotate every secret the repo can read. Then hunt for wfx-ci-* federated credentials in Entra ID and wfx-* sessions in CloudTrail.

Vulnerability Overview

FieldValue
Vulnerability TypeSupply chain credential theft via stolen-token commits; CI/CD workflow injection
CWECWE-506 (Embedded Malicious Code); CWE-522 (Insufficiently Protected Credentials); CWE-349 (Acceptance of Extraneous Untrusted Data)

Technical Anatomy

Root Cause

There is no memory bug or parser flaw here. The root cause is trust in write access, plus how much GitHub Actions can reach.

If an attacker has a valid GitHub token, GitHub accepts their commits as real. The commits show up as the real user, with their noreply email. They are not signed. No signature plus full write access is the gap the attacker uses.

Once a workflow runs, GitHub Actions gives it a lot: secrets, variables, the GITHUB_TOKEN, runtime tokens, and an OIDC identity. That OIDC identity can be swapped for cloud sessions. The stealer cashes all of it in one run.

The name wfx comes from the prefix the payload puts on its files, branches, and cloud objects.

Exploit Path

Entry point. The attacker pushes to a repo with a stolen token. First they open a probe pull request called docs: dependency audit notes from a branch named wfx-docs. It adds a small notes file. It only tests if the token can write.

Aikido saw these probe pull requests in 61,764 repos. SafeDep counted 61,879 of them across 61,734 repos from 4,833 accounts. 91 percent were still open when they checked. A probe pull request alone means the account is compromised, even if no payload came after it.

Planting the stealer. Once write access is confirmed, the attacker uses one of three methods:

  • Code added to an existing workflow (ci: refresh build cache): 7,309 repos.
  • An npm postinstall hook (chore: add ci helper): 771 repos. This one also runs on developer machines.
  • A new workflow file in an empty repo (chore: add dependency audit workflow): 16 repos. A chore: initial commit comes first, so there is something to inject into.

The malicious workflow asks for id-token: write and statuses: write. It copies the Actions runtime tokens into the job environment. Then it passes all secrets and variables to the payload as JSON.

What it does. The payload runs in CI and takes everything it can reach:

  • GitHub secrets and variables, the GITHUB_TOKEN and runtime tokens
  • API keys found in the runner’s process memory and environment
  • Credential files: cloud CLI configs, ~/.ssh, ~/.gnupg, registry tokens, kubeconfig, shell history, and AI tool configs

Then it asks for GitHub OIDC tokens for AWS, Azure, and GCP and tries to use them. It also replays the OIDC token against HashiCorp Vault and Kubernetes APIs.

The data goes out by HTTP POST to attacker servers or to a Telegram chat. After the run, the attacker pushes ci: restore and ci: cleanup to remove the payload. Where the stealer ran, its logs are deleted, and often the run itself too.

Campaign Phases

Phase 1, foothold. A stolen GitHub token opens a probe pull request from wfx-docs to check write access. SafeDep notes a big overlap with the October GhostAction wave. Accounts hit in October were about 1,000 times more likely than other active accounts to be reused this week.

Phase 2, expansion. The stealer goes in through workflow injection, a new workflow, or an npm postinstall hook. All three run in CI. The postinstall variant also runs on developer laptops.

Phase 3, packages. Automated publishing pushed the payload into three packages: the Packagist package digitalelvis/neuronai-studio at v3.14.3, and two Go modules, github.com/vkuznet/gocurl and github.com/onuragtas/redock (also served as docker-env). SafeDep thinks the attacker wants CI secrets, not package spread. The packages got hit as a side effect. Release automation fired on the attacker’s push.

Phase 4, persistence. On AWS the payload creates new access keys. It rewrites role trust policies so any account can assume the role. Session names look like wfx-<pid>. On Azure it adds a federated identity credential named wfx-ci-<n> to Entra app registrations. After that, workflows can sign in without a stored secret, even after rotation.

Indicators of Compromise

TypeIndicatorNotes
IPv4194.150.166[.]244:8080/exfilMain HTTP exfil server; about half of sampled commits
IPv418.143.168[.]96:8080/exfilHTTP exfil server (AWS ap-southeast-1 range; may be reassigned)
IPv4153.75.82[.]159:8080Extra exfil server reported by SafeDep; about 1% of sample
Telegram chat id-1004340163187Attacker collection chat; do not contact
SHA-25689695abb392d5cfd4972672961e644bb46baa98aa1ed7173c2a2816c762735cfReported stealer sample; not the same across all variants
Branchwfx-docsProbe pull request branch
Branchci-check-[0-9]{4}Reported pattern linked to earlier activity
PR titledocs: dependency audit notesProbe pull request
Commit msgci: refresh build cacheWorkflow injection; adds about 1,500 lines
Commit msgchore: add ci helperAdds .ci-xxxxxx.sh plus postinstall hook
File.github/workflows/build-audit-[a-z0-9]{6}.ymlNew malicious workflow (about 1,519 lines)
File.ci-[a-z0-9]{6}.shRoot shell payload (about 1,440 to 1,493 lines)
Azurewfx-ci-* federated credentialBackdoor on Entra app registrations
AWSwfx-* role session nameFollowed by CreateAccessKey or UpdateAssumeRolePolicy
Runner path$RUNNER_TEMP/.wfx-<pid>/Payload staging directory

A repo can show none of the wfx-loot- artifacts, wfx- cache entries, or WFX-BEGIN step summaries and still have lost data. Those channels were turned off in the analyzed samples. A missing run number on the attacker’s commit is a better sign that the stealer ran.

Affected Versions

PackageVulnerable VersionsFixed VersionNotes
digitalelvis/neuronai-studio (Packagist)v3.14.3v3.14.2 or earlier (pin back)composer install does not run the payload. npm install inside the vendor dir does. Packagist still serves v3.14.3 as latest.
github.com/vkuznet/gocurl (Go)v0.0.0-20261111095532-8d5aad0cb0daNone (block the pseudo-version)The payload sits in a workflow that has never run. Go tooling does not run workflow files. The proxy caches the pseudo-version for good.
github.com/onuragtas/redock / docker-env (Go)v1.0.278, v1.0.280, v1.0.282v1.0.277 (.279/.281/.283 are clean reverts)Payload only in beta.yml, which has not run since the attack. Block the poisoned versions.

SafeDep also scanned 218 npm, Go, and Packagist packages whose source repos got malicious commits. None of the published versions had the payload. PyPI and other registries were not checked.

The payload also reached 28 WebdriverIO repos through the wdio-bot account. No package release was affected, but treat the wdio-bot token as stolen.

Exposure Analysis

EnvironmentRisk LevelReason
CI/CD pipelinesCriticalDirect target. Secrets, variables, GITHUB_TOKEN, OIDC and runtime tokens are all exposed in one run.
Cloud workloadsCriticalOIDC is swapped for AWS, Azure, and GCP sessions. AWS key creation, trust-policy rewrites, and Azure federated-credential backdoors survive rotation.
Developer environmentsHighThe npm postinstall variant runs on any machine that runs npm install on an affected commit. Local keys, SSH, and shell history are exposed.
Internet-exposed servicesMediumNot the entry point. But stolen cloud credentials open a path into exposed infrastructure.

Scale: 8,093 repos with malicious commits (SafeDep). The stealer ran in at least 1,806 (Aikido). 61,734+ repos got a probe. 4,837 accounts were hijacked. At least 50 of the compromised users publish packages for npm, Go, Packagist, PyPI, or crates.

Real-World Impact

Think about what a typical CI secret set holds. Registry publish tokens. Cloud deployment credentials. Third-party API keys. So account takeover and cloud credential theft happen right away.

In the 1,806+ repos where the stealer ran, the pipeline is compromised. Because it reads the runner’s process memory, it also gets short-lived tokens that never touch a file. On self-hosted runners it goes further. It reads instance metadata, Docker container state, and systemd units. That opens up the host and its network.

The persistence is what makes this more than a one-time theft.

Take an AWS role whose trust policy now accepts any account. Or an Entra app with a wfx-ci-* federated credential. Both stay open to the attacker after you rotate every secret in the repo.

Teams that rotate secrets and close the pull request will think they’re done. If they skip the cloud hunt, the attacker still has access.

Detection Guidance

Log Indicators

Search all branches, not just the default one, from November 10 onward. Look for:

  • the wfx-docs branch
  • the pull request title docs: dependency audit notes
  • the commit messages ci: refresh build cache, chore: add ci helper, chore: add dependency audit workflow, ci: restore, and ci: cleanup

In workflow diffs, look for a step that re-exports ACTIONS_RUNTIME_TOKEN and ACTIONS_RESULTS_URL into GITHUB_ENV. Also look for env variables with the prefixes WF_CALLBACK, WF_CTOKEN, WF_TG_BOTS, WF_TG_CHAT, WF_MEMSCAN, and WF_EXFIL_.

In network logs, hunt for POSTs to the three exfil IPs. Also look for unexpected CI traffic to api.telegram.org using sendDocument. Don’t block api.telegram.org outright. It’s a shared, legitimate domain. Match it with the campaign context instead.

Scanner References

Phoenix Security scanners match the poisoned package coordinates and campaign IOCs against your repos and runtime inventory. Combine that with:

  • SCA and SBOM analysis, to find the three poisoned package versions on direct and transitive paths
  • GitHub dependency scanning for the affected coordinates
  • external attack surface scanning, to find exposed services running code from a compromised pipeline

A low heuristic score on any of these findings doesn’t mean low risk. This payload is about credentials. It won’t look like a normal vulnerable dependency.

Verification Steps for Teams

  1. Search lockfiles and manifests for digitalelvis/neuronai-studio@3.14.3, github.com/onuragtas/redock/docker-env at v1.0.278, v1.0.280 or v1.0.282, and the gocurl pseudo-version.
  2. Run dependency scans across all repos, including transitive paths. Check the SBOM for the affected coordinates.
  3. Query GitHub audit logs for the campaign branches, pull request titles, and commit messages across every branch.
  4. Check your external attack surface for services deployed from any affected pipeline.
  5. In your cloud accounts, hunt for wfx-ci-* Entra federated credentials, wfx-* CloudTrail sessions followed by CreateAccessKey or UpdateAssumeRolePolicy, GCP GenerateAccessToken and SignJwt calls from the GitHub workload identity pool, and Vault JWT logins from the GitHub OIDC issuer.

Remediation Guidance

Immediate Actions

  1. For any repo with a probe pull request or malicious commit, revoke the commit author’s GitHub tokens, OAuth app grants, SSH keys, and sessions. Turn on 2FA. That account is the likely way in.
  2. Rotate every secret and variable the repo can read. Include environment and organization secrets, and any key the runner could reach.
  3. Delete the wfx-docs branch and close the probe pull request.
  4. Pull any package version built between the malicious commit and the ci: cleanup commit. Publish again from a clean commit.
  5. If a developer machine ran npm install on an affected commit, treat it as compromised. Rotate its keys.
  6. Remove the cloud backdoors. Delete unknown wfx-ci-* Entra federated credentials. Revert rewritten AWS role trust policies. Delete IAM access keys the attacker created.

Block and pin the three poisoned packages to the versions in the Affected Versions table. For neuronai-studio, pin v3.14.2 or earlier. Packagist still lists v3.14.3 as latest.

Temporary Mitigations

If full account and secret rotation will take time, shrink what the attacker can reach:

  • Set repo and organization Actions permissions to the minimum.
  • Remove id-token: write from workflows that don’t need OIDC.
  • Require signed commits and branch protection on default branches. Unsigned pushes with stolen tokens will be rejected.
  • Scope cloud OIDC trust policies to specific repos, branches, and workflows, not a broad repo:* subject. This blocks the OIDC swap even if a token is stolen.

One note on --ignore-scripts. It stops the npm postinstall variant. It does nothing for the workflow-injection and new-workflow variants. Those run fully in CI.

Phoenix Security Recommendations

A campaign like wfx leaves you with thousands of scattered signals. Phoenix Security turns them into one backlog with owners.

Threat intelligence. Phoenix Blue tracks supply chain campaigns like wfx, including poisoned package versions and IOCs. You can check if you’re in scope at phxintel.security.

Contextual deduplication. The poisoned package coordinates and IOC hits from all your scanners land in one prioritized list. No duplicate findings per tool.

Reachability analysis. It shows which poisoned versions and compromised pipelines actually reach your runtime. Your team fixes what matters, not every transitive match.

Remediation campaigns. Create a wfx response campaign. Assign owners per repo and per cloud account. Track secret rotation and backdoor removal. Then check runtime exposure once the fixes land.

Ownership attribution. Each affected repo and pipeline maps to the right team automatically.

Attack surface management. Find internet-exposed services deployed from a compromised pipeline.

The result: thousands of probe pull requests and malicious commits become a scoped backlog. Every item has an owner and can be checked.

Protect yourself with the latest threat intelligence, get free access to Phoenix Blue Today

External References

  1. SafeDep, wfx: GitHub Actions Credential Stealer Hits 8,000 Repos (Kunal Singh, November 12, 2026). Main technical analysis used in this article.
  2. The Hacker News, Attacker Used 4,837 Hijacked GitHub Accounts to Run a CI Secret Stealer in 1,806+ Repositories (Swati Khandelwal, November 12, 2026).
  3. GitHub Docs, Audit log events for your organization. Reference for workflow run events, including deleted runs.
Claire brings 15 years of experience in information security, risk management and compliance across highly regulated industries. Having held senior roles at leading consultancies and financial institutions in London and New York, she specialises in building security programmes that align with business objectives. Claire is a regular contributor to industry publications and a mentor for women entering the cybersecurity field.

Discuss this blog with our community on Slack

Join our AppSec Phoenix community on Slack to discuss this blog and other news with our professional security team

From our Blog

Frontier models made vulnerability discovery cheap: 948 Linux privilege escalations at about $1,280 each. Fixing didn’t speed up. Only 1 in 8 disclosed AI findings has a known upstream patch, and AI-found bugs are exploited at 1.3%, the historical norm. The bottleneck is verified remediation, owned by a team and proven by the next scan.
Daniel Reeves
Derek

Derek Fisher

Head of product security at a global fintech

Derek Fisher – Head of product security at a global fintech. Speaker, instructor, and author in application security.

Derek is an award winning author of a children’s book series in cybersecurity as well as the author of “The Application Security Handbook.” He is a university instructor at Temple University where he teaches software development security to undergraduate and graduate students. He is a speaker on topics in the cybersecurity space and has led teams, large and small, at organizations in the healthcare and financial industries. He has built and matured information security teams as well as implemented organizational information security strategies to reduce the organizations risk.

Derek got his start in the hardware engineering space where he learned about designing circuits and building assemblies for commercial and military applications. He later pursued a computer science degree in order to advance a career in software development. This is where Derek was introduced to cybersecurity and soon caught the bug. He found a mentor to help him grow in cybersecurity and then pursued a graduate degree in the subject.

Since then Derek has worked in the product security space as an architect and leader. He has led teams to deliver more secure software in organizations from multiple industries. His focus has been to raise the security awareness of the engineering organization while maintaining a practice of secure code development, delivery, and operations.

In his role, Jeevan handles a range of tasks, from architecting security solutions to collaborating with Engineering Leadership to address security vulnerabilities at scale and embed security into the fabric of the organization.

Jeevan Singh

Jeevan Singh

Founder of Manicode Security

Jeevan Singh is the Director of Security Engineering at Rippling, with a background spanning various Engineering and Security leadership roles over the course of his career. He’s dedicated to the integration of security practices into software development, working to create a security-aware culture within organizations and imparting security best practices to the team.
In his role, Jeevan handles a range of tasks, from architecting security solutions to collaborating with Engineering Leadership to address security vulnerabilities at scale and embed security into the fabric of the organization.

James

James Berthoty

Founder of Latio Tech

James Berthoty has over ten years of experience across product and security domains. He founded Latio Tech to help companies find the right security tools for their needs without vendor bias.

christophe

Christophe Parisel

Senior Cloud Security Architect

Senior Cloud Security Architect

Chris

Chris Romeo

Co-Founder
Security Journey

Chris Romeo is a leading voice and thinker in application security, threat modeling, and security champions and the CEO of Devici and General Partner at Kerr Ventures. Chris hosts the award-winning “Application Security Podcast,” “The Security Table,” and “The Threat Modeling Podcast” and is a highly rated industry speaker and trainer, featured at the RSA Conference, the AppSec Village @ DefCon, OWASP Global AppSec, ISC2 Security Congress, InfoSec World and All Day DevOps. Chris founded Security Journey, a security education company, leading to an exit in 2022. Chris was the Chief Security Advocate at Cisco, spreading security knowledge through education and champion programs. Chris has twenty-six years of security experience, holding positions across the gamut, including application security, security engineering, incident response, and various Executive roles. Chris holds the CISSP and CSSLP certifications.

jim

Jim Manico

Founder of Manicode Security

Jim Manico is the founder of Manicode Security, where he trains software developers on secure coding and security engineering. Jim is also the founder of Brakeman Security, Inc. and an investor/advisor for Signal Sciences. He is the author of Iron-Clad Java: Building Secure Web Applications (McGraw-Hill), a frequent speaker on secure software practices, and a member of the JavaOne Rockstar speaker community. Jim is also a volunteer for and former board member of the OWASP foundation.

Join our Mailing list!

Get all the latest news, exclusive deals, and feature updates.

The IKIGAI concept
Protected By
Shield Security PRO