Skip to content

GhostAction Returns: Fake Security Audit Workflows Are Stealing CI/CD Secrets and Git History Across GitHub

GhostAction Returns: Fake Security Audit Workflows Are Stealing CI/CD Secrets and Git History Across GitHub

The GhostAction campaign is back. This wave isn't just taking your current secrets — it's scanning every commit you ever made.

GhostAction — Malicious Workflow Injection Concept A conceptual diagram showing a compromised maintainer account pushing a file named security-audit.yml into a repository, triggering a workflow that exfiltrates secrets to 193.32.204.199 ATTACKER Stolen PAT / session from infostealer logs inject REPOSITORY .github/workflows/ security-audit.yml ← NEW fetch-depth: 0 git log -p --all runs WORKFLOW RUN → Named Actions secrets → Working tree credentials → Full git history → AWS key pairs (ctx) curl POST → C2 C2 193.32.204 .199 Conceptual diagram — GhostAction attack chain, October 2026 Source: Generated by UnpanicTech
Conceptual overview of the GhostAction campaign: a stolen credential enables workflow injection, which exfiltrates secrets and git history to an attacker-controlled IP.

Sometime between 13:20 and 21:26 UTC on October 8, 2026, attackers running a campaign called GhostAction compromised two well-known open-source maintainer accounts on GitHub and spent less than twenty minutes bulk-pushing a malicious workflow file into hundreds of repositories. By the time anyone noticed, the workflows had already run, data had left, and the attacker's server had sent back a simple OK.

As of October 9, Socket had identified more than 500 GitHub accounts used to commit the malicious file to tens of thousands of repositories since October 7 [1]. The file is called security-audit.yml — or in earlier variants, github_actions_security.yml — and it does nothing resembling a security audit.

This is not a new vulnerability in GitHub Actions itself. There's no CVE here. What's happening is a persistent, evolving supply chain attack that turns legitimate CI/CD automation against the repositories it runs in — and this latest wave added something meaningfully worse than before: it reads your entire git history, not just your current secrets.

Who Got Hit — and How Fast It Happened

The two compromised accounts on October 8 were kitao (Takashi Kitao), author of the pyxel game engine with over 18,400 stars, and henrywoo (Henry Wu), original author of Uber's athenadriver Go library. Both accounts appear to have had personal access tokens (PATs) or active sessions stolen — most likely from infostealer logs or credential dumps that circulate in underground markets [2].

The kitao sweep ran between 13:20 and 13:44 UTC, hitting 27 repositories. The henrywoo sweep happened eight hours later — 21:10 to 21:26 UTC — and pushed the same workflow to 318 repositories in 16 minutes. That's an average of roughly one repository every three seconds. A human doesn't do that; an automated tool does.

The henrywoo push extended beyond his personal projects. Because Henry Wu is athenadriver's original author and still held write access to the Uber-owned repository, the malicious file went straight to master on an organization-owned codebase — no pull request, no review, no approval gate. The blast radius of a single stolen maintainer credential stretched into a Fortune-500 company's open-source infrastructure [2].

StepSecurity retrieved the Actions run log for the athenadriver malicious run and confirmed exfiltration: the curl POST to the attacker's server at 193.32.204[.]199 completed and the server responded with OK approximately four seconds after the workflow started [2].

GhostAction's History — This Isn't New

The campaign first appeared publicly in September 2025, when it stole more than 3,325 secrets from 817 repositories across 327 GitHub accounts. PyPI, npm, and DockerHub tokens were among the credentials taken [3]. GitGuardian documented another wave between August 31 and September 30, 2026, that pushed the workflow into 772 public repositories targeting 2,577 secrets across 373 GitHub users and organizations, including SSH keys, Azure credentials, AWS access keys, and tokens for cloud, container, and SaaS services [3].

The October wave is the same campaign with upgrades. The delivery mechanism — compromised maintainer credentials, reconnaissance, a plausibly named workflow committed directly to the default branch — is unchanged. What changed is what the workflow actually collects.

How the Workflow Works

There are two variants in active deployment, and the newer one contains both attack methods.

The original method: stealing named Actions secrets

Before committing anything, the attacker scans the repository's existing workflow files for ${{ secrets.NAME }} references — every secret the project has configured. Those exact names are templated directly into the malicious payload. When the workflow runs, GitHub automatically substitutes the actual values, and a curl command POSTs them to the C2 server.

For the pyxel repository, those secrets were CARGO_REGISTRY_TOKEN, PERSONAL_ACCESS_TOKEN, PYPI_PASSWORD, and PYPI_USERNAME. Publishing credentials — the exact tokens needed to push a malicious release of a package that tens of thousands of developers install and trust [1].

