MediumEcosystem changeOngoing

Wiz reports Gheist campaign using stolen GitHub tokens to dump Actions secrets

Wiz reports a campaign planting secret-dumping sync-check workflows via stolen GitHub tokens, hunt for ci-sync branches and rotate exposed secrets.

Published
Exploitation
Yes, according to Wiz, which reports successful runs in private repositories and GitHub enterprise environments, with no independent verification

What happened

Wiz Research reports that it has tracked an automated campaign it calls Gheist since September 15, 2026. According to Wiz, the campaign uses compromised GitHub tokens to commit a workflow named sync-check to every repository each token can access. Wiz says the workflow prints the repository’s secrets into its own log. The tool then downloads the log through the GitHub API and deletes the run seconds later Wiz.

Wiz says the campaign is named after the user agent “gheist” seen on its API requests. Wiz reports it has recovered more than 13,500 planted branches from more than 850 compromised accounts, from personal projects to private enterprise repositories Wiz. These figures come only from Wiz. The provided sources include no statement from GitHub, and no independent verification is available. Who operates the campaign is not confirmed.

How it works, according to Wiz:

  • The tool creates a branch named ci-sync- plus six random characters and commits .github/workflows/sync-check.yml with the message “ci: sync config”. The commit is unsigned and authored as the token’s owner Wiz.
  • The workflow base32-encodes the environment and toJSON(secrets). Wiz says GitHub masks secrets in logs only when they appear verbatim, so encoded values print in full. Wiz also says permissions: {} restricts the job’s GITHUB_TOKEN but not the secrets context Wiz.
  • When a repository has deployment environments, the tool adds them to a job matrix, so environment-scoped secrets are printed too. Wiz notes there is no attacker domain to block, because the data leaves through GitHub’s own API Wiz.
  • Wiz reports that one variant pushed a second job, sync-host, hours after an October 19 change. Wiz says this job was sent “apparently only” to repositories with a registered self-hosted runner. According to Wiz, the job searched the host for tokens, keys, .env files and cloud metadata credentials, including through the Docker socket. Wiz describes this job as buggy Wiz.

Wiz says a GitHub control in place since July 28, 2026 holds potentially malicious workflow runs in public repositories until a collaborator approves them. Every public Gheist run Wiz checked was stuck at action_required, so the payloads did not run. Wiz says that hold does not apply to private repositories or GitHub Enterprise Server. In those environments, Wiz reports audit logs showing ci-sync runs completing and then being deleted. In enterprise organizations, Wiz says it saw cloud credentials from the same organization used to enumerate AWS Secrets Manager hours later Wiz.

As of October 24, Wiz says the attack is ongoing and roughly two thirds of the implicated accounts are no longer available on GitHub. Wiz says it has reported the activity to GitHub Wiz. According to Wiz, the credential sources it could trace include infostealer logs and tokens exposed in earlier supply-chain compromises. Wiz also says Gheist is distinct from the GhostAction campaign Wiz.

Am I affected?

Wiz lists the following indicators Wiz:

  • Branches matching ^ci-sync-[0-9a-z]{6}$ whose only change adds .github/workflows/sync-check.yml with the commit message “ci: sync config”.
  • GitHub audit log activity from the user agent “gheist”, or workflow runs on ci-sync-* branches deleted within a minute of completing.
  • Cloud audit logs showing OIDC role assumptions or token exchanges whose subject includes a ci-sync- branch. Wiz says this finds the activity even without GitHub logs.
  • On self-hosted runners, the files .gdmp_pat, .gdmp_patg and .gdmp_sweep, or the string “gdmp-pivot” in job logs.

Wiz says runs executed in private repositories and on GitHub Enterprise Server. In public repositories, Wiz says the runs it checked were held for approval and did not execute Wiz.

What to do now

These steps are Wiz’s recommendations Wiz:

  1. Hunt for the indicators above across all repositories, GitHub audit logs and cloud audit logs.
  2. If you find a match, rotate every repository, organization and environment secret available to the affected repository. Deleting the run or the branch does not undo the exposure.
  3. Revoke the tokens that pushed the commits, and check their owners’ devices for infostealers.
  4. If a ci-sync branch ran on a self-hosted runner, treat the host and its instance role as compromised.
  5. Do not approve held sync-check runs, and do not run code from ci-sync branches.
  6. Harden your setup:
    • Require reviewers on environments with production secrets.
    • Scope OIDC trust policies to protected branches or environments.
    • Use GitHub Apps or short-lived fine-grained tokens instead of personal access tokens.
    • Run self-hosted runners as ephemeral hosts without Docker socket or unrestricted metadata access.

Sources