· via Hacker News – Front Page (native)
Gheist campaign used stolen GitHub tokens to plant secret-stealing workflows in 850+ accounts
Wiz Research says the Gheist campaign planted secret-dumping GitHub Actions workflows using over 850 compromised accounts, and GitHub's approval hold does not protect private or enterprise repositories.

What happened
Security researchers at Wiz are tracking a campaign, dubbed Gheist, that has been mass-abusing stolen GitHub credentials since mid-September 2026. According to Wiz Research, the operation commits a malicious workflow named sync-check into every repository a compromised token can reach. When the workflow runs, it prints that repository's secrets into its own log, which the attacker then retrieves through GitHub's API and deletes the run moments later. The tool identifies itself with the user agent gheist, which gave the campaign its name.
Wiz says it has recovered more than 13,500 planted branches across more than 850 compromised accounts, spanning everything from personal projects to private repositories owned by enterprises.
How the attack works
For each target, the tool creates a branch named ci-sync- plus six random characters, then commits a workflow file at .github/workflows/sync-check.yml with the commit message ci: sync config. The commit is unsigned but appears authored by the token's legitimate owner.
Wiz highlights three design choices that make the payload effective. GitHub masks secret values in logs only when they appear verbatim, so the workflow base32-encodes them to defeat masking. The workflow also zeroes out the job's GITHUB_TOKEN permissions, which the attacker does not need, because that restriction does not limit the secrets context. Finally, when a repository uses deployment environments, the workflow enumerates them in a job matrix so environment-scoped secrets, often production credentials, are dumped too.
Because the secrets exit through GitHub's own API, there is no attacker-controlled domain or outbound connection to block.
Escalation to self-hosted runners
Wiz observed two variants running in parallel, distinguishable by their branch-name suffixes. On October 19, one variant pushed a second job, sync-host, apparently aimed only at repositories with registered self-hosted runners. According to Wiz, that job collects host details and crontab; recursively searches the home directory, workspace and system paths for 31 token formats (including keys for AI providers such as Anthropic, Hugging Face, Groq and NVIDIA), private keys, .env files, Terraform state and shell history; reads every process environment from /proc; grabs AWS instance-role credentials, GitHub Actions and GitLab runner credential files, and the Kubernetes service account token; and tries to break out through the Docker socket by mounting the host's root filesystem into a container. Wiz notes the job is buggy, with a broken URL-credential regex and no GCP or Azure collection.
Where GitHub's control holds, and where it does not
Since July 28, 2026, GitHub has held potentially malicious workflow runs in public repositories until a collaborator approves them. Wiz found every public Gheist run it checked stuck at action_required, meaning the malicious payloads never executed. The hold does not extend to private repositories or GitHub Enterprise Server, however. There, audit logs show Gheist runs completing and then being deleted, and cloud logs show organizations' own workflows executing on attacker branches and assuming AWS roles, proving Actions ran without approval.
A shared pool of compromised accounts
The same accounts are being reused by other actors. Wiz reports that on October 6, 391 accounts renamed roughly 1,461 repositories to cracked-software lures; on October 18, 25 Gheist accounts created Windows RDP Runner repositories, apparently to abuse Actions for free compute. Some victims also show PolinRider, a DPRK-linked malware, or Megalodon activity. Traceable credential sources include infostealer logs and tokens exposed in earlier supply-chain compromises such as March's Trivy incident. Wiz stresses that Gheist is separate from GhostAction, which uses different workflow files and exfiltrates to a fixed IP address.
What defenders should do
Wiz recommends hunting for ci-sync-* branches whose only change is the sync-check workflow, audit-log entries showing runs deleted within a minute of completion, and any activity from the gheist user agent. Teams using OIDC should check cloud logs for role assumptions referencing ci-sync branches. On self-hosted runners, look for the files .gdmp_pat, .gdmp_patg and .gdmp_sweep plus gdmp-pivot strings in logs.
For remediation, Wiz advises rotating every repository, organization and environment secret reachable from an affected repository, since deleting the run does not undo exposure; revoking the pushing tokens; and treating any host that ran the self-hosted job, and its instance role, as compromised. Hardening measures include requiring reviewers on production environments, scoping OIDC trust policies to protected branches, replacing personal access tokens with short-lived fine-grained alternatives, and running self-hosted runners as ephemeral hosts without Docker socket access.
Why it matters
The attack exfiltrates secrets through GitHub's own trusted API, so network-level detection sees nothing unusual. Meanwhile GitHub's approval hold, the primary defensive control here, simply does not apply to private repositories or enterprise environments, leaving many organizations exposed exactly where they felt safest. As of October 24, Wiz says roughly two-thirds of implicated accounts are no longer available on GitHub, likely due to response activity, but the campaign is ongoing and evolving. Any team using GitHub Actions with secrets or self-hosted runners should be hunting for these indicators now.
- #github
- #security
- #github-actions
- #secrets
- #malware