Threat Overview
GitGuardian published a 13 October 2026 update to its 7 October GhostAction investigation; The Hacker News reported the expanded scale on 15 October. GitGuardian’s dataset shows attackers targeted over 30,000 repositories across roughly 3,000 users/organizations after compromising about 1,900 GitHub accounts. The October 8–9 payload inserted malicious GitHub Actions workflows that executed in CI and attempted to extract 3,174 secrets, including GitHub, cloud, and AI API credentials. The malicious workflow also scanned repository contents and full Git history, including context around AWS key IDs, then used curl to POST data to 193.32.204.199. GitGuardian reports GitHub began blocking these workflows on 9 October; later 10 and 12 October injections reportedly did not execute. The number of attempted extractions is not proof all secrets were successfully stolen. The attack relies on compromised maintainer credentials and repository write access, not a published GitHub platform CVE.
References
- GitGuardian research (7 Oct, updated 13 Oct 2026): https://blog.gitguardian.com/ghostaction-github-actions-supply-chain-attack-returns/
- The Hacker News GhostAction scale report (15 Oct 2026): https://thehackernews.com/
- Socket research referenced by GitGuardian (Oct 2026): https://socket.dev/
Impacted Systems
- Platform: GitHub.com repositories and GitHub Actions CI/CD workflows, public and potentially private repositories reachable by compromised accounts. No GitHub software version/build or CVE is implicated.
- Affected components:
.github/workflows/*.yml, particularlysecurity-audit.ymlandgithub_actions_security.yml; workflow secrets, repository contents, and historical commits. - Prerequisite: Compromised maintainer account/token with repository write permission; workflow execution permissions and accessible secrets determine impact. Public GitHub-hosted runners generally do not generate an organization’s Sentinel endpoint events.
- Exposure: Secrets accessible to CI or embedded in Git history, including cloud/API credentials. The attacker IP
193.32.204.199is a reported campaign-specific exfiltration destination, not a universal indicator. - Fixed versions: Not applicable. GitGuardian says GitHub blocked the observed malicious workflow from 9 Oct 2026, but previously exposed secrets still require rotation. GitHub Enterprise Server is not specifically confirmed affected by the cited GitHub.com campaign.
Why this matters
One compromised developer identity can alter dozens of workflows, leak long-lived cloud keys, and create cross-customer exposure through shared CI/CD systems. This is particularly relevant to MSP/MSSP engineering teams, infrastructure-as-code repositories, and software supply chains.
Exploitation Status
Confirmed campaign and workflow execution. GitGuardian observed the October burst and states six injection batches executed; it reports later batches blocked by GitHub. 3,174 is attempted secrets extracted, not a confirmed count of successful exfiltrations. No confirmed exploitation of a GitHub platform vulnerability is claimed.
What this hunt looks for
Prepared indicator egress, workflow-file changes on monitored runners, git-history/secret-scanning process behavior, rare runner egress, GitHub CloudAppEvents workflow changes, AWS credential-use anomalies, and Linux Syslog fallback. These are queries for use where telemetry is ingested; no customer-specific execution or GitHub repository audit is claimed.
Required logs
Sentinel visibility depends on ingested GitHub audit/Defender for Cloud Apps activity, Defender endpoint telemetry for self-hosted CI runners, AWS CloudTrail, and forwarded Linux Syslog. GitHub-hosted Actions runner filesystem/process/network logs are not automatically in customer Sentinel. CloudAppEvents GitHub data is conditional on a configured connector and its schema. Absence of matches in these sources cannot clear GitHub repositories or unmonitored CI runners.
Hunt 01 — First pass — GhostAction exfiltration IP from onboarded CI runners or endpoints
DeviceNetworkEvents
| where TimeGenerated >= ago(45d)
| where RemoteIP == '193.32.204.199' or RemoteUrl contains '193.32.204.199'
| project TimeGenerated, DeviceName, RemoteIP, RemoteUrl, RemotePort, InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessAccountName
| order by TimeGenerated descHunt 02 — Endpoint files — unexpected GitHub Actions workflow creation or modification
DeviceFileEvents
| where TimeGenerated >= ago(30d)
| where FolderPath contains '.github' and FolderPath contains 'workflows'
| where FileName in~ ('security-audit.yml','github_actions_security.yml')
| project TimeGenerated, DeviceName, ActionType, FileName, FolderPath, InitiatingProcessFileName, InitiatingProcessCommandLine, SHA256
| order by TimeGenerated descHunt 03 — Runner process — git history scanning combined with credential extraction commands
DeviceProcessEvents
| where TimeGenerated >= ago(30d)
| where FileName in~ ('bash','sh','git','grep','curl','python','python3','pwsh','powershell.exe')
| where ProcessCommandLine has_any ('git log -p','AKIA_CTX_START','fetch-depth: 0','193.32.204.199','PERSONAL_ACCESS_TOKEN')
| project TimeGenerated, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName, FolderPath
| order by TimeGenerated descHunt 04 — Network — GitHub Actions runner contacting novel external IPs
let RunnerProcesses=dynamic(['Runner.Listener','Runner.Worker','runsvc.sh','bash','sh']);
let Recent=DeviceNetworkEvents
| where TimeGenerated >= ago(7d)
| where InitiatingProcessFileName in~ (RunnerProcesses)
| where isnotempty(RemoteIP) and not(ipv4_is_private(RemoteIP))
| summarize Hits=count(), LastSeen=max(TimeGenerated), Ports=make_set(RemotePort,10), Processes=make_set(InitiatingProcessFileName,10) by DeviceName, RemoteIP;
let Known=DeviceNetworkEvents
| where TimeGenerated between (ago(37d)..ago(7d))
| where InitiatingProcessFileName in~ (RunnerProcesses)
| summarize by DeviceName, RemoteIP;
Recent
| join kind=leftanti Known on DeviceName, RemoteIP
| order by Hits descHunt 05 — Cloud App Events — GitHub workflow modifications where connector logs are ingested
CloudAppEvents
| where TimeGenerated >= ago(30d)
| extend App=tostring(column_ifexists('Application','')), Raw=tostring(column_ifexists('RawEventData','')), Obj=tostring(column_ifexists('ObjectName',''))
| where App contains 'GitHub' or Raw contains 'github.com'
| where Raw has_any ('security-audit.yml','github_actions_security.yml','.github/workflows','workflow_dispatch') or Obj has_any ('security-audit.yml','github_actions_security.yml')
| project TimeGenerated, Application, ActionType, AccountDisplayName, IPAddress, Obj, Raw
| order by TimeGenerated descHunt 06 — AWS CloudTrail — anomalous secret retrieval or credential enumeration after potential CI compromise
AWSCloudTrail
| where TimeGenerated >= ago(30d)
| where EventName in~ ('GetSecretValue','GetParameter','GetParameters','ListSecrets','ListAccessKeys','CreateAccessKey','GetCallerIdentity')
| extend Principal=tostring(column_ifexists('UserIdentityArn','')), SourceIP=tostring(column_ifexists('SourceIpAddress',''))
| summarize Calls=count(), DistinctActions=dcount(EventName), Actions=make_set(EventName,15), FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated) by Principal, SourceIP, bin(TimeGenerated,1h)
| where Calls >= 20 or DistinctActions >= 4
| order by Calls descHunt 07 — Linux runner Syslog fallback — malicious workflow payload strings in forwarded audit/process logs
Syslog
| where TimeGenerated >= ago(30d)
| where SyslogMessage has_any ('193.32.204.199','security-audit.yml','github_actions_security.yml','AKIA_CTX_START')
| project TimeGenerated, Computer, ProcessName, SyslogMessage
| order by TimeGenerated descDetection Notes
- Highest signal: Query 01 connection to reported exfiltration IP; query 02 unexpected workflow creation on self-hosted runners; query 05 GitHub audit activity if GitHub CloudAppEvents ingestion exists.
- Important limitation: Most GitHub-hosted runners are ephemeral and external; DeviceProcessEvents and DeviceNetworkEvents in a customer workspace usually cannot observe their commands or exfiltration. No Sentinel match does not establish that workflows were clean.
- CloudAppEvents: GitHub integration and event coverage are not confirmed for any customer in the supplied baseline. ActionType and RawEventData are connector-dependent; query 05 may return no results without ingestion.
- AWS CloudTrail query 06 is a contextual pivot, not a GhostAction-specific signature. Secret access can be normal application behavior; correlate identities with known exposed repository secrets before escalation.
- False positives: Git history scans, workflow edits, and high-volume secrets access can be legitimate CI work. IP matching is more specific but may be bypassed by attacker infrastructure rotation. GitHub’s blocking since 9 Oct reduces, but does not erase, earlier exposure.