GhostAction attackers have expanded their GitHub credential theft campaign with a second stage that disguises malicious JavaScript as a font file and targets developer workstations through Visual Studio Code tasks.
Jenn Gile identified 94 compromised repositories belonging to 66 owners, confirming the payload in all 79 repositories available for analysis. The remaining 15 were inaccessible.
OpenSourceMalware investigated after Jamf Threat Labs researcher Thijs Xhaflaire discovered the cluster while hunting PolinRider infections. The activity extends an operation previously centered on malicious GitHub Actions workflows that steal repository secrets and credentials exposed in Git history.
GhostAction Hackers Hide Credential-Stealing Malware
The attack places a launcher in .vscode/tasks.json and stores its payload at public/fonts/fa-solid-400.woff2. Although it resembles a Font Awesome resource, the file contains 38 lines of unobfuscated Node.js code. A task labeled eslint-check invokes Node.js against the disguised script.
The task uses runOn: folderOpen to request execution when developers open the project, while presentation settings suppress terminal visibility.
Execution requires a trusted workspace and permission for automatic tasks. Simply cloning or opening an affected repository does not prove the malware executed.
Once running, the stealer collects usernames, hostnames, selected environment variables, and credential files associated with AWS, npm, PyPI, Git, Kubernetes, Claude, and Gemini.
It reads RSA and Ed25519 SSH private keys completely, while limiting reads from eight other credential files to their first 3,000 characters.
A recursive search scans the home directory for credential patterns, including AWS, Anthropic, GitHub, npm, and PyPI tokens. The collected information leaves via an HTTP POST on port 8080. Jenn Gile linked the infrastructure to 193[.]32[.]204[.]199.
On systems supporting cron, the payload installs a scheduled command that runs every five minutes. It retrieves a script through a hostname-specific server path and pipes the response into Bash, enabling follow-on commands tailored to individual machines.
The entry carries the marker #ghc2, and installation removes existing matching entries before adding another. Deleting the malicious repository files therefore leaves this foothold intact.
Jenn Gile had not retrieved the subsequent server-delivered payload, leaving its functionality unresolved. Windows lacks the targeted crontab mechanism, although credential collection can still execute.
Most second-stage additions arrived October 15. Two owners who removed earlier malicious workflows were reinfected, showing that file cleanup did not eliminate attacker access.
Despite similarities to PolinRider’s fake-font launcher, Jenn Gile found no shared indicators establishing common operators.
Responders should revoke compromised GitHub access before cleanup, inspect every writable repository, remove malicious tasks and workflows, and investigate endpoint persistence.
Credentials exposed through files, environment variables, or Git history require rotation from a clean device after containment.
IOCs
| Category | File / Indicator | SHA-256 / Role |
|---|---|---|
| File | public/fonts/fa-solid-400.woff2 (batch tag reinject) | cb3842832267421b9563c7bd32d3582a8fff624860e57c2c9058966735d4da60 |
| File | public/fonts/fa-solid-400.woff2 (batch tag auto_20261015) | 61eca87b4b4c3e6248dc0fde25ff9cf28637798a8c4be172eaef9843252d12f6 |
| File | public/fonts/fa-solid-400.woff2 (batch tag auto_20261014) | 92dec8f50d934c338ff3c1bcbf1c9b028aa9561128d0077a101a1ef4dac0f0db |
| File | .vscode/tasks.json | a043f03e89ef55779f4f630138cf5efe1dd37632e176c7a0d9bbfa989ba84eeb |
| File | .github/workflows/security-audit.yml (first version) | 6d258db70677c99c08c9db37e002751eb0f0fb7c0cab2a4effd7c8fa8d115d19 |
| File | .github/workflows/security-audit.yml (second version) | d301438d713006a7a63889969fb5a30389c88bba5fbd89ef22becac611823a4f |
| File | .github/workflows/lint.yml (reference second-stage workflow) | 40a007874722c46e0d194c4453f6cee26ee9c64513597784cc9c0e8b85471e7c |
| Network | 193[.]32[.]204[.]199 | GhostAction server |
| Network | hxxp://193[.]32[.]204[.]199:8080/?c=reinject | Exfiltration from the infostealer and second workflow |
| Network | hxxp://193[.]32[.]204[.]199:8080/?c=auto_20261013 | Exfiltration with a date-stamped batch tag |
| Network | hxxp://193[.]32[.]204[.]199:8080/?c=auto_20261014 | Exfiltration with a date-stamped batch tag |
| Network | hxxp://193[.]32[.]204[.]199:8080/?c=auto_20261015 | Exfiltration with a date-stamped batch tag |
| Network | hxxp://193[.]32[.]204[.]199:8080/?c=security | Early Stage 1 variant observed in one repository |
| Network | hxxp://193[.]32[.]204[.]199/?c=new | First Stage 1 version |
| Network | hxxp://193[.]32[.]204[.]199:8080/c2/ | Script fetched by the cron job |
Note: IP addresses and domains are intentionally defanged (e.g., [.]) to prevent accidental resolution or hyperlinking. Re-fang only within controlled threat intelligence platforms such as MISP, VirusTotal, or your SIEM.
Join 16,000+ SOC teams using ANY.RUN to streamline threat investigations and reduce manual effort. Explore for your team

