Guide

Detect Gheist ci-sync branches in GitHub repos

Goal

Hunt every GitHub repo you can reach for Gheist's planted ci-sync-* branches, confirm a clean result, and respond correctly if you find one.

Background

Wiz Research has tracked Gheist since September 15, 2026. A stolen GitHub token is used to push a branch named ci-sync- plus six random characters into every repository the token can reach. That branch commits one workflow, .github/workflows/sync-check.yml, whose only job is to print the repository's secrets into its own Actions log. The log is downloaded through the GitHub API and the run is deleted seconds later. Wiz recovered more than 13,500 planted branches from more than 850 compromised accounts, from personal projects to enterprise private repositories. As of October 24, 2026, the campaign was still running and evolving.

Three details make it work: GitHub masks a secret in logs only when it appears verbatim, so a base32-encoded secret prints in full; an empty permissions: {} block only limits the job's own GITHUB_TOKEN, not which secrets the job can read; and where a repo has deployment environments, a variant fans the dump out across the environments, pulling environment-scoped secrets β€” often production credentials β€” too. Because the secrets leave through GitHub's own API, there is no attacker domain or outbound connection to block.

Since July 28, 2026, GitHub holds suspicious workflow runs in public repositories until a collaborator approves them β€” every public Gheist run Wiz checked sat at action_required, so those payloads never ran. Private repositories and GitHub Enterprise Server are not covered. There, GitHub audit logs show runs on ci-sync-* branches completing and then being deleted by the gheist user agent, and AWS CloudTrail shows the organizations' own workflows running on those branches and assuming AWS roles.

The campaign keeps evolving: on October 19 a second job named sync-host appeared, aimed at repositories with registered self-hosted runners β€” it sweeps 31 token types (including AI provider keys, private keys, .env files, Terraform state) and even mounts the host's root filesystem through the Docker socket. Wiz describes this job as buggy, with no successful run seen yet, but its intent is clear. On October 18, 25 Gheist accounts each created a "Windows RDP Runner" repository within nine minutes, attempting to abuse Actions for free compute.

Indicators of compromise

From Wiz's published indicators (October 25, 2026), also summarized by The Hacker News and CredenShare:

  • Branch: ci-sync- followed by six characters β€” regex ^ci-sync-[0-9a-z]{6}$. One variant uses a hexadecimal suffix, another a base36 suffix.
  • Commit: message ci: sync config, adding only .github/workflows/sync-check.yml. Unsigned, authored as the token's owner.
  • User agent: gheist in GitHub audit logs β€” the tool sends it with its API requests.
  • Strings: toJSON(secrets) }}' | base32 -w 120 and ===== gdmp-pivot: (self-hosted variant).
  • Files on runners: .gdmp_pat, .gdmp_patg, .gdmp_sweep.
  • Workflow blob SHAs: f3da2b8b357dcda02fd455d314be2a95007516a6 (plain), d09535857a741bbb976bdc084a9a021713133291 (timeout), 1dc5af9cce950aad1eb1546ecce8565b117540c4 (separator), c665b778b2d822453293003e7ca0bbb2cb08e39d (self-hosted job).
  • Run lifecycle: workflow runs on ci-sync-* branches that completed and were deleted within about a minute.

