A threat actor called GlassWorm has compromised over 430 code repositories across GitHub, npm, VS Code, and OpenVSX by hiding malicious payloads inside Unicode characters that are completely invisible in every editor, diff tool, and code review interface currently in use.
In early March 2026, researchers at Aikido Security, Socket, and StepSecurity independently uncovered what has become one of the more technically sophisticated supply chain attacks on the open-source ecosystem. The threat actor, tracked as GlassWorm, did not exploit a zero-day vulnerability in a major platform. Instead, it exploited something far older and far more overlooked: Unicode characters designed decades ago that are invisible to human eyes but perfectly readable by a JavaScript interpreter. The campaign is still active as of this writing, with new repositories being compromised as researchers continue to map the full scope of the operation.
The Technique: Invisible Code in Plain Sight
The foundation of the GlassWorm attack rests on a category of Unicode characters called Private Use Area (PUA) code points. Specifically, the attacker exploits two ranges: U+FE00 through U+FE0F and U+E0100 through U+E01EF. These characters are technically known as Unicode variation selectors, originally intended to specify alternate glyph representations for emoji and other symbols. In practice, they render as zero-width whitespace in virtually every code editor, terminal, GitHub's pull request diff interface, and static analysis tool in widespread use today.
The attacker uses these characters to encode an entire malicious payload. A small JavaScript decoder is placed in the repository to extract the hidden bytes at runtime. When a developer reviews the code, they see what appears to be an empty string inside backticks. When the JavaScript engine executes that same string, it becomes a full executable payload.
The decoder pattern identified by Aikido Security works like this:
const s = v => [...v].map(w => (
w = w.codePointAt(0),
w >= 0xFE00 && w <= 0xFE0F ? w - 0xFE00 :
w >= 0xE0100 && w <= 0xE01EF ? w - 0xE0100 + 16 : null
)).filter(n => n !== null);
eval(Buffer.from(s(``)).toString('utf-8'));
The backtick string passed to s() looks completely empty in every viewer. It is packed with invisible variation selector characters that, once decoded, produce a complete malicious payload. That payload then reaches out to a command-and-control server to download a second-stage script capable of stealing credentials, tokens, and cryptocurrency wallet data.
What makes this technique particularly damaging is that the attack bypasses the defenses developers routinely rely on. Visual code review cannot detect characters that do not render. Standard linters do not flag them by default. GitHub's own pull request interface shows nothing. The malicious commit looks entirely indistinguishable from a legitimate one.
"The backtick string passed to s() appears completely empty in every viewer, but it is packed with invisible characters that, once decoded, produce a full malicious payload." — Aikido Security Research Team
Aikido Security also noted that the malicious commits are constructed to blend in convincingly with each targeted project's style. The surrounding changes include documentation tweaks, version bumps, minor refactors, and bug fixes that are stylistically consistent with each codebase. The scale of the operation — more than 150 individually tailored commits across diverse projects within a single week — strongly suggests the attacker is using large language models to generate plausible cover commits automatically.
The GlassWorm campaign checks the victim system's locale before executing. If a Russian locale or time zone is detected, the payload skips execution entirely. This operational security measure is a common indicator of Eastern European cybercrime groups operating under an informal non-targeting agreement with Russian systems.
A Campaign That Has Been Evolving Since 2025
GlassWorm did not appear suddenly in March 2026. The campaign has been running and escalating for over a year, expanding its target surface with each wave. Understanding the timeline is important to understanding the threat's current scale.
Aikido Security first documented the invisible Unicode technique being used in malicious npm packages as early as March 2025. By October 2025, the same threat actor had expanded into the OpenVSX marketplace, the extension registry used by VS Code alternatives and open-source builds of the editor. Koi Security identified and analyzed that wave, which was estimated to have been downloaded approximately 35,000 times before it was contained within three days. A second wave followed in November 2025, this time infecting three VS Code extensions with a combined download count near 10,000. Because VS Code extensions update automatically, every user who had the extension installed at the time likely received the malicious version without any action on their part.
In late January 2026, attackers compromised a developer's account and published malicious versions of four additional extensions with a combined download count exceeding 22,000. Then, between March 3 and March 9, 2026, the campaign shifted into a substantially larger operation. Aikido Security identified at least 151 GitHub repositories compromised using the invisible Unicode technique during that window. Concurrently, Socket flagged 72 malicious OpenVSX extensions linked to the same campaign, and researchers collectively identified over 433 compromised components across all platforms when combining findings from Aikido, Socket, StepSecurity, and the OpenSourceMalware community.
"The malicious injections don't arrive in obviously suspicious commits. The surrounding changes are realistic: documentation tweaks, version bumps, small refactors, and bug fixes that are stylistically consistent with each target project." — Ilyas Makari, Security Researcher, Aikido Security
Socket's research revealed an additional layer of sophistication in the VS Code extension component of the campaign. The attacker exploited the extensionPack and extensionDependencies fields in VS Code extension manifests to deliver malicious payloads through a transitive dependency model. When an editor installs an extension that declares other extensions as dependencies or pack members, it installs all of them — regardless of whether those dependent extensions are benign or malicious. This allowed GlassWorm to compromise users who installed what appeared to be a fully legitimate extension, only for that extension to silently pull in malicious companions.
ForceMemo: Turning Stolen Tokens Into a Second Wave
While the invisible Unicode repositories were being documented, a parallel and related operation emerged. StepSecurity's threat intelligence team identified a second campaign, which they named ForceMemo, active from at least March 8, 2026. ForceMemo represents what happens downstream from a successful GlassWorm infection: the attacker uses credentials stolen through the original malware to carry out account takeovers at scale across GitHub.
GlassWorm's payload, when it executes on a developer's machine, searches aggressively for GitHub tokens. It checks git credential helpers, editor storage locations, the ~/.git-credentials file, and the GITHUB_TOKEN environment variable. Once a valid token is found, it is exfiltrated to attacker-controlled infrastructure. The ForceMemo campaign then uses those stolen tokens to access every repository associated with the compromised GitHub account.
Rather than creating new commits that might appear suspicious in a repository's history, the attacker uses a technique called force-pushing with history rewriting. The attack appends obfuscated malicious code to Python files — specifically files named setup.py, main.py, or app.py — and then rebases the latest legitimate commit with the poisoned version and force-pushes it to the default branch. Critically, this preserves the original commit's message, author, and author date. Only the committer date is modified. In GitHub's UI, there is no pull request, no new commit, and no visible trace of the intrusion unless a developer manually compares file contents against a known-good state.
"This technique rewrites git history, preserves the original commit message and author, and leaves no pull request or commit trail in GitHub's UI." — StepSecurity Threat Intelligence Team
The targets in the ForceMemo wave are broad: Django applications, machine learning research repositories, Streamlit dashboards, Flask APIs, and PyPI packages. StepSecurity confirmed that accounts like BierOne, wecode-bootcamp-korea, and HydroRoll-Team each had six repositories backdoored identically, confirming the use of automated tooling rather than manual targeting. In one documented case reported by a Reddit user, a "null" user appeared committing across the victim's repositories. Tracing the access back, the victim discovered it originated from a rogue Cursor extension that had deployed the GlassWorm malware months earlier.
Two npm packages — react-native-international-phone-number and react-native-country-select, maintained by npm user "astroonauta" — were also briefly compromised as part of this extended campaign. Malicious versions published on March 16, 2026 contained a preinstall hook invoking obfuscated JavaScript with the same locale-checking and Solana-querying behavior seen throughout the GlassWorm operation.
The Blockchain C2: Why This Is Hard to Take Down
A defining characteristic of GlassWorm across every wave is its use of the Solana blockchain as a command-and-control channel. The attacker owns the private key for a Solana wallet address and uses Solana's Memo program to post JSON instructions. Infected machines query this address via Solana's RPC infrastructure, read the latest memo field, decode the base64 link, and connect to the resulting payload server URL.
StepSecurity queried the primary C2 address used in ForceMemo — BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC — and found 50 transactions on-chain, with the earliest dating to November 27, 2025. That is over three months before the first ForceMemo GitHub injections on March 8, 2026, indicating the attacker was operating against other infection vectors well before pivoting to the current repository compromise strategy. The payload URL was updated multiple times per day throughout the campaign.
A second Solana wallet, 6YGcuyFRJKZtcaYCCFba9fScNUvPkGXodXE1mJiSzqDJ, was used in the compromised npm packages detected on March 16. Both addresses are attributed to the GlassWorm actor based on shared infrastructure patterns and functionally identical payloads. The blockchain-based C2 infrastructure creates a significant remediation problem: blockchain transactions are immutable. There is no mechanism to delete or modify the instructions already posted on-chain. Takedown requests that work for traditional C2 servers — contacting hosting providers, suspending domains — have no effect on a Solana wallet.
In previous confirmed GlassWorm incidents, the fully decrypted payload deployed hidden VNC servers and SOCKS proxies on infected systems, giving the attacker persistent remote access. The final JavaScript payload is AES-encrypted with a key delivered via HTTP headers, making static analysis and signature-based detection ineffective. The malware executes entirely in memory on macOS and Linux via eval(), and uses a Node.js vm.Script sandbox on other platforms, avoiding disk writes that might trigger endpoint detection tools.
Neither GitHub, npm, nor Microsoft had publicly commented on the GlassWorm campaign as of March 18, 2026. If you have installed VS Code extensions, npm packages, or cloned Python repositories in the past 30 days, treat your developer credentials as potentially compromised until verified otherwise.
Who Is at Risk and What to Do Now
The risk profile of this campaign is unusual because it does not require a victim to do anything obviously wrong. A developer might clone a high-starred GitHub repository for a legitimate project, run a setup script, and unknowingly execute GlassWorm's payload. Another developer might install a trusted-looking VS Code or Cursor extension that silently adds malicious companion extensions through the dependency mechanism. A third might simply have been running an extension that was benign when installed but was later updated by a compromised account to carry the GlassWorm payload — with no notification and no user action required, because extensions auto-update.
The geographic risk is concentrated in countries with large developer populations and high GitHub usage: the United States, India, Germany, Japan, and the United Kingdom face the highest exposure based on the distribution of the affected repositories. Any developer who installed affected packages or extensions should treat the following as immediate priorities:
- Revoke all current GitHub Personal Access Tokens and SSH keys. Generate fresh credentials only from a known-clean machine.
- Audit all repositories associated with your GitHub account for unauthorized force-push events. Look specifically for commits where the committer date does not match the author date, or where your file contents differ from what you last committed.
- Search repository files for the malware marker variable
lzcdrtfxyqiplpd, which StepSecurity confirmed appears across compromised Python files as a reliable detection indicator. - Rotate any secrets, API keys, or environment variables that may have been accessible in your development environment.
- Monitor outbound network connections from your workstation for requests to Solana RPC endpoints, which are not expected traffic for the vast majority of development workflows.
- Enable hardware-backed multi-factor authentication on all developer accounts. FIDO2 keys prevent token theft from being sufficient for account takeover even when credentials are exfiltrated.
- Use short-lived, fine-grained Personal Access Tokens with the minimum repository scope required for each task.
For teams managing CI/CD pipelines, StepSecurity recommends monitoring for git push --force events originating outside of authorized pipeline identities. Aikido Security has built detection for invisible Unicode injection into their malware scanning pipeline and released Aikido Safe Chain, a free open-source tool that wraps npm, yarn, and pnpm to detect and block malicious packages during install. The OpenSSF Package Analysis Project is a broader industry initiative scanning open-source packages for malicious behavior that represents the kind of infrastructure needed at ecosystem scale to address campaigns of this sophistication.
Key Takeaways
- Visual code review is not a defense against this class of attack. Invisible Unicode characters render as whitespace in every tool currently in widespread use. Automated scanning that specifically detects zero-width Unicode in source files is required.
- GlassWorm is a multi-platform, multi-wave campaign with over a year of operational history. More than 430 components across GitHub, npm, VS Code, OpenVSX, and Python repositories were compromised in the most recent wave alone. The scope continues to expand as of this writing.
- Blockchain-based C2 infrastructure makes traditional takedown approaches ineffective. The Solana wallet addresses used for command-and-control cannot be suspended, modified, or deleted. Defenders must focus on detection and credential hygiene rather than infrastructure disruption.
- The ForceMemo campaign demonstrates credential theft compounding into supply chain compromise. A single developer infected by a malicious VS Code extension can result in every repository on their GitHub account being backdoored, with no visible trace in the platform's UI.
- AI-assisted attack generation is likely scaling the operation. The volume and quality of project-specific cover commits across 150-plus codebases in a single week exceeds what manual crafting can explain. Defenders must assume attackers are using LLMs to generate convincing malicious contributions at scale.
The GlassWorm campaign is a clear demonstration that the open-source software supply chain remains one of the highest-leverage attack surfaces available to a sophisticated threat actor. The combination of a technique that is invisible to human review, a command-and-control channel that cannot be dismantled, and AI-assisted scale means that the defenses developers relied on even two years ago are no longer sufficient. Invisible threats require active, automated defenses. Assume that what you cannot see can still execute.