Book a demo →
← All posts
Threat Watch

GhostAction Adds GitHub Device Code Phishing and a Font-File Stealer

A year-old GitHub supply chain campaign now emails maintainers a fake sign-in alert and plants a stealer that runs when a project folder opens.

GhostAction Adds GitHub Device Code Phishing and a Font-File Stealer

AegisAI Threat Watch · Device code phishing

GhostAction Adds GitHub Device Code Phishing and a Font-File Stealer

A year-old GitHub supply chain campaign now emails maintainers a fake sign-in alert and plants a stealer that runs when a project folder opens.

Analysis based on OpenSourceMalware and GitGuardian research, 9 to 16 Oct 2026.

GhostAction, the GitHub supply chain campaign that has been stealing CI secrets since September 2025, now starts in the inbox. Its operators sent a forged GitHub sign-in alert to an open source maintainer, routed the click through a reverse proxy of GitHub's login, and loaded a script built to approve a GitHub OAuth device code in the background, so the victim would never see or type a code.

A week later the same infrastructure was receiving data from a second payload: a credential stealer committed to 94 repositories as a file named to look like a web font, set to run when a developer opens the project in Visual Studio Code. Both moves came after GitHub began blocking the campaign's original workflow on 9 Oct 2026.

30,000+
repositories targeted in the October 2026 wave
~1,900
GitHub accounts compromised to push the malicious workflows
94
repositories carrying the fake font-file stealer
66
owners of those repositories

Sources: GitGuardian, updated 13 Oct 2026; OpenSourceMalware, 16 Oct 2026.

Key judgments

  • GhostAction has moved from abusing accounts it already controls to phishing maintainers for new ones. The lure is a forged GitHub security alert, which puts an email at the front of a software supply chain attack.
  • The phishing kit is built to turn one captured sign-in into a reusable OAuth token with repository and workflow write access, without the victim typing a device code. Researchers confirmed the capability in the page source but did not see the grant complete in the one documented case, where an additional MFA challenge stopped the attacker.
  • The second stage no longer needs GitHub Actions. A fake font file and an editor task run the stealer on the developer's own machine when the project folder opens, outside the runner that GitHub began blocking on 9 Oct.
  • One server, 193.32.204.199, receives the CI secrets, the phishing tokens and the stealer's output. That shared infrastructure links the stages even though no operator has been publicly named.

The phishing stage is built to skip the device code

How the GitHub device flow normally works

The OAuth device flow exists for tools that cannot open a browser, such as command line clients. The tool shows an eight-character code, the user enters it at github.com/login/device and approves the request, and the tool then receives an access token; the code expires after 15 minutes (GitHub Docs). The step that matters for defense is the human one: someone has to type the code and click Authorize, which is exactly where device code phishing, as in the Kali365 kit, aims its social engineering.

The GhostAction kit is designed to remove that step. According to OpenSourceMalware, the proxied login page carries a script that requests a device code for the attacker's OAuth app, loads GitHub's device page inside the victim's freshly authenticated session, and submits the approval form itself. The token is then sent to my-github.com on port 8443.

What the token would be worth

The script asks for three scopes. On GitHub, repo grants full access to public and private repositories, workflow allows adding and changing Actions workflow files, and read:org exposes organization and team membership (GitHub Docs). That is the exact access GhostAction needs to enumerate a maintainer's repositories and push its own workflows into them, and unlike a session cookie it is a token that works directly against the API.

The evidence has a limit. The captured traffic from the documented case contains none of the OAuth requests, so the device grant is confirmed as a capability of the page, not as a completed theft. The proxy did capture the victim's password and one-time code, and the attacker signed in, but an additional MFA challenge stopped the session from going further.

The lure borrows GitHub's own alert

The email copies GitHub's new sign-in notice: "[GitHub] New sign-in from Moscow, Russia", sent from noreply@my-github[.]com, with a link to secure the account. The pretext is well chosen. An unexpected login from abroad is the kind of message a maintainer is trained to act on quickly, and acting on it means signing in.

