Skip to content

Back to the catalog

Gheist: Attempted Scaled Abuse of Stolen GitHub Tokens Stumbles
wiz.iowriteup

Gheist: Attempted Scaled Abuse of Stolen GitHub Tokens Stumbles

Gheist is a campaign tracked by Wiz Research since 15 September 2026 that uses stolen GitHub tokens to push a sync-check workflow on ci-sync-* branches in every reachable repository. The workflow prints base32-encoded secrets into logs, which the tool downloads through the GitHub API and then deletes. Over 13,500 branches from 850+ accounts were recovered. The post covers the two tool variants, a buggy self-hosted runner payload, GitHub's approval hold (which does not cover private repositories), overlaps with other campaigns, hunting queries, IOCs and hardening steps.

TL;DR Wiz details the Gheist campaign that plants secret-dumping GitHub Actions workflows using stolen tokens, with hunt queries, IOCs and mitigations.
Document

What it is

Gheist is an automated campaign that Wiz Research has tracked since 15 September 2026. It uses stolen GitHub tokens to push a workflow named sync-check to every repository each token can reach. The workflow prints the repository's secrets into its own log, and the tool then downloads the log through the GitHub API and deletes the run. Wiz recovered more than 13,500 branches from more than 850 accounts. As of 24 October 2026 the campaign was ongoing, and about two thirds of the implicated accounts were no longer on GitHub.

How it works

For each repository the tool creates a branch ci-sync- plus six random characters. It commits .github/workflows/sync-check.yml with the message ci: sync config, unsigned and authored as the token owner. The push triggers the workflow.

  • GitHub masks secrets only when they appear verbatim, so base32-encoded values print in full.
  • permissions: {} limits the job's GITHUB_TOKEN but not the secrets context.
  • In repositories with deployment environments, a job matrix with environment: ${{ matrix.environment }} also prints environment-scoped secrets, often production credentials.
  • Secrets leave through GitHub's own API, so there is no attacker domain to block.

Two variants run in parallel. Tool A uses a hex branch suffix. Tool B uses a base36 suffix and, since 28 September, adds timeout-minutes: 6 and the environment matrix. On 19 October, Tool B began pushing a second job, sync-host, with runs-on: self-hosted. It searches for 31 token formats, reads /proc/*/environ, mounts the host root through the Docker socket, and collects cloud metadata and runner credentials. Wiz says this job is buggy: it looks for the wrong runner key file, its URL-credential regex is broken, and it does not collect GCP or Azure tokens.

Preconditions / Affected

  • A stolen token with push access. Sources Wiz could trace are infostealer logs and tokens exposed in earlier supply-chain compromises, such as the Trivy compromise in March 2026.
  • Public repositories are largely protected. Since 28 July 2026 GitHub holds suspicious runs until a collaborator approves them, and every public Gheist run Wiz checked sat at action_required.
  • Private repositories and GitHub Enterprise Server are not covered by the hold. Audit logs show runs completing there, and CloudTrail shows the victims' own workflows on ci-sync-* branches assuming AWS roles.
  • In one enterprise, the tool cycled through several users' and automation accounts' tokens within minutes. It cloned private repositories first, and hours later cloud credentials from that organization enumerated AWS Secrets Manager.
flowchart TD
    A[Push ci-sync branch] --> B{Repository visibility}
    B -->|Public| C[Run held: action_required]
    B -->|Private or GHES| D[Workflow runs, secrets printed]
    D --> E[Tool downloads log, deletes run]
    D --> F{Self-hosted runner?}
    F -->|Yes| G[sync-host job on host]

What to do

Hunt:

  • Branches matching ^ci-sync-[0-9a-z]{6}$ whose only change is a new .github/workflows/sync-check.yml with the message ci: sync config.
  • In GitHub audit logs, runs on ci-sync-* branches deleted within a minute of completing, and any activity from the user agent gheist.
  • If workflows use OIDC to reach the cloud, check cloud audit logs for role assumptions or token exchanges whose subject includes a ci-sync- branch. This finds Gheist without GitHub logs.
  • On self-hosted runners, look for the files .gdmp_pat, .gdmp_patg and .gdmp_sweep, and the string gdmp-pivot in job logs.

Respond:

  • Rotate every repository, organization and environment secret available to an affected repository. Deleting the run or branch does not undo the exposure.
  • Revoke the tokens that pushed the commits and check their owners' devices for infostealers.
  • If a ci-sync branch ran on a self-hosted runner, treat the host and its instance role as compromised.
  • Do not approve held sync-check runs.

Harden:

  • 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.

Wiz Defend rules named in the post: "New Workflow Completed And Deleted In Short Time Span", "Workflow Pushed With Secret Dump" and "Commit Created With Known Malicious Commit Message".

Caveats

  • The same stolen accounts also appear in other campaigns: cracked-software lure repositories (6 October), cryptomining "Windows RDP Runner" repositories (18 October), PolinRider (a DPRK-linked malware that Wiz says hid loaders in vite.config.js) and Megalodon. Branch wipes or renames from these can remove ci-sync evidence, since 610 branches were lost in the 6 October renames.
  • Gheist is distinct from GhostAction, which uses different workflow files and exfiltrates to 193.32.204[.]199.
  • The LAFA==== separator purpose is Wiz's guess (a log parser for the operator).
  • The two-thirds account loss likely reflects response activity, which Wiz states as probable, not confirmed.

Organisations named here

  • gdmp-pivot
  • Gheist
  • sync-check
  • Trivy compromise
  • Wiz Research

Technologies named here

  • Gheist tool
  • sync-check.yml workflow
  • GitHub public repositories
  • sync-host job
  • GitHub personal access tokens and automation account tokens
  • Wiz Threat Center advisory Event Explorer query
  • Wiz Defend
  • GitHub audit logs and cloud audit logs
  • GitHub
  • GitHub Actions
  • AWS
  • Docker
  • Kubernetes
  • OIDC

Techniques named here

  • Secret exfiltration through workflow logs
  • Cloud follow-on

Threat actors named here

  • Gheist Tool A
  • Free compute
  • ARTEX-using actor, overlapping with Storm-0940
  • Trivy compromise
  • GhostAction
  • PolinRider
  • Megalodon
  • DPRK