Gheist campaign abuses stolen GitHub tokens to expose Actions secrets

Cloud security company Wiz has identified an automated campaign, named Gheist, that uses stolen GitHub tokens to push malicious GitHub Actions workflows into repositories. The workflows print secrets available to a job into Actions logs, which the attackers download and then delete. Wiz has recovered more than 13,500 planted branches across more than 850 compromised accounts since tracking the activity began on September 15.
The campaign has succeeded in private repositories and GitHub Enterprise environments. Wiz says it observed activity ranging from personal projects to enterprise private repositories, although its analysis does not quantify how many organisations had secrets exposed. As of October 24, the operation was still active and changing.
How the workflow exposes secrets
For every repository reachable with a stolen token, the tool creates a branch named ci-sync- followed by six random characters. It adds .github/workflows/sync-check.yml in a commit labelled ci: sync config. The commit is unsigned, contains the token owner’s name and triggers the workflow when it is pushed.
The workflow prints its environment and every secret it can read after encoding the values in base32. GitHub masks known secret values in logs, but GitHub documentation notes that masking is not guaranteed after a value is transformed. Wiz says the encoded output no longer matches the original secret and is therefore displayed in full.
An empty permissions block restricts the job’s GITHUB_TOKEN, but does not prevent access to repository secrets. One observed variant also runs against each deployment environment, potentially reaching environment-scoped credentials. After collecting the output through the GitHub API, the tool deletes the workflow run within seconds. Because the data leaves through GitHub’s own services, there is no external attacker connection for network controls to block.
Private repositories face a different control gap
Since July 28, GitHub has held workflow runs it identifies as potentially malicious until a collaborator with write access approves them. Wiz found that every Gheist execution it checked in public repositories was held for approval and did not run. GitHub says this protection currently applies only to public repositories on github.com, not to private repositories or GitHub Enterprise Server.
Wiz also observed audit logs showing runs on the planted branches completing and being deleted with the gheist user agent. In some enterprise cases, AWS CloudTrail recorded the organisation’s own workflows assuming AWS roles from those branches. A self-hosted runner variant, first seen around October 19, attempts to search runner machines for private keys, process environments, AWS credentials, runner files and Kubernetes service-account tokens. Wiz describes that code as buggy and reports no successful execution.
What teams should investigate and rotate
Security teams should search for branches matching ^ci-sync-[0-9a-z]{6}$, commits that add only .github/workflows/sync-check.yml with the message ci: sync config, deleted runs, and activity using the gheist user agent. Teams using OpenID Connect for cloud access should also inspect cloud audit records for role assumptions or token exchanges whose subject contains a ci-sync branch.
When a ci-sync branch is found, Wiz advises rotating every repository, organisation and environment secret the repository could access, revoking the token that pushed the change, and examining its owner’s device for infostealers. A branch that ran on a self-hosted runner should lead teams to treat both the machine and its cloud instance role as compromised. Requiring reviewers for production environments, narrowing OIDC trust to protected branches or environments, and favouring short-lived fine-grained tokens or GitHub Apps can reduce the value of a stolen token.