The domain my-github.com was registered on 9 Oct 2026 and points at 193.32.204.199, the server GhostAction already used to collect secrets from its malicious workflows (OpenSourceMalware). A second domain on the same pattern, my-gitlab.com, was registered 17 days earlier, but it uses a different registrar, nameservers and IP address, and the researchers treat a link to GhostAction as a hypothesis rather than a finding.

The second stage moves off the runner

GitGuardian reported that GitHub began blocking the campaign's malicious workflow on 9 Oct, and that later waves on 10 and 12 Oct ran the same payload without extracting any secrets (GitGuardian). The next payload does not depend on a runner at all.

In 79 repositories that OpenSourceMalware could still clone, the operators committed three files: a hidden VS Code task labeled eslint-check and set to run on folder open, a 38-line Node.js script saved as public/fonts/fa-solid-400.woff2, and a second workflow under a rotating name such as lint.yml, ci-check.yml or repo-health.yml (OpenSourceMalware). The stealer reads cloud, package registry, Git, Kubernetes and SSH credentials, along with Claude and Gemini login files, posts them over plain HTTP to port 8080 on the same server, and installs a cron job that fetches and runs new commands every five minutes. If the upload fails, the workflow saves the findings to a secret gist instead.

The targets were mostly quiet projects. Before the first malicious commit, 65 of the 79 repositories had gone more than a year without a commit, which makes them easy to modify unnoticed and still trusted by anyone who clones them. OpenSourceMalware calls the font trick a copycat of PolinRider, a campaign linked to North Korea, and found no shared indicators between the two; it also states that the timing alone cannot show GitHub's block caused the shift.

Block the runner and the stealer moves to the laptop. Protect the password and the kit asks for a token instead.

AegisAI Threat Intelligence

Why standard controls miss it

Every action in the phishing stage happens inside a real GitHub session. The device page is GitHub's own, the approval is a normal form submission, and the result is a token issued by GitHub to a registered OAuth app; the only signal is that the person never meant to approve it. One-time codes do not help here, since the proxy relays them, and controls that look only at whether a sign-in succeeded will record a legitimate login.

The second stage hides in files that reviewers skim. A .woff2 file under public/fonts is expected to be binary noise, and an editor configuration file rarely gets the scrutiny of source code, yet together they execute code on the machine that holds the developer's credentials. This is a gap in where review happens, not a new exploit.

How Aegis protects against it

The phishing stage of this campaign arrived by email: a forged GitHub sign-in alert with a link to a proxied login. That is the part of the chain an email defense can stop.

AegisAI's agents evaluate the message and the destination it points to together, and pull a malicious message out of mailboxes before users see or click it. When a lure or a compromised session is caught, the response compounds: the message is withheld at classification, copies already delivered are retracted, rewritten links refuse a late visit, the account's outbound and internal mail gets rescanned, and lateral phishing attempts to colleagues are blocked at the same bar rather than treated as a fresh, unrelated message. More on how that works: inbound email security.

The font-file stage spreads through repositories, not mail, and is outside what an email control sees; the recommendations below cover it.

Related: how the Kali365 device code phishing kit defeated MFA without breaking it and account takeover protection.

What the reporting does not tell us

Scale. One phishing victim has been documented. How many maintainers received the email, and whether any device code token was actually issued, has not been reported.

Timing. The domain was registered on 9 Oct and the kit was documented on 11 Oct, but the date the email was sent has not been published.

Attribution. No operator has been named. The link to my-gitlab.com is unproven, and the PolinRider overlap is a borrowed technique, not shared infrastructure.

Stage 3. The cron job fetches and runs whatever the server returns. What it has delivered so far is unknown.

MITRE ATT&CK mapping

IDNameUse in this campaign
T1566.002Phishing: Spearphishing LinkA forged GitHub sign-in alert links to the proxied login page.
T1528Steal Application Access TokenThe page is built to approve a GitHub OAuth device grant and send the token to the attacker.
T1195.001Supply Chain Compromise: Software Dependencies and Development ToolsCompromised repositories carry a fake font stealer and an editor task that runs it on folder open.
T1053.003Scheduled Task/Job: CronThe stealer installs a cron job that fetches and runs new commands every five minutes.

Indicators of compromise

