wfx-loot Campaign Uses Stolen GitHub Credentials to Steal CI Secrets

· Original article ↗

Summary

Aikido says the wfx-loot campaign used stolen GitHub credentials to inject workflows into tens of thousands of repositories and steal CI and cloud credentials. It details the payload’s collection, escalation, persistence, and exfiltration methods.

Key points

  • Aikido reports 4,837 compromised accounts opened probe pull requests in 61,764 repositories; 10,431 pull requests targeted repositories through collaborator or organization access.
  • The campaign used probe pull requests and three payload delivery methods: workflow injection, an npm install hook, and a short-lived branch containing a workflow.
  • The payload collected GitHub Actions secrets, tokens, cloud credentials, local credential files, shell histories, repository data, and credentials from running processes.
  • It could escalate access through AWS, GCP, Azure, Vault, and Kubernetes, and persist by forging branch-protection checks, changing AWS trust policies, or adding Azure federated credentials.
  • Aikido gives two minimum counts—1,806 and 1,835—for repositories where the payload ran or credentials were exfiltrated; it says deleted workflow logs may obscure the impact.
  • Aikido identified a malicious Packagist package, digitalelvis/neuronai-studio 3.14.3, and workflow-file payloads in github[.]com/onuragtas/docker-env versions 1.0.278 and 1.0.280.
  • Aikido says wfx-loot overlapped with October GhostAction activity but assesses them as distinct campaigns, citing differences in infrastructure, tooling, and tradecraft.

Article Details

Attack Vectors
  • Using stolen GitHub credentials, the threat actor opened probe pull requests to confirm write access, then injected malicious GitHub Actions workflows or package install hooks into accessible repositories.
  • The payload collected GitHub Actions secrets, workflow and runtime tokens, cloud credentials, credential files, and secrets from runner environments and processes.
  • The payload used collected credentials to obtain cloud access, including by exchanging OIDC tokens, creating AWS IAM access keys, and adding Azure federated identity credentials.
  • In the related October GhostAction activity, a JavaScript stealer disguised as a font was run by a hidden VS Code task and installed a cron job that polled a command server.
Defensive Notes
  • If the payload ran in a repository, treat every secret and cloud role available to its workflows as compromised.
  • Check for the reported branch names, pull request title, commit messages, injected workflow files, and missing workflow run numbers; the probe pull request alone indicates the account was compromised.
  • Treat machines that installed or opened Packagist digitalelvis/neuronai-studio version 3.14.3 as compromised. The identified Go module tags contain the payload only in a workflow file; the article recommends removing them.
  • The article recommends checking Aikido's central feed and manually rescanning repositories; it also recommends Aikido Safe Chain for checking packages before installation.

Indicators of compromise

TypeIndicatorContext
IPV418[.]143[.]168[.]96Secondary callback server used by the wfx-loot payload to exfiltrate collected data over HTTP.
IPV4193[.]32[.]204[.]199Command server used by the related GhostAction activity; reported workflows sent stolen keys there, and the developer-machine stealer polled it for commands.
IPV4194[.]150[.]166[.]244Callback server used by the wfx-loot payload to exfiltrate collected data over HTTP.
SHA25689695abb392d5cfd4972672961e644bb46baa98aa1ed7173c2a2816c762735cfSHA-256 hash identified in the article for the wfx stealer script.

MITRE ATT&CK

T1041 · Exfiltration Over C2 ChannelIn this campaign, the payload sent collected data by HTTP POST to its callback servers.T1053.003 · CronThe related GhostAction stealer installed a cron job tagged #ghc2 to poll its command server.T1059.004 · Unix ShellThe wfx payload is a shell script executed in the GitHub Actions runner.T1059.007 · JavaScriptThe related GhostAction developer-machine stealer is JavaScript disguised as a font and run by a hidden VS Code task.T1078 · Valid AccountsThe threat actor used stolen GitHub credentials to access repositories where those accounts had write access.T1098.001 · Additional Cloud CredentialsThe payload created long-lived AWS IAM access keys and added Azure federated identity credentials to applications for persistence.T1195.002 · Compromise Software Supply ChainThe campaign's payload appeared in a Packagist package through automated publishing triggers; the article also reports affected Go module tags containing the payload in a workflow file.T1528 · Steal Application Access TokenThe payload collected GitHub PATs, OIDC and Actions runtime tokens, and other application tokens from runner environments and process memory.T1550.001 · Application Access TokenThe payload replayed cached Azure CLI refresh tokens and exchanged or used collected tokens to access cloud services.T1552.001 · Credentials In FilesThe payload searched for credentials in files including .env files, kubeconfigs, and credential files for cloud, developer, and infrastructure tools.T1552.004 · Private KeysThe payload collected SSH and GPG keys, service account keys, and other private-key material from repositories and runner files.T1552.005 · Cloud Instance Metadata APIOn self-hosted runners, the payload collected AWS, GCP, and Azure instance-metadata credentials.

Malware

Vendors

Products

Related Articles