---
id: "CMP-202610-ghostaction-uses-stolen-github-tokens-to-plant-credential-st"
kind: "campaign"
aliases: []
title: "GhostAction uses stolen GitHub tokens to plant credential-stealing workflows and a fake-font VS Code stealer in thousands of repos"
severity: "high"
cvss: null
epss: null
exploited: true
status: "open"
category: "package"
products: [{"name": "GitHub Actions", "fixed": [], "affected": "repos pushed to with stolen tokens", "ecosystem": "vendor"}, {"name": "GitHub", "fixed": [], "affected": "accounts with leaked, unrevoked tokens", "ecosystem": "vendor"}, {"name": "Visual Studio Code", "fixed": [], "affected": "opening an affected repo with workspace trust", "ecosystem": "vendor"}, {"name": "AWS IAM", "fixed": [], "affected": "roles trusting GitHub OIDC without repo/branch restrictions", "ecosystem": "vendor"}, {"name": "GitHub Actions self-hosted runners", "fixed": [], "affected": "runners that executed the payload", "ecosystem": "vendor"}]
ecosystems: []
tags: ["campaign", "early-warning"]
not_affected_if: []
published_at: "2026-10-27T00:00:00+00:00"
first_seen_at: "2026-10-27T19:09:09+00:00"
updated_at: "2026-10-27T19:09:09+00:00"
sources: [{"source": "analyst", "url": null, "first_seen_at": "2026-10-27T19:09:09+00:00"}]
---

# GhostAction uses stolen GitHub tokens to plant credential-stealing workflows and a fake-font VS Code stealer in thousands of repos

The GhostAction operator uses GitHub tokens that were stolen earlier and never revoked. Between 2026-10-13 and 2026-10-21 it pushed 72,026 commits to at least 22,964 public repositories from 1,792 accounts, according to GitGuardian. The commits carry five payload families: (1) re-pointed security-audit.yml workflows; (2) seven innocuous-looking workflows that grep the repo, its history and wiki for secrets, including AI keys (sk-oat-, sk-svcacct-, gsk_, xai-); (3) self-hosted-runner workflows that read IMDS role credentials and local AWS/PyPI/npm/Docker/kube/gh/Claude/Gemini/OpenAI/Hugging Face credentials; (4) a GitHub OIDC workflow that tries to assume every AWS IAM role ARN it finds; (5) a Node.js stealer disguised as public/fonts/fa-solid-400.woff2. A hidden .vscode/tasks.json task (runOn: folderOpen) launches the stealer when a developer opens the repo in VS Code and trusts the workspace. The launcher is copied from PolinRider, a campaign originally attributed to DPRK. Three families install a cron job that fetches and runs a shell script from the C2 every 5 minutes, so cleaning the repo does not remove it. GitHub blocked the malicious workflow runs, but that does not stop the VS Code font stealer. From 2026-10-22 to 26, 188 GhostAction commits were amended and force-pushed with PolinRider loaders (multi-stage, Ethereum-resolved C2, browser and wallet stealer). Developers who opened affected repos are at risk, as are self-hosted runners and AWS accounts whose OIDC trust allows those repos. The last GhostAction commit GitGuardian saw was at 2026-10-21 04:37 UTC. Whether the two campaigns share an operator is unknown.

_Summary, check and fix written by a model from the sources; labelled as such._

## Affected

- vendor:GitHub Actions affected repos pushed to with stolen tokens fixed ?
- vendor:GitHub affected accounts with leaked, unrevoked tokens fixed ?
- vendor:Visual Studio Code affected opening an affected repo with workspace trust fixed ?
- vendor:AWS IAM affected roles trusting GitHub OIDC without repo/branch restrictions fixed ?
- vendor:GitHub Actions self-hosted runners affected runners that executed the payload fixed ?

## How to check

- On developer machines and self-hosted runners: run crontab -l and look for '#ghc2' or 'curl -s -m 10 http://193.32.204.199:8080/c2/'. Look for ~/.node_modules/.npm-ws-runner.js, .npm-ws.json and .npm-ws.pid (PolinRider). Check for connections to 193.32.204.199:8080 or 95.135.181.151:443.
- In repos, on every branch: look for .vscode/tasks.json with task 'eslint-check' and runOn folderOpen, and for public/fonts/fa-solid-400.woff2, fa-solid-300.ttf or fa-solid.lkf that are actually text/JS. Look for api.js with code after a long run of whitespace, and for unexpected workflows: audit.yml, build-check.yml, repo-health.yml, lint.yml, ci-check.yml, test-suite.yml, code-review.yml, security-audit.yml, maintenance.yml, cache-cleanup.yml, runner-maintenance.yml, cleanup-job.yml, cleanup_cache.yml, github_actions_security.yml. Check for force-pushes you did not make.
- On the GitHub account: look for a private gist named 'build cache' with a c.dat file.
- In AWS CloudTrail: look for AssumeRoleWithWebIdentity from token.actions.githubusercontent.com with unexpected repos or branches, or session names starting 'secret'.
- PolinRider SHA-256: api.js b59e598ded824c7318ca9fae4e9a6d98c9600873677ece7d9896870e3e7ced8e, fa-solid-300.ttf 7ba0a30eabfa46008d6417532533199bbf351b27f3841477e9133f43fb404d24, tasks.json 284d167f51c93b90100b7faeaec971959c1f8bb642e7ea0de50190a5a306f3d8; ETH sender 0x1eef0849eda15d87f64e51c73c8442cf3c8bcef3.

## Fix

- Delete the planted files on every branch. Do not revert 'Update' commits, because that restores the earlier malicious version.
- Revoke the pushing account's PATs, OAuth app grants and SSH keys. GitGuardian saw re-infection when tokens were kept.
- Rotate every secret in the repo, its history and wiki, plus all Actions secrets.
- On any machine that opened an affected repo in VS Code, and on any self-hosted runner: remove the '#ghc2' cron entry and the ~/.node_modules/.npm-ws* files, then rotate all local credentials (cloud, npm/PyPI/Docker registries, AI tool keys, SSH, kube, browser sessions).
- Restrict AWS OIDC trust policies to specific repos and branches, and require approval for workflow changes.
- Keep VS Code Workspace Trust on; do not trust freshly cloned repos that carry folderOpen tasks.

## Timeline

- 2026-10-27T19:09:09+00:00 analyst

## Documents

- [describes] @_r_netsec: GhostAction Crosses Paths With PolinRider https://t.co/ot0jl9ku0G https://x.com/_r_netsec/status/2115149871288406084
- [describes] GhostAction Crosses Paths With PolinRider: Inside the October Escalation (GitGuardian) https://blog.gitguardian.com/ghostaction-x-polinrider/
- [discussion] r/netsec: GhostAction Crosses Paths With PolinRider https://www.reddit.com/r/netsec/comments/1xh04rd/ghostaction_crosses_paths_with_polinrider/

---

_Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai_