IndicatorTypeNote
my-github[.]comDomainPhishing domain and proxy, registered 9 Oct 2026; tokens sent to port 8443.
noreply@my-github[.]comSender"[GitHub] New sign-in from Moscow, Russia" lure.
193.32.204[.]199IPCollector for CI secrets, phishing tokens (8443) and stealer data (HTTP 8080).
Ov23ctrqCqZ79UaYKwyqOAuth client IDApp the kit requests the device grant for. Worth searching in GitHub audit logs.
public/fonts/fa-solid-400.woff2File pathNode.js stealer disguised as a font, run by a VS Code task labeled eslint-check.
#ghc2Cron tagMarks the five-minute cron entry the stealer installs.
my-gitlab[.]comDomainSame naming pattern, registered 22 Sep 2026; link to GhostAction unconfirmed.

Infrastructure changes quickly. Treat these as historical indicators, not a live blocklist. Domains are defanged with [.]. Source: OpenSourceMalware.

Recommendations for defenders

  • Restrict OAuth app access at the organization level. With OAuth app access restrictions turned on, a token granted to an unapproved app loses API access to the organization's private data and cannot perform elevated writes on its public resources, which limits what a phished device grant is worth.
  • Move maintainers to phishing-resistant sign-in. Passkeys and security keys are bound to github.com, so a proxy on a look-alike domain has no one-time code to relay. Codes sent by app or SMS were captured in this campaign.
  • Review authorized apps and the audit log after any suspect sign-in. Revoke OAuth apps and tokens no one recognizes, look for new grants with the workflow scope, and search for the client ID above.
  • Treat editor configuration as code. Review changes to .vscode/tasks.json and unexpected files in asset folders in the same pull request review as source, and keep VS Code Workspace Trust on, so tasks in a newly cloned folder do not run until the folder is trusted.
  • Rotate every secret a compromised repository could reach, then check again. Two owners who cleaned up the first stage were hit by the second six days later (OpenSourceMalware), so cleanup is not a single event.

FAQ

What is GhostAction?

GhostAction is a GitHub supply chain campaign first reported by GitGuardian in September 2025, when it had compromised 327 users across 817 repositories and stolen at least 3,325 secrets. It pushes malicious GitHub Actions workflows that send CI secrets to the attacker. Its October 2026 wave targeted more than 30,000 repositories through about 1,900 compromised accounts.

How does GitHub device code phishing work in this campaign?

A forged GitHub sign-in alert leads to a reverse proxy of GitHub's login. Once the victim signs in, a script on the page is built to request a device code for the attacker's OAuth app and approve it inside the victim's session, so no code is ever shown or typed. The resulting token would carry repository, workflow and organization read access.

Did multi-factor authentication stop it?

In the one documented case, yes, but only partly. The proxy captured the password and one-time code and the attacker signed in; an additional MFA challenge then stopped the session from going further. Codes that can be typed can be relayed, so passkeys and security keys are the stronger control.

What should a maintainer do after signing in through my-github.com?

Change the GitHub password from a clean device, revoke unfamiliar OAuth apps and tokens, check the account's security log for new grants, and rotate every secret the account's repositories can reach. Then check owned repositories for an unexpected .vscode/tasks.json, a public/fonts/fa-solid-400.woff2 file or new workflow files.

References

  • OpenSourceMalware (11 Oct 2026). GhostAction Phishing Campaign. opensourcemalware.com
  • OpenSourceMalware (9 Oct 2026). GhostAction Attack Escalates By Targeting GitHub Users. opensourcemalware.com
  • OpenSourceMalware (16 Oct 2026). GhostAction Copycats PolinRider by Hiding a Stealer in a Fake Font File. opensourcemalware.com
  • GitGuardian (7 Oct 2026, updated 13 Oct 2026). GhostAction Returns: 772 Repos Hit, 30k More in Oct. blog.gitguardian.com
  • GitGuardian (5 Sep 2025). The GhostAction Campaign: 3,325 Secrets Stolen Through Compromised GitHub Workflows. blog.gitguardian.com
  • GitHub Docs. Authorizing OAuth apps (device flow); Scopes for OAuth apps. docs.github.com