GitHub Actions secret theft became an urgent incident-response problem on October 26, 2026, when fresh reporting detailed how the Gheist campaign planted secret-dumping workflows in private and enterprise repositories. The campaign used stolen GitHub tokens to create more than 13,500 branches across over 850 compromised accounts, then pulled encoded credentials from Actions logs before deleting the evidence.

If one of those workflows ran, removing the branch is not remediation. Your team must treat every credential the repository, environment, or runner could reach as exposed, revoke the token that made the change, and investigate downstream cloud activity. The attack is a reminder that a workflow file is executable infrastructure, not harmless configuration.

Key Takeaway: A token that can push a workflow can turn trusted CI into a credential export path. Containment must follow the secrets and cloud roles, not stop at the repository.

What the Gheist disclosure revealed

The Hacker News reported the Gheist campaign on October 26, making it today's main hook. The report is based on Wiz Research's October 25 technical analysis, which says the activity had been tracked since September 15 and was still evolving on October 24.

Gheist starts with valid GitHub credentials, often tokens obtained from infostealer logs or earlier compromises. The automation enumerates repositories the token can access, creates a branch matching ci-sync- plus six lowercase letters or digits, and commits .github/workflows/sync-check.yml with the message ci: sync config.

The workflow prints environment data and the secrets context after encoding the output. That transformation matters because log masking generally looks for the original secret value. The operator then downloads the log through GitHub's API and deletes the workflow run within seconds.

There is no attacker-controlled exfiltration domain for a network filter to block. GitHub's own control plane carries the malicious commit, executes the job, stores the output, and delivers the log to the attacker.

Key Stat: Wiz recovered more than 13,500 planted branches from more than 850 compromised accounts. The scale turns a workflow-security weakness into an enterprise credential-rotation event.

The campaign reportedly succeeded in private repositories and GitHub Enterprise Server environments. A GitHub approval hold stopped the public-repository runs Wiz reviewed, but that protection did not cover the private and enterprise cases described in the research.

Why GitHub Actions secret theft crosses trust boundaries

Teams often treat a repository token, a workflow secret, and a cloud role as separate controls. In practice, they form a chain. If a stolen token can write a workflow, the workflow may be able to read repository secrets, request environment secrets, use an organization secret, or exchange an OpenID Connect identity for cloud access.

That chain can cross several boundaries in minutes:

  1. a developer or automation token grants repository write access
  2. a new workflow runs on the attacker's branch
  3. the job reads CI secrets or reaches a self-hosted runner
  4. cloud or registry credentials create a second foothold
  5. deleted runs and branches reduce obvious evidence

The danger is not limited to long-lived keys stored directly in GitHub. A permissive cloud trust policy may accept an OIDC subject from any branch. In that case, the attacker's workflow can request a short-lived cloud token that never existed as a stored repository secret.

Private repositories are not automatically safer. Their source code may be hidden from the public, but the workflows still execute with the authority your organization assigned. The absence of public logs can also make external discovery less likely while the attacker operates.

This is distinct from the prompt-injection path covered in Hexon's GitHub agentic workflows guide. Gheist did not need to persuade an AI agent. It used valid stolen credentials and ordinary CI features to make the platform expose its own trusted material.

Common Mistake: Setting permissions: {} and assuming the job is harmless. That limits the automatic GITHUB_TOKEN; it does not remove every secret explicitly available to the workflow or every credential present on a self-hosted runner.

Editorial illustration visualizing hunt for gheist before cleaning anything in an enterprise cybersecurity context

Hunt for Gheist before cleaning anything

Preserve evidence before deleting a suspicious branch or run. Export organization and enterprise audit logs, record the repository, actor, token type, source address, commit SHA, workflow path, timestamps, and run status, and retain any available job logs or artifacts.

Start with the published indicators:

  • branch names matching ^ci-sync-[0-9a-z]{6}$
  • .github/workflows/sync-check.yml
  • commit message ci: sync config
  • API requests with the gheist user agent
  • workflow runs created and deleted within seconds
  • unexpected branches invoking environment jobs
  • self-hosted jobs named or behaving like runner synchronization

Do not search only current branches. The campaign deleted runs, and other activity may have removed branches later. Query audit history for repository creation, ref creation, workflow changes, Actions execution, log downloads, run deletion, token use, and changes made by the same account across multiple repositories.

Correlate repository and cloud evidence

GitHub evidence tells you where the workflow ran. It may not tell you what an exposed credential did next. Correlate the timeline with AWS CloudTrail, Azure activity and sign-in logs, Google Cloud audit logs, package registries, container registries, deployment systems, secret managers, and identity providers.

Look for cloud sessions issued to unexpected branch subjects, secret enumeration, new access keys, role assumptions, registry downloads, image pushes, deployment changes, and access from infrastructure your team does not use. Include the hour before the workflow event and a generous window afterward because an attacker may stage credentials for later use.

GitHub's security incident investigation guidance recommends tracing token use and checking code, logs, and files for exposed secrets. Apply that guidance across the whole organization, not only the repository where the first indicator appeared.

Treat missing logs as evidence, not reassurance

A deleted workflow run does not prove the job failed. A missing branch does not prove the repository was untouched. If the audit trail shows a workflow was added and a run started, assume reachable credentials were exposed unless you can demonstrate that a protection gate prevented execution.

For a public repository with a run held at action_required, preserve the event and do not approve it. The secrets may not have been dumped through that run, but the pushing token is still compromised and may have reached other repositories.

Contain a GitHub Actions secret theft incident

