Gheist Campaign Is Quietly Draining GitHub Secrets From Private Repos and Enterprise Environments
An automated attack campaign has been systematically planting rogue GitHub Actions workflows to extract repository secrets, download the logs containing them, and vanish before most defenders notice. Cloud security firm Wiz has been tracking it since mid-September and named it Gheist, after the user agent string the attackers' tooling sends to GitHub's API.
The mechanics are blunt but effective. For each repository a stolen token can access, the tool creates a branch named ci-sync- followed by six random characters, then commits a single workflow file. When that workflow runs, it prints every secret the job can read, encoded in base32. GitHub normally masks secret values in logs, but its own documentation acknowledges this isn't reliable once values have been transformed. Base32 encoding is enough to sidestep the masking entirely, so the secrets print in full. The tool then pulls the log via GitHub's API and deletes the run within seconds. No attacker-controlled server is needed. No outbound connection to block. The secrets leave through GitHub's own infrastructure.
Wiz has found over 13,500 planted branches across more than 850 compromised accounts, ranging from personal projects to enterprise private repositories. It does not confirm how many of those exposures resulted in actual secret theft.
GitHub introduced a safeguard in late July that holds workflow runs it identifies as suspicious until someone with write access approves them. The catch: it only applies to public repositories on github.com. Private repositories and GitHub Enterprise Server are not covered. Every Gheist run Wiz checked in public repositories was still sitting in the approval queue, payload undelivered. In private repos and enterprise environments, audit logs show runs completing and then being deleted by the gheist user agent, with no approval gate in the way.
The attackers are not being subtle about scale. In enterprise environments, Wiz observed the tool cycling through tokens from multiple users and automation accounts within minutes, cloning private repositories, planting the workflow, and then, hours later, using cloud credentials from the same organisation to probe AWS Secrets Manager. Where those cloud credentials came from is not something Wiz's analysis was able to confirm.
One version of the tool specifically targets deployment environments within repositories, running a separate job for each one. These environments tend to hold production credentials, which makes them the more valuable target.
A newer variant, spotted around 19 October, added a second job aimed at self-hosted runners. It attempts to harvest 31 categories of credentials from the runner machine, including private keys, AWS instance role credentials, Kubernetes service account tokens, and runner credential files. Wiz describes the implementation as buggy and reports no confirmed successful execution of this job, but its existence signals where the campaign is heading.
The stolen tokens feeding Gheist have been traced to infostealer logs and earlier supply-chain compromises, including the March breach of the Trivy vulnerability scanner. The same compromised accounts are being used by other threat actors simultaneously. On 6 October, 391 accounts, many overlapping with Gheist activity, renamed roughly 1,461 repositories to impersonate cracked software and distribute malware. Three Gheist-affected accounts also show signs of PolinRider infection, malware linked to North Korea, and re-pushed their Gheist commits with a loader injected into a vite.config.js file. Wiz separately notes that Megalodon, a campaign that hit thousands of GitHub repositories in May, had previously compromised 57 of the same accounts.
As of 24 October the campaign was still active. Roughly two-thirds of the involved accounts had disappeared from GitHub, which Wiz attributes to GitHub's response after being notified.
How to check whether you've been hit
Look for branches matching the pattern ci-sync-[6 alphanumeric characters], where the only commit adds .github/workflows/sync-check.yml with the message "ci: sync config". In GitHub audit logs, search for workflow runs on ci-sync-* branches that were deleted within a minute of completing, and for any activity bearing the user agent gheist.
If your workflows authenticate to AWS or another cloud provider via OIDC, check cloud audit logs for role assumptions whose subject field references a ci-sync- branch. This works even without GitHub log collection and is one of the cleaner detection paths available.
On self-hosted runners, look for the files .gdmp_pat, .gdmp_patg, and .gdmp_sweep, and search job logs for the string gdmp-pivot.
Published indicators include the user agent gheist, branch pattern ^ci-sync-[0-9a-z]{6}$, commit message "ci: sync config", the string toJSON(secrets) }}' | base32 -w 120 in workflow content, and several git blob SHA hashes for known workflow variants.
What to do if you find one
Rotate every secret the affected repository could access: repository-level, organisation-level, and environment secrets. Revoke the token that pushed the branch and check the token owner's device for infostealer compromise. If a ci-sync branch ran on a self-hosted runner, treat the machine and any associated cloud role as fully compromised.
Do not approve held sync-check runs. Do not run anything from a ci-sync branch.
For longer-term hardening, Wiz recommends requiring human reviewers on environments holding production secrets, restricting OIDC trust policies to protected branches or specific environments, replacing personal access tokens with GitHub Apps or short-lived fine-grained tokens, and running self-hosted runners as ephemeral machines without Docker socket access or broad access to cloud metadata.
The fundamental problem here is simple and worth stating plainly: anyone with write access to a GitHub repository can read every secret configured in it. A stolen token with that access is sufficient to run this entire operation. The workflow complexity is just a delivery mechanism.