- OpenSourceMalware reports that GhostAction now plants a stealer disguised as a font file in 94 GitHub repositories. It survives deletion of the malicious workflow.
- On macOS and Linux, opening an affected repo in VS Code with automatic tasks allowed runs the stealer and installs a cron job fetching commands every five minutes.
- Revoke the attacker's access before cleaning files. Then check machines for the cron entry and rotate credentials from a clean device.
Deleting the workflow is not the same as removing the attacker
One repository owner did what the standard advice says. They spotted a malicious workflow and deleted it. The commit message read "Remove malicious workflow - security incident [skip ci]".
Nearly six hours earlier, the attacker had added two more files. One was a hidden task file. The other was a fake font file. Both were still there when OpenSourceMalware investigated.
That gap is the story. The lesson here is that cleaning files and removing access are different jobs. GhostAction's new second stage is built to exploit the difference.
What OpenSourceMalware found
GhostAction steals secrets through malicious GitHub Actions workflows. A workflow is an automation script that runs inside a repository. In the first stage, the attacker uses stolen GitHub access to add a fake "security audit" workflow to every repository the account can write to. That workflow sends the repository's secrets, and credentials from its git history, to the attacker's server.
Thijs Xhaflaire of Jamf Threat Labs found the new stage. He was hunting for victims of PolinRider, a North Korean campaign. Instead he found 94 repositories using the same file trick. They belong to 66 owners.
The OpenSourceMalware team could download 79 of the repositories. Every one of those 79 held the second stage. The other 15 had been deleted, renamed or made private.
The researchers call GhostAction a copycat, not an extension of PolinRider. They found no indicators shared with other North Korean malware they have seen.
How the fake font works
The second stage leaves three files in a repository. Together they plant a timed job on the developer's own computer.
The first file is .vscode/tasks.json. It tells the VS Code editor to run a task when someone opens the folder. The task is labelled eslint-check, so it looks like routine code checking. Its settings keep it out of sight.
The second file is public/fonts/fa-solid-400.woff2. It is not a font. It is 38 lines of plain Node.js code, and Node ignores the file extension. The third file is a backup workflow, in case the stealer never runs.
The script gathers stored Git logins, Kubernetes credentials, SSH private keys, and the login files for Claude and Gemini. It also scans the user's home folder for keys from AWS, Anthropic, GitHub, npm and PyPI. Then it sends everything to the attacker's server in one request over plain HTTP.
The researchers say the author made two mistakes. A filter misses most real API key variable names. A ten-second search timeout can throw away results when the search runs long. The researchers did not test either behavior. Neither mistake protects the credential files or SSH keys, which are read directly.
The bigger risk is the last step. The script installs a cron job, which is a scheduled task. Every five minutes the machine fetches a script from the server and runs it. The script's address includes the machine's hostname. That lets the operator give each machine different orders.
The researchers have not retrieved what the server returns. They cannot say what a third stage would do.
The trick has limits. VS Code runs such a task only in a folder the user has marked as trusted. Automatic tasks must also be switched on, either by accepting a one-time prompt or through the task.allowAutomaticTasks setting. On Windows, the researchers note, the theft would run but the cron job would not install.
A second stage that needs no GitHub runner
The researchers say GitHub began stopping the malicious first-stage workflow on October 9. In the first repository they traced, only one of ten runs finished. The other nine stalled, waiting for an approval nobody gave.
The second stage arrived on October 15, six days later. Its launcher needs no GitHub runner at all. The researchers say they cannot claim the block caused the change. They say only that the operator moved to a place GitHub's controls do not reach.
The Hacker News adds a second thread. It reports that the attacker registered the domain my-github.com on October 9. The same day, the domain appeared in a phishing email sent to an open-source maintainer.
According to OpenSourceMalware, the fake login page captured the password and two-factor code. In the background, it also approved an app with broad rights. Those rights cover reading and writing repositories, editing workflow files and seeing organization membership. The researchers have not tied this kit to the 94 repositories.
Forgotten repositories carry the same malware
Most of the 79 repositories were idle long before the attack. Before the first malicious commit, 65 had no activity for over a year, the researchers found. Forty-seven had been quiet for more than two years. One had not been touched in over nine years.
The attacker does not pick targets by hand. Automation hits every repository the stolen account can edit. So a project its owner forgot gets the same infection as the one they use daily.
The researchers draw an inference from this. Dormant projects have little automation worth stealing from. The developer's laptop, where the keys live, is the likelier prize.
The stealer also lists Claude and Gemini logins among its targets, plus variables starting ANTHROPIC and OPENAI. AI tool credentials now sit beside SSH keys in a developer's home folder, and one script collects both.
What to ask your team
Cleaning up without revoking access may not be enough. Two owners in the set removed the first-stage workflow on October 9. Both received the second stage on October 15. The researchers' simplest explanation is that the access that pushed the first stage was never revoked. They did not establish the cause. GitGuardian studied an earlier wave from August and September covering 772 repositories. By October 5, it found, just 16 percent had been effectively cleaned in public history.
Put these questions to your security team.
First, has every GitHub session, personal access token, OAuth grant, SSH key and deploy key been revoked from a clean device for any affected account?
Second, has someone listed every repository those accounts can write to, including forks and abandoned projects? Have the workflows, tasks.json and font files been removed on every branch?
Third, has anyone run crontab -l on developer machines? The researchers say to look for a line with the server's IP address or ending in #ghc2.
Fourth, is task.allowAutomaticTasks switched off, and do workflow runs require approval?
Fifth, were SSH keys, cloud, npm, PyPI and AI tool credentials rotated after each machine was contained?
Deleting a file removes evidence. Only revoking access removes the attacker.
Produced by the WebPulse Newsroom with AI assistance from the original reporting credited below, and checked against that source by our editorial review. How we use AI.
Original reporting: OpenSourceMalware.





