GitHub and wfx-loot: Steps to Detect and Contain Secret Theft

GitHub and wfx-loot: Steps to Detect and Contain Secret Theft

The wfx-loot campaign affected 4,837 compromised accounts and tested write permissions across 61,764 GitHub repositories; in at least 1,835 of them, it ran code that stole secrets and cloud credentials, according to Aikido. The initial indicator is a pull request titled docs: dependency audit notes, but finding it is not enough to know whether the stealer ran.

The attackers used stolen credentials to probe repositories, including ones the accounts could access as collaborators. They then injected a script into GitHub Actions workflows, shell scripts, or an npm installation hook, and often deleted the changes and logs. The absence of a log does not rule out exfiltration: researchers recommend treating secrets as exposed if the payload ran.

1. Look for indicators in every repository

  1. Review all repositories that your account or automation accounts could write to since November 10. Aikido says the campaign began at approximately 12:45 UTC that day. Include organization repositories and those accessible as a collaborator, not just repositories owned by your user. The scope followed write permissions.

  2. Look for a wfx-docs branch and a pull request titled docs: dependency audit notes. Also watch for short-lived branches with names such as chore/ followed by eight random characters, or ci-check- followed by four digits. That pull request serves as proof of access: it is not itself the payload, but Aikido considers the account that opened it compromised, even if there are no other changes.

  3. Examine the commit history for ci: refresh build cache, chore: add ci helper, and chore: add dependency audit workflow. The indicators also include ci: restore and ci: cleanup, used during cleanup. Commit messages can reveal the injection, even if the change has already been reverted.

  4. Inspect the associated files and changes: a modification to an existing workflow, a new file in .github/workflows/ with a name resembling build-audit-, or a hidden .ci- script connected to a hook in package.json. StepSecurity also observed code added to shell scripts that workflows were already running. Therefore, do not limit your review to workflow files.

2. Determine whether the code actually ran

  1. In the Actions history, review runs around the suspicious commit and look for gaps in the numbering. Aikido describes a missing run number as a more reliable indicator than looking for artifacts: the attacker deleted runs and logs, sometimes in less than a minute. A gap may be the only visible trace.

  2. Do not assume a run is clean because you cannot find artifacts with names such as wfx-loot-, cache entries containing wfx-, or summaries marked with WFX-BEGIN. Aikido explains that these methods were disabled in the samples from this campaign that it analyzed; in addition, data could be sent through other channels. The absence of these indicators does not prove that no data was extracted.

  3. If the repository automatically published packages, check whether any changes propagated. Aikido identified digitalelvis/neuronai-studio 3.14.3 on Packagist and github.com/onuragtas/docker-env in versions v1.0.278 and v1.0.280. The Hacker News also points to the github.com/vkuznet/gocurl module in pseudo-version v0.0.0-20261111095532-8d5aad0cb0da. In this last case, its analysis indicates that the malicious workflow had not run. Check the exact version before taking action.

  4. Separately assess machines that installed or opened Packagist package 3.14.3: Aikido advises treating them as compromised. The Hacker News clarifies that a normal Composer installation does not run the stealer, but an npm install inside the package directory can. For the affected Go module versions, the payload was only in a workflow file; Aikido and The Hacker News say that the Go code and published binaries were unchanged, although they recommend removing those versions.

GitHub y wfx-loot: pasos para detectar y contener el robo de secretos
© Aikido Security

3. Contain access and rotate anything that may have been exposed

  1. If you confirm that the payload ran, consider all secrets, variables, tokens, and cloud roles accessible to those workflows exposed. Rotate them immediately. The script was designed to collect GitHub Actions, AWS, Azure, and Google Cloud credentials, among others, as well as configuration files, SSH keys, and development tool credentials. Limit rotation to the right set, but do not narrow it based on guesswork.

  2. Revoke credentials for the accounts and automation that opened the pull requests or pushed the suspicious commits. SafeDep, cited by The Hacker News, recommends revoking tokens, OAuth app authorizations, SSH keys, and sessions, as well as enabling two-factor authentication. Pay particular attention to bots with write permissions: StepSecurity observed commits published under automated accounts.

  3. Look for signs of persistence in the cloud providers the workflow could access. The Hacker News recommends checking Entra ID for federated credentials with the wfx-ci- prefix; AWS CloudTrail for AssumeRoleWithWebIdentity sessions or names beginning with wfx- followed by CreateAccessKey or UpdateAssumeRolePolicy events; and GCP for GenerateAccessToken and SignJwt calls from GitHub's workload identity. Aikido describes changes that could maintain access even after secrets were rotated.

  4. Also check HashiCorp Vault logs and the cloud roles associated with the affected workflows. The Hacker News suggests looking for JWT logins from GitHub's OIDC issuer in Vault. If a role or policy was modified, restore its legitimate configuration and remove unauthorized credentials; do not consider the incident resolved just because the old tokens no longer work.

  5. If you find malicious changes, preserve the available data for investigation before cleaning up the repository, and remove or revert the injected code. Check branches, workflows, shell scripts, and npm hooks. The attacker's rollback is not remediation: the code may have run and extracted credentials before its traces were deleted.

Mistakes that can leave access open

Do not confuse the test pull request with the payload. The former proves that an account could write to the repository; the malicious payload came later and not in every case. Conversely, finding only the pull request does not mean the account is safe: Aikido considers the account that opened it compromised.

Do not rely solely on the changes having disappeared, the workflow showing as successful, or the absence of artifacts. The attackers reverted commits and deleted runs, and StepSecurity documented that the code could also be hidden in scripts already used by automation. Verify the history and cloud access, not just the current state of the file tree.

Finally, do not apply the same conclusion to every package. Packagist 3.14.3 can run the code if npm install is run in its directory; according to Aikido, the docker-env versions contain the payload in a workflow, not in the Go code or binaries. The gocurl version identified by The Hacker News also carries the code in a workflow that had not run. Responses should reflect these differences while still blocking the identified versions.

Sources: TechRadar, BleepingComputer, Aikido Security, StepSecurity, The Hacker News