RC RANDOM CHAOS

Fake font steals developer credentials

GhostAction's second stage hides a credential stealer in a fake font file that runs when developers open the project in VS Code.

· 4 min read
Fake font steals developer credentials

A file named public/fonts/fa-solid-400.woff2, planted in 94 GitHub repositories, is a credential stealer dressed as a web font. It reads AWS keys, PyPI tokens, npm tokens, Git logins, Kubernetes cluster credentials, SSH private keys, and API credentials for Anthropic Claude and Google Gemini off developer machines. It ships alongside a VS Code tasks.json set to runOn: folderOpen, so opening the project in the editor runs the payload automatically. The stealer also drops a cron job that executes attacker-supplied code every five minutes and sends what it collects to a server over plain HTTP on port 8080.

This is the second stage of GhostAction, the supply chain campaign OpenSourceMalware has tracked since it began injecting malicious GitHub Actions workflows into compromised projects. The first stage depended on GitHub running those workflows. On October 9, 2026, GitHub began preventing the malicious workflow from executing, and the waves on October 10 and 12 extracted no secrets. The font-file launcher appeared six days later. “We can’t say the block caused it,” OpenSourceMalware wrote. “We can say the operator moved to a place GitHub’s controls don’t reach.” The launcher needs no CI runner and no server-side execution. GitHub cannot gate a VS Code task that fires when a developer opens the folder.

The persistence stage commits three files. The tasks.json provides the trigger. The fake font carries the stealer. The third is a second GitHub Actions workflow that activates only if the infostealer never runs, reusing the original malicious workflow with extra credential formats and one addition: if its exfil POST fails, it uploads findings to a secret GitHub gist. It travels under innocuous names like lint.yml, ci-check.yml, audit.yml, code-review.yml, and cache-cleanup.yml.

The font-file trick is borrowed. The filename fa-solid-400.woff2 matches one used in North Korea’s PolinRider campaign from January 2026.

The campaign now also goes after maintainers directly. The actor registered my-github[.]com on October 9 and pointed it at 193.32.204[.]199, the same IP used to receive data from the malicious workflow. That day, a phishing email from noreply@my-github[.]com reached an open-source maintainer dressed as a GitHub security alert, warning of a new login from Moscow with a link to secure the account. The page behind the link is a reverse proxy. It harvests the password and 2FA code as the victim types them, and runs JavaScript that silently drives GitHub’s OAuth device flow.

Paul McCarty’s description of that flow: the script receives a device code and user code, loads /login/device, extracts GitHub’s forms from the returned HTML, inserts the user code, finds the authorization form, adds authorize=1, and posts the approval through the victim’s authenticated proxied session. The victim never types the device code or clicks approve. The OAuth app comes away with repo, workflow, and read:org scopes: read/write on repositories, the ability to modify Actions workflow files, and visibility into organization membership. The token goes to my-github[.]com on TCP/8443.

A repository-scoped OAuth token is a reusable API credential, and those scopes are exactly what GhostAction needs to enumerate repositories and plant workflows under .github/workflows/. The maintainer phishing and the repo automation feed each other.

A related domain, my-gitlab[.]com, was registered 17 days earlier and follows the same my-<code-host>.com pattern, but McCarty is cautious about linking it. Different registrars, registrant records, Cloudflare nameserver pairs, IPs, ASNs, and DNS designs, with no shared certificate or account artifact. It is a useful pivot, not proof of the same operator.

The victim set is mostly stale. The 94 repositories belong to 66 owners, and 15 have since been deleted, renamed, or made private. Of the 79 still reachable, most look abandoned, one untouched for over nine years, and 65 went more than a year without a commit.

The operator is sloppy, which helps defenders. Jenn Gile, co-founder of OpenSourceMalware, points to a stealer whose environment-variable filter misses most API keys and whose home-directory search can time out and throw away its own results. One IP handles exfiltration, phishing, and noisy internet scanning all at once, which is why searching for that address still turns up infections.

If you maintain anything that could have been touched, revoke GitHub access and tokens from a clean device, change your password, audit your repositories, rotate every credential the workflows could reach, and warn anyone who cloned the affected repos. The cron job and the tasks.json outlive removal of the workflow, so cleaning the GitHub side is not enough. Check developer machines for the five-minute cron job and for the fake font under public/fonts/.


Contains a referral link.

Share

Keep Reading

Latest on the Wire

Full wire →

New signal daily · RSS

Stay in the loop

New writing delivered when it's ready. No schedule, no spam.