Events Secure.com at Black Hat USA 2026

Gheist: The GitHub Attack That Deletes Its Own Fingerprints

A Gheist GitHub attack planted 13,500 branches that printed repo secrets into Actions logs, then deleted the runs. See the steps and IOCs.

TL;DR: Somebody stole a pile of GitHub tokens and built a machine to spend them. It pushed one small file into every repository it could reach, read the secrets out loud, then wiped the evidence before anyone woke up.

What Happened?

Researchers have tracked the campaign since September 15, 2026, and named it after the user agent stamped on its API calls: gheist. For every repository a stolen token can reach, the tool creates a branch called ci-sync- plus six random characters and commits a single workflow file, sync-check.yml, with the message “ci: sync config”.

The workflow prints the repository secrets into its own run log in base32. GitHub masks secrets only when they appear word for word, so encoded values sail straight through. The operator then pulls the log through the API and deletes the run seconds later. More than 13,500 planted branches have been recovered across more than 850 compromised accounts.

What’s the Impact?

Nothing ever leaves GitHub. There is no attacker domain to block and no strange outbound traffic to spot. Deleting the branch does not undo the exposure either. In enterprise environments, the tool cycled through several user and automation accounts within minutes, cloned private repositories, and hours later cloud credentials from the same organization were seen enumerating AWS Secrets Manager.

Why Public Repos Got Lucky

Since July 28, 2026, GitHub has parked suspicious workflow runs in public repositories until a human with write access approves them. Every public run researchers checked sat frozen at that gate and never executed. Private repositories and GitHub Enterprise Server get no such hold. That is where runs completed, got deleted, and where cloud role assumptions later turned up in audit logs. Roughly two-thirds of the implicated accounts have since vanished from GitHub, suggesting cleanup is already underway.

It Is Getting Greedier

Around October 19, one variant added a second job aimed at runners teams host themselves. It hunts 31 token formats, private keys, environment files, Terraform state, and the Kubernetes service account token, then pivots through the Docker socket to the host filesystem. Researchers call the job buggy and have not seen it succeed. Buggy today is not the same as buggy next month.

Indicators of Compromise (IOCs)

Indicators of compromise · Gheist

What to hunt for before you rotate anything.

Published indicators for the campaign abusing stolen GitHub tokens. Nothing here is a domain or an IP, because nothing ever left GitHub. Hunt the behaviour, not the infrastructure.

Core identifiers
User agent gheistAppears on the API calls that pull and then delete the run log.
Branch pattern ^ci-sync-[0-9a-z]{6}$Two variants seen in parallel: one hexadecimal suffix, one base36.
Commit message ci: sync configUnsigned, authored as the token owner, adding only one file.
File added .github/workflows/sync-check.yml
Strings and artefacts
Workflow marker toJSON(secrets) }}’ | base32 -w 120
Runner job marker ===== gdmp-pivot:Stage header written into job logs on runners teams host themselves.
Dropped files .gdmp_pat  .gdmp_patg  .gdmp_sweep
Log separator LAFA====Printed between dumps by the later variant, likely for the operator’s parser.
Workflow blob SHAs
Plain payload f3da2b8b357dcda02fd455d314be2a95007516a6
Timeout variant d09535857a741bbb976bdc084a9a021713133291
Separator variant 1dc5af9cce950aad1eb1546ecce8565b117540c4
Runner job variant c665b778b2d822453293003e7ca0bbb2cb08e39d
Behavioural signals
GitHub audit log Workflow runs on ci-sync-* branches deleted within a minute of completing.
Cloud audit log OIDC role assumptions or token exchanges whose subject carries a ci-sync- branch. This catches the campaign even with no GitHub logging in place.

One caveat worth reading twice. The environment matrix variant differs per repository, so it has no fixed blob SHA. Hash matching alone will miss it. And a separate campaign using different workflow files exfiltrates to its own IP address, so do not blend the two indicator sets.

How to Avoid This

  • Rotate every repository, organization, and environment secret reachable from an affected repo.
  • Revoke the pushing tokens and sweep those laptops for infostealers.
  • Swap personal access tokens for GitHub Apps or tokens that expire fast and are scoped tightly.
  • Require human reviewers on any environment holding production secrets.
  • Run your own runners as throwaway hosts with no Docker socket access.

Your Pipeline Deserves a Teammate Who Reads the Audit Log

A deleted workflow run looks like nothing on a Monday morning dashboard. Somebody still has to connect that gap to a cloud role assumption three hours later, and most teams simply do not have the hours.

  • AI Teammates watch pipeline and cloud audit trails together, so a vanished run and a surprise role assumption become one case instead of two ignored events.
  • The Red Teammate tests which tokens and runners are actually reachable, and defensive Teammates harden what it proves is exposed.
  • Secret rotation, branch cleanup, and owner notification run as governed work with your approvals in the right places.
  • Every action is logged, so you can show an auditor exactly who approved what and when.
  • It sits above the stack you already own, so nothing gets ripped out to make room.