When reconnaissance finds no configured secrets, the template degrades gracefully to an empty expression that evaluates silently. The repository gets instrumented anyway, because there's a second method.

The new method: mining the entire git history

This is what makes the October wave significantly more damaging than earlier ones. The workflow checks out with fetch-depth: 0, which fetches every branch and tag — not just the current HEAD. It then runs git log -p --all to read the complete patch text of the repository's history. Against that output, it applies the same regex patterns it uses on the working tree [1] [2].

The practical implication is important: a secret you committed in 2021 and deleted the next day is still in your git history. If a branch or tag references that commit, git log -p --all will find it. Rotating your current secrets — the thing that fixed the 2025 exposure — does nothing about credentials that were ever committed to any branch, at any point in the repository's life.

The workflow also does something specifically clever around AWS keys: it captures two lines of context on either side of every AKIA or ASIA key identifier it finds, in both the working tree and the history. An AWS access key ID is useless without the corresponding 40-character secret access key. In practice, those sit a line or two apart in an .env file or a credentials config. By grabbing context, the payload reconstructs complete, usable key pairs instead of returning orphaned identifiers [1].

What Credentials Are Targeted

Thirteen regex patterns cover the credential types the current payload seeks, categorized below:

Category Credential Type Pattern / Prefix
AWS Long-term access key ID AKIA[0-9A-Z]{16}
STS temporary access key ASIA[0-9A-Z]{16}
Secret access key aws_secret_access_key
STS session token aws_session_token
AI Providers Anthropic API key sk-ant-…
OpenAI project key sk-proj-…
OpenRouter key sk-or-(v1-)?…
Source Control GitHub classic PAT ghp_[A-Za-z0-9]{36}
GitHub fine-grained PAT github_pat_…
GitLab token glpat-…
SaaS / Cloud Google / Firebase / GCP key AIza[A-Za-z0-9_-]{35}
Slack bot / user / app token xox[baprs]-…
SendGrid API key SG\.…\.…

AI provider keys appearing alongside AWS credentials says something about what these repositories tend to contain: ML and AI projects are exactly the kind of codebases where developers are running inference workloads against OpenAI or Anthropic, have billing-enabled API keys in their environments, and sometimes let those slip into a config file that ends up committed. This audience and the payload's target list are well matched [1].

The Attack Flow Step by Step

GhostAction Attack Flow Diagram Four numbered boxes connected by arrows showing: 1. Account compromise, 2. Reconnaissance, 3. Workflow injection, 4. Exfiltration 1 Account Compromise Stolen PAT / session from infostealer logs 2 Reconnaissance Scan existing workflows for secrets.NAME refs, template into payload 3 Workflow Injection Push security-audit.yml direct to default branch, triggers on next push 4 Exfiltration Secrets + working tree + full git history → curl POST to 193.32.204.199
The GhostAction attack chain: reconnaissance and injection both happen under the victim's own identity. Source: Generated by UnpanicTech.

What Makes Pyxel a Particularly Worrying Target

The kitao/pyxel repository has 18,420 stars and distributes across both PyPI and crates.io. The attacker didn't just push the generic history-sweep payload — they also templated pyxel's specific publishing credentials into the named-secrets section of the workflow. That's the reconnaissance step working as intended: the attacker read the repository's existing CI configuration, identified the exact secrets that control package releases on two package registries, and made sure to collect them [1].

The kitao account also ran the malicious workflow manually twice via workflow_dispatch at 13:36 and 13:42 UTC — hands-on-keyboard operation, not just automated deployment. The attacker re-triggered the exfiltration to verify or repeat collection [2].

As of the time of writing, no malicious package releases had been published from the compromised credentials. The exposure window remains open until they are rotated. That's a separate point worth holding onto: the absence of abuse during an observation window is not the same as the credentials being safe.

Forks Are Also Exposed

The 279 repositories in the henrywoo fork namespace each inherited the malicious workflow file. Any fork owner who enables GitHub Actions and pushes will trigger the workflow against their own working tree and their own full git history, sending results to the same collector. Private forks are, arguably, more valuable to the attacker than public ones — they're where credentials are actually stored [1].

There's also an intelligence benefit the attacker gets regardless of credential yield: every successful workflow run returns a repository identifier, so the operator ends up with a map of live execution contexts they can target in future waves.

One Control That Actually Stopped It