Containment should remove the attacker's current access while preserving enough evidence to understand the blast radius. Sequence the work so a still-valid token cannot immediately steal the replacement credentials.

1. Revoke the pushing identity

Revoke the compromised personal access token, OAuth token, GitHub App credential, or automation secret. Suspend the account if you cannot identify which credential was used, then reset authentication and review active sessions, SSH keys, passkeys, authorized apps, and recently created tokens.

Investigate the endpoint or automation system that held the token. If an infostealer collected it, issuing a replacement on the same untreated device can repeat the compromise.

2. Pause risky workflow execution

Disable Actions for affected repositories or restrict allowed actions while you investigate. Block unreviewed workflow changes, detach self-hosted runners, and prevent the compromised identity from writing branches, tags, releases, or workflow files.

Preserve suspicious commits before removing them. Then delete unauthorized branches, workflows, artifacts, caches, releases, and persistence after evidence collection.

3. Rotate everything the job could reach

Build the rotation list from capability, not proof of use. Include:

  • repository, environment, and organization secrets
  • cloud access keys and deploy credentials
  • package, container, and artifact registry tokens
  • code-signing material and release credentials
  • database passwords, webhook secrets, and API keys
  • GitHub App private keys and other automation tokens
  • credentials stored on or accessible from self-hosted runners

GitHub's incident-response documentation advises rotating credentials whenever exposure is possible. Revoke first when doing so will not destroy critical evidence, then issue replacements through a clean administrative path.

Pro Tip: Track each credential with an owner, scope, revocation time, replacement time, and validation result. A vague instruction to "rotate CI secrets" almost guarantees omissions.

4. Rebuild self-hosted runners

If the workflow executed on a self-hosted runner, do not simply reconnect it. Isolate the host, capture forensic data appropriate to your response plan, rotate its instance or workload identity, and rebuild it from a known-good image.

Self-hosted runners can expose files, process environments, local caches, Docker sockets, cloud metadata, service-account tokens, and credentials for other CI systems. Hexon's malicious npm package response guide explains why runtime behavior and the executing host matter more than a clean dependency list after code has already run.

Editorial illustration visualizing reduce the value of a stolen github token in an enterprise cybersecurity context

Reduce the value of a stolen GitHub token

The durable fix is to make one stolen credential less useful. Start by separating ordinary code contribution from permission to create or modify workflows.

Require code-owner review for .github/workflows/**, reusable workflow directories, runner configuration, and deployment policy. Protect important branches, block direct pushes, and prevent bypass by administrators or bots unless a documented emergency process requires it.

Prefer GitHub Apps or fine-grained personal access tokens with narrow repository access, short expiration, and only the permissions the automation needs. Most integrations do not need unrestricted access to every private repository or permission to edit workflows.

For cloud access, replace static keys with short-lived OIDC credentials, but make the trust policy specific. Bind it to the expected organization, repository, workflow, environment, and protected branch or tag. OIDC is not a security improvement if any branch in the repository can assume the production role.

Use deployment environments with required reviewers for production credentials. Keep organization secrets opt-in, and audit which repositories can consume them. Separate build, test, release, and production identities so one workflow cannot inherit every privilege in the delivery chain.

GitHub's secure-use reference for Actions also warns that log redaction is not a true security boundary. Treat any job that intentionally prints or transforms a secret as able to disclose it.

Key Takeaway: Secret masking reduces accidental leakage. It cannot safely contain malicious code that already runs inside the job.

The same identity principle appears in Hexon's Rust supply chain attack analysis: release integrity depends on the maintainer and automation credentials that can change trusted outputs. Apply the lesson to workflows, not only package registries.

Validate recovery and keep detecting the pattern

Recovery is complete only when the old credentials fail, the new credentials work from approved paths, affected runners are rebuilt, and monitoring can detect the original behavior. Test each control with a benign workflow in a staging repository rather than assuming configuration changes took effect.

Verify that:

  1. revoked GitHub credentials can no longer authenticate
  2. unreviewed workflow changes cannot reach protected branches
  3. a workflow on an unauthorized branch cannot request production cloud access
  4. environment secrets require the intended reviewer or policy gate
  5. self-hosted runners are ephemeral or rebuilt between trust levels
  6. alerts fire on unusual workflow creation, log access, and rapid run deletion
  7. organization owners can export audit evidence before retention expires

Monitor for variants rather than only the published names. Alert when a newly created branch adds its first workflow, a workflow serializes the full secrets context, a job transforms environment output, or an account changes workflows across many repositories in a short period.

Also watch for downstream symptoms: unusual package releases, unexpected cloud role assumptions, secret-manager enumeration, altered deployment artifacts, and new automation credentials. An attacker who already collected keys does not need to repeat the GitHub indicator.

Hexon's GitLab exploitation containment guide offers a useful parallel: restoring the visible development platform is only one phase. You must also hunt for persistence and credential use in every connected system.

Make workflow authority explicit

Gheist succeeded because valid tokens and normal platform features were enough to turn CI logs into an exfiltration channel. The campaign did not need a GitHub zero-day, a conspicuous command-and-control server, or a public repository.

Your immediate priorities are clear: hunt the branch and workflow indicators, preserve audit evidence, revoke the pushing identity, rotate every reachable credential, rebuild self-hosted runners, and investigate downstream cloud activity. Then reduce who can change workflows and what those workflows can reach.

The strongest response to GitHub Actions secret theft is not another masking rule. It is an architecture in which workflow write access, secret access, runner access, and production deployment authority are separate, reviewed, and short-lived.