enzosoler.comreviews 09bench 9 devices
Published

Stolen GitHub logins planted a CI secret stealer in 1,800+ repos. Check yours for "docs: dependency audit notes"

Title card: Stolen GitHub logins planted a CI secret stealer in 1,800+ repos
Image: enzosoler.com

Since November 10, an attacker using 4,837 stolen GitHub accounts has pushed a credential stealer into repositories those accounts can write to, according to Aikido Security. It ran in more than 1,800 repos and erases its own workflow logs. If a probe pull request titled "docs: dependency audit notes" reached any repo you can write to, rotate every secret its workflows can read and check your AWS and Azure accounts for backdoors.

Search every GitHub repository you or your company can write to for a pull request titled docs: dependency audit notes, opened on or after November 10. If one is there, the account that opened it is compromised. If the attacker’s code also ran in that repo, every secret and cloud role its workflows can reach is in the attacker’s hands, and you should rotate all of it today.

What happened

Starting at about 12:45 UTC on Tuesday, November 10, an attacker used stolen credentials for 4,837 GitHub accounts to push a secret-stealing script into repositories those accounts could write to. Aikido Security, which first reported the campaign and calls it wfx-loot, says the probe pull requests reached 61,764 repositories and the stealer ran in more than 1,800 of them. The Hacker News summarized the findings on November 12.

A second analysis by SafeDep counted 8,093 repositories that received malicious commits between November 10 at 12:46 UTC and November 12 at 04:36 UTC. SafeDep searched only the default branches of public repositories, says the real number is higher, and says the campaign was still active when its search ran. The Hacker News found more probe pull requests opened after 05:00 UTC on Thursday.

Neither company says how the attacker got the credentials. The commits carry the real users’ names and noreply addresses with no signature, which SafeDep says points to stolen tokens. We found no public statement from GitHub on the campaign as of Thursday morning US Eastern time.

How the attack works

Aikido describes three steps for each repository a stolen token can write to:

  • Probe. A pull request titled “docs: dependency audit notes,” from a branch named wfx-docs, adds a small notes file to test write access.
  • Payload. One of three variants: a commit titled “ci: refresh build cache” that adds about 1,500 lines to an existing workflow; “chore: add ci helper,” which adds a .ci-xxxxxx.sh script plus an npm postinstall hook; or “chore: add dependency audit workflow” on a short-lived chore/ branch.
  • Cleanup. The change is reverted within about a minute, and the workflow run is deleted along with its logs.

The script collects GitHub Actions secrets and variables, the workflow’s GITHUB_TOKEN, OIDC and runtime tokens, AI service keys and credential files for AWS, Azure, Google Cloud, Kubernetes, npm, PyPI and SSH, according to Aikido. It copies the repository and its last 100 commits. On self-hosted runners it also reads cloud instance metadata.

It also tries to keep access after you rotate. Aikido says it can trade GitHub OIDC tokens for AWS, Google Cloud and Azure sessions, create long-lived AWS access keys, rewrite an AWS role’s trust policy to accept any AWS account, and add federated credentials named wfx-ci-* to Azure AD applications.

The campaign reached published packages through automated release workflows. Aikido names Packagist digitalelvis/neuronai-studio version 3.14.3 as malicious, and Go module github.com/onuragtas/docker-env tags v1.0.278 and v1.0.280, where the payload sits only in a workflow file that Go builds never run.

The npm hook variant runs on a developer’s laptop too. SafeDep found 771 repositories where the stealer arrived as a postinstall hook, which executes on any npm install.

What to do now

1. Look for the signs. In each repo you can write to, from November 10 onward, check for:

  • A pull request titled “docs: dependency audit notes” or a branch named wfx-docs.
  • Commits titled “ci: refresh build cache,” “chore: add ci helper” or “chore: add dependency audit workflow.”
  • Short-lived branches named chore/ plus eight random characters.
  • A gap in the workflow run numbers next to one of those commits. Aikido says a missing run number is often the only trace that the stealer ran.

Aikido counts 10,431 probe pull requests opened through collaborator or organization access, in repos the compromised account does not own. 92% were still open when it checked. Check your organization’s repos, not only your personal ones.

2. If a probe appeared, lock the account. SafeDep advises revoking the commit author’s personal access tokens, OAuth app grants, SSH keys and sessions, then turning on two-factor authentication.

3. If the payload ran, rotate everything. Rotate every secret and variable the repository can read, including cloud roles reachable through OIDC. Treat any machine that ran npm install on an affected commit as compromised and rotate its keys.

4. Hunt for cloud backdoors. Rotation alone does not remove them. The researchers suggest looking for:

  • Entra ID federated credentials named wfx-ci-* that you did not create.
  • AWS CloudTrail AssumeRoleWithWebIdentity or AssumeRole sessions named wfx-*, followed by CreateAccessKey or UpdateAssumeRolePolicy.
  • Google Cloud GenerateAccessToken and SignJwt calls from your GitHub workload identity pool.
  • HashiCorp Vault JWT logins from the GitHub OIDC issuer.

5. Remove the bad packages. If anyone on your team installed digitalelvis/neuronai-studio 3.14.3, treat that machine as compromised, per Aikido.

A clean branch proves nothing here

The detail that should worry engineering leaders is the cleanup. The attacker reverts the commit within a minute and deletes the run and its logs, so a repository can look untouched and still have lost every secret its CI could see. Aikido says a repo can show none of the attacker’s artifacts or cache entries and still have been hit.

Our read: this is a credential problem first and a CI problem second. Every developer account with write access is a path to your production cloud, because CI holds the keys. Scope cloud roles that trust GitHub OIDC to specific repositories and branches, keep long-lived cloud keys out of Actions secrets, and audit which third-party OAuth apps hold access to your organization. The same pattern of one leaked token opening a whole cloud account drove the stolen-key AI bills we covered last week and the Claude Code settings file that leaked secrets to public repos. It also follows a run of breaches at AI developer platforms, including Railway and Northflank, where the advice was the same: rotate, then check what the old key already did.

One email when a review goes up. Unsubscribe from any of them.