Gheist Turns Stolen GitHub Tokens Into a Secret-Dumping Service: 13,500+ 'ci-sync' Branches Print CI Secrets in Base32 — Private Repos and Self-Hosted Runners Hit

An automated campaign called Gheist uses stolen GitHub tokens to push sync-check workflows that leak every Actions secret through base32-encoded logs, then deletes the runs, across more than 850 compromised accounts.
Overview
Researchers have documented Gheist, an automated campaign that turns stolen GitHub tokens into a secret-dumping service. For every repository a stolen token can reach, the tool pushes a throwaway branch containing a workflow called sync-check. When the push triggers GitHub Actions, the workflow prints all available secrets into its own log in base32, the operator downloads that log through the GitHub API, and the run is deleted seconds later.
The campaign has been tracked since 15 September 2026. More than 13,500 planted branches across more than 850 compromised accounts have been recovered, from personal projects to private enterprise repositories. Activity was still ongoing and evolving as of 24 October.
The Campaign
The mechanics are simple and abuse only legitimate platform features:
- Branch:
ci-sync-followed by six random characters (^ci-sync-[0-9a-z]{6}$). - Commit: a single unsigned commit, authored as the token owner, with the message
ci: sync config, adding only.github/workflows/sync-check.yml. - Payload: the workflow serialises the
secretscontext and pipes it throughbase32. GitHub masks secrets in logs only when they appear verbatim, so the encoded values print in full. - Exfiltration: the log is fetched via the GitHub API with the user agent
gheist, then the run is deleted. There is no attacker domain or C2 server to block.
Three design details make it effective:
permissions: {}limits theGITHUB_TOKEN, but it does not limit thesecretscontext.- An environment matrix pulls in environment-scoped secrets, which are often production credentials.
- Payloads vary per repository, defeating simple hash-based blocking.
Why Public Repositories Mostly Escaped
Since 28 July 2026 GitHub holds potentially malicious workflow runs in public repositories until a collaborator approves them. Every public Gheist run that researchers examined stayed at action_required — the control worked and the payload never ran. The hold does not apply to private repositories or GitHub Enterprise Server. There, audit logs showed ci-sync-* runs completing and being deleted by the gheist user agent, and cloud logs showed organisation workflows assuming AWS roles from those branches. In one enterprise case, cloud credentials from the same organisation were used hours later to enumerate AWS Secrets Manager.
Timeline
- 15 September 2026: Tracking begins.
- 28 September: A second tool variant appears; within hours it adds a six-minute job timeout and the environment matrix.
- 6 October: 391 accounts (some overlapping with Gheist victims) rename about 1,461 repositories into cracked-software lures.
- 18 October: 25 Gheist-affected accounts each create a "Windows RDP Runner" repository within nine minutes — free compute abuse.
- 19 October: A base32 separator (
LAFA====) and a newsync-hostjob targeting self-hosted runners are added. - 19–20 October: Three victims re-push Gheist commits carrying a PolinRider loader, an operation researchers describe as DPRK-linked.
- 25 October: Public disclosure; the activity is reported to GitHub.
Tradecraft
The self-hosted runner job is the most dangerous addition. Logging each stage under a gdmp-pivot header, it collects host details and crontab; recursively searches for 31 token formats (including AI provider keys), private keys, .env files, Terraform state and shell history; dumps process environment variables; mounts the host root filesystem through the Docker socket; queries cloud metadata for AWS instance-role credentials; and grabs runner credential files and the Kubernetes service account token. Researchers noted bugs — a wrong runner key path, a broken regex, no working GCP or Azure token collection — but the intent is full host takeover.
The tokens themselves came from infostealer logs and tokens exposed in earlier supply-chain compromises. The same accounts also appear in other campaigns, which suggests stolen GitHub credentials are being traded and reused by several actors. The tool is distinct from the earlier GhostAction campaign. No attribution has been made.
Indicators of Compromise
- User agent:
gheist - Branch regex:
^ci-sync-[0-9a-z]{6}$ - Commit message:
ci: sync config(only.github/workflows/sync-check.ymlchanged) - Payload markers:
toJSON(secrets) }}' | base32 -w 120and===== gdmp-pivot: - Runner helper files:
.gdmp_pat,.gdmp_patg,.gdmp_sweep - Workflow blob SHA-1s:
f3da2b8b357dcda02fd455d314be2a95007516a6d09535857a741bbb976bdc084a9a0217131332911dc5af9cce950aad1eb1546ecce8565b117540c4c665b778b2d822453293003e7ca0bbb2cb08e39d
Detection
List remote branches matching the pattern across your organisation's clones:
git ls-remote --heads origin | grep -E 'refs/heads/ci-sync-[0-9a-z]{6}$'
- In the GitHub audit log, search for workflow runs on
ci-sync-*branches that were deleted within a minute of completion, and for thegheistuser agent. - In CloudTrail and other cloud audit logs, look for OIDC role assumptions whose subject contains
ci-sync-. - On self-hosted runners, search job logs for
gdmp-pivotand the filesystem for the.gdmp_*files.
Recommended Actions
- Rotate every secret (repository, organisation and environment) reachable from an affected repository. Deleting the branch or run does not undo the exposure.
- Revoke the tokens that pushed the commits and check their owners' machines for infostealers.
- Treat any self-hosted runner that executed a
ci-syncbranch — and its instance role — as compromised; rebuild it. - Never approve held
sync-checkruns or execute code fromci-syncbranches. - Require reviewers on environments holding production secrets, and scope OIDC trust policies to protected branches or environments.
- Replace classic personal access tokens with GitHub Apps or short-lived fine-grained tokens.
- Run self-hosted runners as ephemeral hosts without Docker socket access or unrestricted metadata access.
Analyst Assessment
Gheist shows how far a stolen developer token now reaches: one credential becomes every secret in every repository that token can push to, extracted through GitHub's own API with nothing to block at the network edge. The approval hold for public repositories proved its value; private and Enterprise Server repositories lack that safety net and are where the damage occurred. We rate this High. Organisations should hunt for the branch pattern today and assume that any secret exposed to an affected workflow is already in the attacker's hands.