AI & Automation

GhostAction: GitHub Supply-Chain Attack Hits Thousands of Repos

Illustration of a code repository with a security warning representing stolen API keys and credentials (ghostaction)

On October 8, 2026, two compromised GitHub maintainer accounts pushed the same single file, a workflow named security-audit.yml, into every repository they had write access to. By October 9, Socket’s research team had tracked this GhostAction wave to more than 500 compromised GitHub accounts and tens of thousands of affected repositories. The file’s name sounds like a security improvement. It does the opposite: it collects credentials from the repository and its entire history, then sends them to an attacker’s server over plain, unencrypted HTTP.

What Actually Happened in the GhostAction Wave

The two accounts involved, publicly identified as henrywoo and kitao, had legitimate write access to a combined 346 repositories, including kitao/pyxel, a popular 18,420-star game engine, and uber/athenadriver, a repository owned by Uber’s own GitHub organization. The henrywoo-linked push hit 318 repositories in a 16-minute window; the kitao-linked push hit 27 repositories in a four-minute window. That speed and uniformity, hundreds of near-identical commits across unrelated repositories in minutes, points to automated tooling driving the attack, not someone manually clicking through each one.

This is a new wave of a campaign called GhostAction, first documented by GitGuardian in September 2025 and recurring since. The earlier version only stole whatever was stored in a repository’s GitHub Actions secrets, the credentials a project’s own CI/CD pipeline uses to publish packages or deploy code. This version keeps that capability and adds something new: a search through the entire git history, not just the current code, for 13 distinct patterns matching AWS keys, GitHub and GitLab tokens, Slack tokens, SendGrid keys, and API keys for Anthropic, OpenAI, and OpenRouter specifically.

Why Searching Git History Is the Genuinely New Part

Most developers who’ve accidentally committed a credential know the fix: delete the file, commit the removal, maybe rewrite history with a force-push. What a lot of people don’t realize is that a “removed” secret often isn’t actually gone. The GhostAction workflow uses a setting called fetch-depth: 0, which tells GitHub Actions to pull the complete history of every branch and tag instead of just the current, shallow snapshot a normal checkout uses. That full history includes commits that were rewritten off the main branch but are still reachable from an old branch or tag nobody deleted, exactly the kind of leftover a maintainer reasonably assumes is gone after they “fixed” an accidental commit months or years ago.

The workflow doesn’t just grep for a credential pattern in isolation, either. For AWS keys specifically, it captures two lines of surrounding text on either side of every matched key ID, in both the current code and the full history. That detail matters because an AWS access key ID by itself authenticates nothing; it needs its paired secret access key, which typically sits a line or two away in the same configuration file or environment variable block. Capturing that surrounding context, rather than just the bare key ID, is what turns an orphaned identifier into a complete, usable credential pair.

Two Different Kinds of Damage, Stacked Together

The attack’s own design splits into two halves that cause genuinely different kinds of harm. The first half, stealing a repository’s declared GitHub Actions secrets, targets publishing credentials. For the Pyxel project specifically, that meant its PyPI and Cargo (Rust package registry) publishing tokens, credentials that let an attacker ship a malicious update to a package real users already trust and have installed. That’s a software supply-chain attack: compromise one popular open-source project’s publishing keys, and every downstream user who updates that package is now a potential victim, without ever interacting with the attacker directly.

The second half, the committed-credential history sweep, targets something different: cloud and AI service credentials that developers put directly into code or configuration files at some point, whether by mistake or through careless local development habits, and that then sat in git history even after being “removed.” An exposed AWS key pair gives direct access to whatever cloud infrastructure that key controls: compute, storage, data, and often a path to escalate further. An exposed Anthropic, OpenAI, or OpenRouter key gives an attacker the ability to run up billable usage on someone else’s account, or in some cases, access to whatever data flows through API calls made with that key.

It’s tempting to read this story as something that only matters to large, famous software projects. The more useful way to read it is by blast radius. The attack didn’t target Uber’s own repository directly; it reached uber/athenadriver because the compromised maintainer, henrywoo, happened to have write access to it as the project’s original author. That’s the real lesson here: a single compromised credential’s reach extends to every repository, personal or organizational, that the account can write to, not just the account holder’s own projects. A small, personally-maintained open-source library can become the entry point into a much larger organization’s codebase purely through an access grant nobody thought to revisit.

