The GhostAction Shift: How Stolen OAuth Tokens and Weaponized Font Files Compromised 94 GitHub Repositories
A technical breakdown of the GhostAction supply chain campaign, exploring automated OAuth device code theft, VS Code workspace weaponization, and local machine compromise.
Published: 2026.10.20
From Cloud CI Hijacking to Local Endpoints: The Anatomy of GhostAction
Software supply chain attacks have moved past basic typo-squatting and package poisoning. Attackers now systematically abuse the trust boundaries between cloud developer platforms, Continuous Integration (CI) workflows, and local developer workstations. The threat campaign known as GhostAction illustrates this shift. When GitHub deployed server-side blocks to prevent malicious workflow files from running on its hosted runners, the threat actor did not abandon the campaign. Instead, they adapted within six days, pivoting from cloud runner abuse to targeting developer machines directly.
The attackers compromised 94 repositories across 66 maintainer accounts by pairing reverse-proxy credential phishing with local developer environment execution. The campaign began by targeting open-source project maintainers with a spoofed security alert from a lookalike domain, my-github[.]com. Rather than stopping at username and password harvesting, the phishing infrastructure acted as a real-time reverse proxy. It bypassed standard two-factor authentication (2FA) and automatically authorized an OAuth device code flow without requiring the victim to approve or enter a verification code manually.
With broad OAuth permissions granted—specifically repo, workflow, and read:org—the attacker automated commits across repositories under the compromised account. The initial phase focused on injecting malicious GitHub Actions workflows designed to harvest repository secrets and push them to an external endpoint at 193.32.204[.]199.
When platform defenses halted the execution of these cloud CI runners on October 9, the attacker deployed an evasive second stage. They committed workspace automation files that trigger when a developer opens the project in an editor like Visual Studio Code. Disguised inside a fake font file, a credential stealer executed on the developer’s workstation, establishing a persistence mechanism via a five-minute cron job.
How platform-level CI blocks forced the attacker into developer workstations
Reverse-Proxy Phishing
Victim visits fake alert; proxy harvests 2FA and silently approves OAuth device flow
OAuth Token Exfiltration
Broad repo, workflow, and read:org permissions captured over port 8443
Stage 1: Cloud CI Injection
Automated commits insert secret-harvesting workflows under .github/workflows/
Platform Countermeasures
GitHub blocks execution of malicious runner jobs on October 9
Stage 2: Local Workspace Poisoning
Weaponized VS Code tasks execute a fake font stealer and install local cron jobs
This campaign demonstrates how developer trust in workflow automation can backfire. A compromised repository is no longer just a hosting venue for compromised code; it is now an active delivery system targeting developer laptops and local credentials.
94 Repositories, Two Stages: Attack Vectors and Technical Fact Matrix
The GhostAction campaign relies on distinct operational stages that separate credential acquisition from payload delivery. Stage 1 depended entirely on GitHub’s hosted compute, while Stage 2 shifted execution entirely to client machines. Understanding the technical divergence between these two approaches reveals how threat actors bypass centralized cloud guardrails.
The attack infrastructure centered on a single server (193.32.204[.]199), which handled phishing, credential harvesting, command-and-control communication, and bulk scanning. While using a single IP address across all phases represents an operational security failure by the attacker, the tactical execution of the reverse-proxy OAuth bypass was technically sophisticated.
| Metric / Dimension | Stage 1: Cloud CI Workflow Injection | Stage 2: Local Developer Workspace Abuse |
|---|---|---|
| Execution Environment | GitHub Actions hosted runners (Ubuntu) | Local developer workstations (macOS/Linux/Windows) |
| Trigger Mechanism | Repository events (push, pull_request, workflow_dispatch) | Workspace open in Visual Studio Code (tasks.json / workspace run) |
| Access Requirement | Stolen OAuth token with workflow scope | User cloning the repository and opening the directory locally |
| Payload Disguise | Legitimate-looking CI automation scripts | Executable binary disguised inside a fake font file asset |
| Persistence Method | Continuous CI runs on branch updates | Local user cron job executing every 5 minutes |
| Exfiltration Channel | HTTPS POST to external endpoint / fallback to secret Gist | Plain HTTP POST to 193.32.204[.]199:8080 |
| Target Data | CI/CD secrets, deployment tokens, environment variables | Local browser data, system environment keys, local SSH/cloud credentials |
| Platform Evasion | Defeated by centralized platform runner blocks | Immune to platform CI blocks; executes entirely off-platform |
The technical gap between the two stages centers on where code execution occurs. Stage 1 relied on GitHub computing resources to read repository secrets. When GitHub blocked the workflow names and script signatures, subsequent execution waves on October 10 and October 12 yielded zero secrets for the operator.
Stage 2 circumvented this by committing three files into the repository root: a workspace configuration file, an automation trigger, and an executable file formatted to appear as a standard typography font. When a developer pulls the repository and opens the folder, the IDE reads the task definitions. Without proper workspace trust protections, the editor triggers the binary.
The binary collects local system metadata and extracts environment variables, then drops a background task into the user’s crontab that reaches out to the attacker’s HTTP server on port 8080 every 300 seconds.
Supply Chain Exposure: Direct Operational Fallout for Engineering Teams
GhostAction shows that an attacker does not need high-level development skills to cause disruption. Even an inexperienced operator using basic tools can compromise sensitive assets by targeting weak points in developer workflows. The attack highlights three main areas of operational risk for engineering teams.
GhostAction Exploitation and Remediation Dynamics
Breaking down the mechanics of the compromise and enterprise containment
Reverse-Proxy Device Phishing
Maintainer approves proxied login; automated scripts authorize broad OAuth scopes
Dormant Repository Blindspots
Old, unmonitored repos sit with active tokens, providing silent footholds
Endpoint and Credential Triage
Invalidate tokens, purge cron jobs, and enforce IDE workspace trust boundaries
1. Silent OAuth Granting and Unmonitored Scope Expansion
The most critical technical element of the GhostAction intrusion is the automated authorization of the GitHub OAuth device code flow. Traditional phishing captures a username, password, and sometimes a one-time session cookie. However, modern Identity and Access Management (IAM) configurations often trigger step-up verification or session revocation when an anomalous IP appears.
In this campaign, the attacker’s reverse proxy acted as a man-in-the-middle for the actual GitHub login session. Once the user supplied their 2FA code, the proxy injected JavaScript directly into the authenticated session. The script made an internal request to /login/device, pulled the authorization form tokens, added authorize=1 to the request payload, and approved the client without requiring the victim to read or verify the device string.
Standard Flow: User -> Sees Code -> Enters Code in Browser -> Confirms Scopes -> Grants Token
GhostAction: User -> Phished -> Script Grabs Form -> Sets authorize=1 -> Silent Token Issuance
This gave the attacker a persistent OAuth bearer token with repo, workflow, and read:org scopes. With these privileges, an attacker can bypass branch protection rules that lack administrator enforcement, push commits directly to codebases, and access organizational metadata. In an enterprise environment, an OAuth token with read:org and repo access allows an external actor to map internal team hierarchies, discover private repository naming conventions, and systematically scan codebases for exposed infrastructure keys.
2. Remediation Costs Across Abandoned and Dormant Assets
Of the 94 repositories compromised in this campaign, 65 had not received a legitimate commit in over a year, and one had remained untouched for nine years. This highlights a clear operational vulnerability: unmaintained, abandoned software assets often serve as initial access vectors for supply chain attacks.
When an active project maintainer’s personal credentials are stolen, attackers do not just target high-profile flagship repositories, which are usually monitored by automated CI/CD security tools. Instead, they often deploy malicious code into older, forgotten projects owned by the same user. Downstream consumers may still run these older libraries as legacy dependencies.
For engineering organizations, responding to compromises across dormant codebases creates significant operational overhead:
- Audit Latency: Security teams spend valuable time confirming whether an old repository contains production secrets, proprietary algorithms, or active webhooks.
- Credential Rotation Churn: Based on industry incident response standards, rotating an active engineering credential exposed across multiple CI/CD pipelines requires an estimated 4–6 engineering hours per secret. This includes finding dependencies, updating key vaults, deploying changes to production, and verifying application health.
- Downstream Dependency Tracing: If an organization imported a compromised open-source repository as a sub-module or vendor package, developers must audit their local workstations to determine whether any engineer cloned the malicious workspace.
3. Compromise of Developer Workstations Beyond Cloud perimeters
By moving to Stage 2, the threat actor shifted the attack surface from cloud servers to developer workstations. A compromised cloud runner typically runs in an ephemeral container that is destroyed once the job completes. Even if an attacker steals short-lived environment secrets from that runner, they usually cannot gain an ongoing foothold inside the cloud provider’s core infrastructure.
A developer’s local machine, however, is a high-value, persistent target. Developers frequently store sensitive, unencrypted credentials on their workstations, including:
- Long-lived personal AWS, Google Cloud, or Azure access keys stored in
~/.aws/credentialsor shell rc files. - Unencrypted SSH private keys used for accessing production bastion hosts, internal staging servers, and remote git repositories.
- Active authentication cookies from corporate identity providers, VPN clients, and internal web consoles stored inside local browser directories.
By leveraging an automated IDE task and establishing a cron job that runs every five minutes, the GhostAction attacker secured a foothold capable of capturing future secrets. If a developer uses their workstation to generate new API tokens or deploy infrastructure via command-line tools, the background script—communicating over HTTP on port 8080—can capture those rotated credentials, blunting standard key-rotation efforts.
Technical Buffers: Workspace Isolation, CI Guardrails, and Detection Benchmarks
Mitigating multi-stage supply chain attacks requires layered defenses. Organizations cannot rely solely on the built-in security controls of third-party platforms. They must apply security controls across the entire development lifecycle, from cloud repositories down to the developer’s local environment.
Security Posture: Legacy Trust vs. Modern Zero Trust
Contrasting default development environments with hardened supply chain controls
Default Permissive Setup
Vulnerable to GhostAction- • IDE automatically executes workspace tasks on folder open
- • Personal OAuth tokens grant broad organization-wide scopes
- • Dormant repositories remain linked to active accounts
- • Developer workstations lack outbound execution monitoring
Hardened Pipeline Standard
GhostAction Mitigated- • Workspace Trust strictly isolates untrusted folders and tasks
- • Fine-grained, resource-specific tokens expire automatically
- • Automated archiving policies revoke dormant repository access
- • Centralized secrets auditing monitors pipeline variables
IDE Workspace Trust and Execution Guardrails
Modern development tools have introduced controls to mitigate workspace poisoning. Visual Studio Code includes a “Workspace Trust” feature, designed specifically to address risks like the tasks-based execution used in GhostAction. When Workspace Trust is enabled, opening a folder in Restricted Mode blocks automatic task execution, disables debugging extensions, and prevents workspace-defined scripts from running until the user explicitly marks the directory as trusted.
Organizations should standardize these IDE configurations across developer workstations using device management profiles (such as MDM or Group Policy). If an engineer clones a dormant or third-party open-source repository to inspect its contents, the editor must open that workspace in Restricted Mode by default.
Hardening CI/CD Secrets and Token Privileges
Stage 1 of the GhostAction attack relied on malicious workflows reading repository secrets. Preventing this requires two architectural controls:
- Least-Privilege Token Permissions: The default
GITHUB_TOKENpermissions across an organization’s repositories should always be set to read-only. Workflows requiring write access to checks, contents, or pull requests must explicitly define those permissions within the workflow YAML file. - Third-Party Application Restrictions: Organization administrators should block third-party OAuth applications from accessing organization resources by default. Setting up an explicit OAuth application approval policy ensures that even if an individual maintainer is tricked into granting an application access to their personal account, that application cannot access organization-owned codebases without security team review.
To detect anomalous outbound connections or unauthorized pipeline modifications, engineering teams frequently use infrastructure observability and pipeline security platforms such as Datadog. By streaming CI/CD audit logs to a centralized monitoring system, security teams can trigger automated alerts whenever a workflow file is committed directly to an unmonitored branch or an unfamiliar outbound IP address is contacted during a job run.
Defensive Action Plan: Three Lines of Defense Against Supply Chain Pivots
Protecting an engineering organization against supply chain attacks that bridge cloud infrastructure and local environments requires a systematic response framework. The following defense lines provide a structured approach to identifying exposures, mitigating active compromises, and reducing attack surfaces.
Enterprise Defense Framework: Incident Response Sequence
Step-by-step mitigation workflow for supply chain credential compromises
1. Token Invalidation
Revoke active personal and OAuth tokens; terminate existing browser web sessions
2. Endpoint Remediation
Inspect local crontabs, remove unknown workspace tasks, scan for dropped binaries
3. Lifecycle Governance
Archive dormant repos, restrict OAuth device flows, enforce fine-grained tokens
First Line of Defense: Immediate Credential Invalidation and Token Revocation
When supply chain activity indicates compromised developer accounts, incident responders should immediately revoke active credentials from a verified clean machine:
- Revoke All Authorized OAuth Apps: Navigate to account settings and inspect every application authorized to interact with personal or organization repositories. Revoke any unrecognized integrations, particularly those granted
repoorworkflowscopes. - Terminate Active Web Sessions: Force-revoke all active browser sessions across GitHub and associated code-hosting services to clear any session tokens held by reverse-proxy infrastructure.
- Rotate Personal Access Tokens (PATs) and SSH Keys: Invalidate all classic Personal Access Tokens. Migrate pipelines and tools to Fine-Grained Personal Access Tokens, which restrict access to specific repositories, set short expiration windows, and require explicit capability declarations.
- Reset Core Identity Credentials: Change passwords across code-hosting accounts and identity providers. Verify that multi-factor authentication methods rely on hardware security keys (FIDO2/WebAuthn) rather than push notifications or SMS, mitigating modern reverse-proxy phishing attacks.
Second Line of Defense: Hardening Developer Environments Against Workspace Auto-Execution
Because GhostAction deploys persistence payloads directly to developer workstations, teams must treat local environments as potentially compromised if a poisoned repository was opened:
- Audit Scheduled Tasks and Cron Jobs: Inspect local persistence mechanisms. On macOS and Linux systems, review user crontabs (
crontab -l) and system launch daemons (/Library/LaunchDaemons,~/.config/systemd/user/) for unauthorized recurring scripts or suspicious network calls pointing to unknown IPs or unusual ports (such as 8080 or 8443). - Inspect Editor Workspace Configurations: Before opening cloned codebases, check for hidden configuration files inside
.vscode/tasks.jsonor.idea/. Review whether any configured command runs automatically on project initialization. - Enforce Strict IDE Workspace Boundaries: Require all developers to operate their IDEs with Workspace Trust enabled. Configure corporate development machines to block automated script execution in untrusted directories.
Third Line of Defense: Dormant Repository Lifecycle Management and Supply Chain Auditing
To close the attack surface exposed by unmonitored codebases, organizations should establish formal lifecycle management policies for all hosted repositories:
- Implement Automated Repository Archiving: Identify repositories that have had no commit activity, pull requests, or active maintenance for more than six months. Archive them or mark them as read-only. Archiving a repository locks its settings, disables GitHub Actions workflows, and prevents attackers from using it as an unmonitored staging ground for malicious code.
- Disable Unused Actions Capabilities: If an open-source project or legacy repository does not require CI/CD automation, disable GitHub Actions completely within the repository settings. Removing unused execution runners eliminates the cloud compute attack surface entirely.
- Enforce Organizational Device-Code Policies: Within your identity provider and code-hosting platforms, restrict or disable the OAuth device authorization flow if developers do not strictly require it for headless CLI environments. Where it is necessary, require secondary approval policies before device grants can access organization-scoped data.