Detect

  1. Fetch and list suspicious branches in a repo:
    git fetch --all --prune && git branch -a | grep ci-sync-

    Expected output when clean: nothing. A hit looks like: remotes/origin/ci-sync-9f2ad1.

  2. Inspect the hit's single commit β€” it should touch only the workflow file:
    git log --format='%H %an %ae %s' origin/ci-sync-9f2ad1 --not main --max-count=3
    git diff --name-only origin/ci-sync-9f2ad1^ origin/ci-sync-9f2ad1

    Expected for Gheist: one commit with message ci: sync config, diff naming only .github/workflows/sync-check.yml. Compare the file's blob SHA against the indicator list above.

  3. Look inside the planted workflow for the dump markers:
    git show origin/ci-sync-9f2ad1:.github/workflows/sync-check.yml | grep -E 'base32|toJSON\(secrets\)|gdmp-pivot|sync-host' | head -5

    Expected for Gheist: lines matching base32 -w 120 and the secrets-dump markers. Do not copy the file to any public paste service β€” it references your repo's secret names.

  4. Search your GitHub audit log for the tool's user agent β€” the branch may already be deleted, but the API calls stay in the log. In the org audit-log web UI search for gheist, or via the audit-log API:
    gh api /orgs/ORG/audit-log --paginate -f include='all' -q '.[] | select(.user_agent == "gheist") | [.created_at, .action, .actor, .repo]'

    Expected when clean: no rows. Any row means the tool touched your org through its API.

  5. Check cloud audit logs for role assumptions from attacker branches β€” this works even if you do not collect GitHub logs. In AWS CloudTrail (or the equivalent for your provider), search for AssumeRoleWithWebIdentity / token-exchange events whose OIDC subject includes ci-sync-:
    aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=AssumeRoleWithWebIdentity --max-results 50 --query 'Events[?contains(CloudTrailEvent, `ci-sync-`)]'

    Expected when clean: no events. A hit proves GitHub Actions executed on an attacker branch.

  6. On any self-hosted runner, look for the variant's helper files and markers:
    find /home /opt /tmp -maxdepth 4 -name '.gdmp_*' 2>/dev/null; grep -rl 'gdmp-pivot' /var/lib/actions-runner/_diag 2>/dev/null | head

    Expected when clean: no output. Any hit means the runner host may have been swept β€” treat it as compromised.

Wiz Threat Center users can also run the Event Explorer query from the Wiz advisory, which covers planted commits, Gheist activity in GitHub audit logs, and cloud role assumptions from attacker branches.

Verify

Re-run steps 1–4 on every repo that shares a token or an owner with an affected repo. A clean result is: no ci-sync- branches anywhere, and no gheist user-agent hits in the org audit log for the last 90 days. Repeat the hunt quarterly, and immediately after any token-theft alert β€” infostealer logs and earlier supply-chain compromises are the traced sources of Gheist's stolen tokens.

Respond

  • Rotate every repository, organization, and environment secret the affected repo could read. Deleting the branch or the run 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 cloud instance role as compromised.
  • Do not approve held sync-check runs, and do not run code from ci-sync branches.
  • To make the next stolen token less useful: require reviewers on environments with production secrets, scope OIDC trust policies to protected branches or environments, and use GitHub Apps or short-lived fine-grained tokens instead of personal access tokens.

Our tool

gheist-guard is our local, deterministic, read-only CLI that detects this attack shape: branch pattern, workflow identity, dump content, run lifecycle, and the gheist user agent β€” one command, one verdict per repository. It is not affiliated with Wiz. What it does not do: it does not search your cloud audit logs, and it does not revoke tokens or rotate secrets β€” those stay your response steps.

Gheist vs GhostAction

Do not mix these up β€” they are distinct October 2026 campaigns. Gheist (tracked by Wiz) plants sync-check.yml on ci-sync-* branches and exfiltrates secrets through GitHub's own API log download β€” no C2 server. GhostAction (reported by GitGuardian) plants security-audit.yml workflows and exfiltrates secrets to an external server (193.32.204[.]199). Per GitGuardian via The Hacker News, GhostAction reached 30,000+ repositories across 3,000 organizations from 1,900 compromised accounts. Different workflow filenames, different network behavior, same cure: rotate the secrets.

Sources

  • Wiz Research, "Gheist: Attempted Scaled Abuse of Stolen GitHub Tokens Stumbles" (2026-10-25)
  • The Hacker News, "Gheist Uses Stolen GitHub Tokens to Steal Private Repository Secrets via Actions Logs" (October 2026)
  • CredenShare, "Gheist: stolen GitHub tokens used to dump Actions secrets" (2026-10-27)

Last updated: 2026-10-30. Edit on GitHub Β· Report an issue

← Previous guide Β· Next guide β†’

Still stuck? Get deployment help β†’