Gheist: Stolen GitHub Tokens Drain Secrets Through Actions Logs
The Gheist campaign uses stolen GitHub tokens to plant workflows that dump secrets into Actions logs. GitHub now holds such runs in public repos, but private repos and Enterprise Server stay exposed.
Translated from the German original with an AI language model, approved by me. Read the original
An ongoing campaign called Gheist is abusing stolen GitHub tokens to get at repository secrets. Secrets are the stored credentials that build and deploy pipelines use, such as cloud keys or API tokens. Wiz Research discovered the campaign and named it after the user agent gheist, which the attack tool sends with its GitHub API requests. The Hacker News, Help Net Security and Dark Reading are among the outlets that have reported on it.
What happens
The tool takes a stolen token and pushes a new workflow to every repository that token can write to. A workflow is an automation in GitHub Actions, GitHub's built-in CI/CD system. The planted workflow writes every secret the job can read into its own run log. The secrets are encoded so GitHub's log masking doesn't catch them. The tool downloads the log through the API and deletes the run seconds later.
The tricky part is that the data leaves GitHub through GitHub itself. There is no attacker server and no outbound connection for a firewall to block. According to Wiz, one variant also goes after the secrets of individual deployment environments, which are often production credentials. Since around October 19, another version also searches self-hosted runners for credentials. Wiz calls that variant buggy and has not seen it succeed.
How big is it?
In my original post I cited Dark Reading's figure of thousands of affected developer repos. Wiz's numbers are more precise: more than 13,500 planted branches from over 850 compromised accounts, tracked since September 15. Wiz does not say how many organizations actually lost secrets. On October 24 the campaign was still running, although about two-thirds of the accounts were no longer available on GitHub by then.
According to Wiz, the tokens come from sources including infostealer logs and earlier supply-chain attacks, such as the March compromise of the Trivy scanner. Infostealers are malware that harvest passwords and tokens from developer machines. No software vulnerability is involved, so there is no CVE and no patch. The attack abuses ordinary write access.
What has changed since the post
One detail needs adding: since July 28, GitHub has held potentially malicious workflow runs until someone with write access approves them. That only applies to public repositories on github.com. Every public Gheist run Wiz checked was stuck in that hold, which is why the title of Wiz's report says the attack "stumbles."
The hold does not cover private repositories or GitHub Enterprise Server. In those environments, Wiz saw audit logs showing the runs completing and then being deleted. In one case, cloud credentials from the same organization were used hours later to enumerate AWS Secrets Manager. Wiz doesn't say exactly where those credentials came from.
Who is affected
Any organization is at risk if its members or automation accounts hold tokens with write access that may have leaked somewhere. Private repos and self-hosted Enterprise Server instances are the most exposed.
What you should do
Check:
- Look for branches that start with
ci-sync-and contain only a new workflow file namedsync-check.yml, committed with the message "ci: sync config." - Search GitHub audit logs for runs on those branches that were deleted shortly after finishing, and for the
gheistuser agent. - If your workflows use OIDC, which lets a workflow sign in to the cloud with short-lived credentials, search your cloud audit logs for role assumptions with
ci-sync-in the subject. This works even without GitHub logs.
If a repo is affected:
- Rotate every repository, organization and environment secret the repo could access. Deleting the runs doesn't undo the leak.
- Revoke the tokens that pushed the commits, and check their owners' machines for infostealers.
- If one of these branches ran on a self-hosted runner, treat the machine and its cloud role as compromised.
- Don't approve held
sync-checkruns.
Harden:
- Require reviewers for environments that hold production secrets.
- Restrict OIDC trust policies to protected branches or environments.
- Use GitHub Apps or short-lived fine-grained tokens instead of classic personal access tokens.
My take: Gheist shows that a token with write access is effectively a key to every secret in a repo. The hold for public repos helps, but the valuable data usually lives in private repos, and there you have to protect yourself.