In one case documented by StepSecurity — the typecho-fans/plugins repository — the malicious workflow was injected in September and the attacker made two additional pushes on October 7, including a zero-change commit, purely to re-trigger it. Both runs stalled in action_required because that repository required approval for workflow runs from outside collaborators. The exfiltration never executed [2].

That's a single GitHub setting that broke the entire kill chain.

What You Need to Do

GhostAction Remediation Checklist A visual checklist showing immediate actions split into two tracks: if named Actions secrets were templated, and if the history sweep ran GhostAction Remediation — Immediate Actions IF named Actions secrets were in the payload → Rotate every secret named in the workflow file → Revoke — don't just rotate — any GitHub PAT named → Check package registry release history for unexpected versions (PyPI, npm, crates.io, container registries) → Review Actions run history — treat any completed "Security Audit" run as confirmed exfiltration → Do not push new releases until credentials rotated → Treat the account as fully compromised — revoke all sessions, PATs, OAuth grants, SSH keys → Re-enforce phishing-resistant MFA IF the history sweep ran → Run git log -p --all and scan every branch and tag, not just current HEAD → Rotate ALL 13 credential categories ever committed, even if deleted from current tree → For AWS keys found in history, review CloudTrail for the exposure window → Delete workflow from all branches, not just default → Block 193.32.204[.]199 in egress logs → Check forks — they carry the workflow file too → Enable GitHub secret scanning with push protection
Remediation splits into two tracks depending on what the workflow collected. Source: Generated by UnpanicTech, based on guidance from Socket and StepSecurity.

If you find either security-audit.yml or github_actions_security.yml in any repository you maintain, added since August 31, 2026, treat it as a confirmed breach [2]. The "Audit" step runs unconditionally — even if it finds nothing, it sends the repository identifier back to the attacker.

To check whether your organization is affected, run the following code search on GitHub while logged in:

org:your-org "AKIA_CTX_START"
org:your-org "193.32.204.199"
org:your-org "c=monami"

Replace your-org with your organization name. A zero result is a good sign. Any hit means an infected repository is indexed on the default branch.

Beyond the immediate cleanup, the structural lesson is about workflow permissions and branch protection. The approval gate — requiring review for workflow runs — is the one control documented as actually stopping this campaign mid-execution. On GitHub, that's under Settings → Actions → General → "Require approval for all outside collaborators." Requiring pull requests for changes to .github/workflows/* would have made the injection impossible without creating a paper trail. Neither control is exotic or expensive to enable.

Indicators of Compromise

Type Value
C2 IP 193.32.204[.]199 (ports 80 and 3000)
Workflow filenames security-audit.yml
github_actions_security.yml
Workflow name Security Audit / Github Actions Security
Commit messages Add security audit workflow
Update security audit workflow
Trigger security scan
POST body markers REPO=
AKIA_CTX_START
AKIA_CTX_END
URL query markers ?c=monami (named secrets found)
?c=new (history sweep only)

What Remains Uncertain

The exact method of initial account compromise hasn't been confirmed for the October 8 accounts. StepSecurity's assessment is that the credentials most likely came from infostealer logs — stolen PATs that surface in underground credential dumps and get reused across multiple campaigns. That's consistent with what was observed in the 2025 wave, but it hasn't been independently verified for kitao and henrywoo specifically [2].

As of October 9, 2026, no malicious package releases had been published using credentials harvested in this wave. That could change, and the exposure window for pyxel's publishing tokens remains open until they are rotated.

It's also not clear whether GitHub has taken down the malicious workflows across all affected repositories. Socket reported that as of October 9, the workflow remained live on the default branch of repositories including uber/athenadriver and kitao/pyxel [1].

Sources & References

  1. Socket Research Team — "New GhostAction Wave Hits Hundreds of Repos, Expanding Beyond CI/CD Secrets to Cloud Credentials" — socket.dev, October 9, 2026
  2. StepSecurity — "GhostAction Returns: Malicious 'Security Audit' Workflows Now Mine Credentials from Entire Git Histories" — stepsecurity.io, October 9, 2026
  3. The Hacker News — "Credential-Stealing GitHub Actions Workflows Planted in Tens of Thousands of Repositories" — thehackernews.com, October 9, 2026
  4. StepSecurity — Original GhostAction campaign coverage, September 2025 — stepsecurity.io
  5. GitGuardian — "GhostAction GitHub Actions Supply Chain Attack Returns" — blog.gitguardian.com, 2026
NK

Cybersecurity Researcher & Technical Editor

UnpanicTech publishes independent cybersecurity research and defensive security analysis. Naseem Khan serves as Technical Editor, with a focus on vulnerability analysis, defensive security, incident response, cloud security, and practical security engineering.