An incident-response matrix for Gheist-style CI log theft
Evidence-based analysis of the Gheist GitHub Actions secret-exfiltration campaign and GitHub Enterprise exposure management.
I incidents cross teams quickly. A repository administrator can see a branch, a security analyst can see a cloud alert, and a platform engineer can see a runner problem, while no one has the whole sequence. Gheist provides a concrete reason to join those views.
Wiz documented the core chain: a stolen GitHub token, a ci-sync-* branch, a malicious sync-check.yml, execution in private repositories or GitHub Enterprise environments, log retrieval, and run deletion. The report also described token use across users and automation accounts, private repository cloning, and later AWS Secrets Manager enumeration in enterprise organizations. The source did not establish how many organizations had secrets exposed or where the AWS credentials originated.
Matrix one: repository and workflow
The repository owner should identify suspicious branches, commits, workflow files, and runs. Check for ci-sync- plus six lowercase alphanumeric characters, ci: sync config, and .github/workflows/sync-check.yml. Determine which token pushed the change and which repositories it could reach.
Preserve the relevant branch and audit records before cleanup where policy allows. Remove the malicious workflow and held runs after evidence capture. Revoke the token. If a run executed, list every repository, organization, and environment secret the workflow could read.
Matrix two: cloud identity
The cloud team should search role-assumption and token-exchange logs for OIDC subjects containing the suspicious branch or environment. Review the role's permissions and activity during the exposure window. Look for access to secrets, policy changes, new identities, logging changes, and resource access that does not fit the normal workflow.
Do not assume the cloud credential came from GitHub. Wiz observed downstream AWS secrets enumeration but did not establish the origin of the credentials. The cloud investigation should preserve that uncertainty while checking all plausible paths.
Matrix three: runner and endpoint
The platform team should determine whether the job ran on a GitHub-hosted or self-hosted runner. For a self-hosted runner, isolate it and preserve host data. Review files, processes, cron jobs, container access, metadata requests, runner credentials, and cloud role use. Wiz identified attempts to collect these categories in the self-hosted variant while describing the job as buggy.
If the runner was persistent, rebuild it rather than trusting cleanup alone. Rotate host credentials and verify that old access fails. If the runner was ephemeral, confirm that the instance is gone and that the image and registration process did not preserve attacker-accessible state.
Matrix four: secrets and applications
The application owners should rotate secrets that the repository or runner could use. Verify downstream services reject old values. Review application logs for use after the incident. Check for new deploy keys, app installations, webhooks, and identity-provider changes.
Secret rotation should follow blast radius. Start with credentials that can create or modify access, then data and deployment credentials. Record evidence for each item instead of marking the task complete from a change ticket alone.
Matrix five: external visibility
Security operations can use ZoomEye to keep an inventory of visible GitHub Enterprise product fingerprints. The query app="GitHub Enterprise" returned 12,520 all-scope observations at the time of writing.
This view helps find services that need ownership and control review. It does not show private repositories, workflow execution, runner registration, or stolen secrets. Those findings come from GitHub audit records, repository settings, host telemetry, cloud logs, and secret-store activity.
Join the evidence
Use four fields as the join key: repository, branch, actor or token, and time. From GitHub, capture the workflow run and deletion event. From the cloud, capture the OIDC subject and role session. From the runner, capture job, process, and file evidence. From the application, capture secret use and rotation status.
The incident commander should keep three statuses separate: confirmed malicious execution, possible secret exposure, and confirmed downstream use. This structure supports decisive containment without turning every product match into a victim claim.
The exercise is worth running before the next campaign. Find one production repository, trace its token and runner path, list the secrets in scope, and time how long the evidence takes to assemble. The result shows where the response matrix has gaps.
References
Did you enjoy this article?
Recommend it — Standard Reader surfaces well-loved writing to more readers across the network.