If You Find the Workflow in Your Own Repository

Discovering a malicious workflow file already present is a different situation from a preventive audit, and it calls for a different response. Removing the file stops the immediate data collection, but it does not undo anything that already ran. Treat any secret the workflow could have accessed, every GitHub Actions secret configured on that repository, plus any credential pattern it could have matched in the working tree or history, as compromised and rotate it, rather than assuming the exposure window was too short to matter.

Check the commit history around when the file was added for any other unexpected changes from the same window, since an attacker with write access to commit one file has the same access to commit others. And review the repository’s recent collaborator and access-token activity specifically around the commit timestamp, since that is the most direct way to identify which credential was actually used to make the malicious commit in the first place.

What This Means If Your Business Uses GitHub Actions to Deploy

A growing number of small businesses and agencies manage website deployments, whether for a WordPress site, a custom application, or an e-commerce storefront, through GitHub Actions pipelines that push code to a live server automatically on every commit. If that describes your setup, this GhostAction campaign is directly relevant to you, not just to large open-source maintainers. A workflow file with deploy credentials to your actual production hosting, sitting in GitHub Actions secrets, is exactly the kind of target this attack is built to find and exfiltrate, and a compromised deploy pipeline doesn’t just leak a credential; it’s a path to push malicious code straight onto a live, customer-facing site.

A few concrete, low-effort checks apply whether you maintain a popular open-source package or a single client’s deployment pipeline:

  • Check every repository’s .github/workflows/ directory for files you don’t recognize, especially ones with generic, trustworthy-sounding names like “security audit” or “security check.” Don’t assume a workflow file is legitimate just because its name sounds defensive.
  • Rotate any long-lived personal access token (PAT) you can’t account for the current use of. Socket’s own research didn’t determine exactly how the initial maintainer credential in this campaign was obtained, but a PAT with broad scope that’s been sitting unused for months is pure downside risk regardless of how any particular compromise happens.
  • Scan your own repositories’ full git history for committed secrets, not just the current code. Tools like gitleaks or git-secrets can search entire commit history for credential patterns, which is exactly the surface this attack exploited and that a simple review of current files would miss entirely.
  • Use scoped, short-lived credentials for CI/CD where your provider supports it, such as GitHub’s native OIDC integration with AWS or other cloud providers, instead of a long-lived static secret sitting in GitHub Actions secrets indefinitely. A credential that expires in minutes has a far smaller window of usefulness to an attacker than one that’s valid until someone remembers to rotate it.
  • Review which collaborators and integrations have write access to each repository, particularly older grants nobody has revisited. The specific damage in this campaign, reaching an Uber-owned repository through a personal maintainer account, happened entirely through a legitimate, long-standing access grant, not a new vulnerability.

Socket reported no malicious package versions had been published to PyPI or crates.io as a direct result of this campaign at the time of its research, which suggests the stolen publishing credentials hadn’t yet been weaponized into a downstream supply-chain attack. That’s a narrow window, not a resolution; the stolen credentials themselves remain valid until someone actively rotates them, regardless of whether they’ve been misused yet.

Key Takeaways on GhostAction

  • GhostAction is a campaign in which stolen maintainer credentials are used to commit a plausibly named workflow file; the October 8 wave added a sweep of the full git history for cloud and AI credentials.
  • Socket tracked more than 500 compromised GitHub accounts and tens of thousands of affected repositories by October 9.
  • Removing the malicious workflow stops further collection but does not undo what already ran, so rotate every secret it could have reached.
  • Check .github/workflows/ for files you don’t recognize, scan your full git history for committed secrets, and prefer short-lived credentials such as OIDC.
  • Socket had observed no malicious PyPI or crates.io releases from this GhostAction activity at the time of its report, but the stolen credentials stay valid until they are rotated.

Related reading: for another supply-chain case aimed at developers, see the malicious npm package that posed as a Twilio bug-bounty tool.

Source: Socket Research Team