# GlassWorm Developer Supply Chain Campaign Takedown — CrowdStrike + Google + Shadowserver Disrupt 4-Channel C2 (Solana / BitTorrent DHT / Google Calendar / VPS)

> On 2026-05-27 CrowdStrike, Google, and the Shadowserver Foundation announced the simultaneous neutralization of all four C2 channels used by GlassWorm, the first self-propagating worm targeting the VS Code / OpenVSX extension ecosystem. Active since at least October 2025, GlassWorm trojanized extensions across OpenVSX, the Microsoft VS Code Marketplace, Cursor, Windsurf, Positron, and VSCodium, plus npm and Python packages, and weaponized stolen developer credentials to poison 300+ GitHub repositories. Its payload, GlassWormRAT, is a WebSocket-based JavaScript RAT that pivots into the ZOMBI module — turning developer hosts into SOCKS / Hidden VNC / WebRTC proxy infrastructure — and deploys a Chrome extension for screenshot, keystroke, and clipboard capture.

- **Published:** 2026-05-27T00:00:00Z
- **Last reviewed:** 2026-05-27T00:00:00Z
- **Canonical:** https://intel.threadlinqs.com/threat/TL-2026-0603
- **Card image:** https://intel.threadlinqs.com/og/threat/threat-intel-glassworm-developer-worm-tl-2026-0603.webp?v=97485040 (Threadlinqs threat intel: GlassWorm Takedown of Four C2 Channels: Detection & IOCs (TL-2026-0603) — High severity, 49 IOCs, 9 detection rules.)
- **ID:** TL-2026-0603
- **Severity:** HIGH
- **Category:** SUPPLY_CHAIN
- **Status:** MONITORING
- **Actor:** GlassWorm (Russia)
- **Detections:** 9 (1 shown free below) · **IOCs:** 49 (3 shown free below)

## Description

GlassWorm is a self-propagating supply chain worm first publicly disclosed by Koi Security on 2025-10-18 after the actor compromised 7 OpenVSX extensions on 2025-10-17 (later expanded to 13 OpenVSX + 1 VS Code Marketplace extension `cline-ai-main.cline-ai-agent` v3.1.3 on 2025-10-19; ~35,800 cumulative installations) and resurfaced on 2025-11-06 with three more OpenVSX extensions (`ai-driven-dev.ai-driven-dev`, `adhamu.history-in-sublime-merge`, `yasuyuky.transient-emacs`; ~10,000 installations).

**Invisible-code stealth.** The worm hides its bootstrap in invisible Unicode variation selectors injected into otherwise benign-looking JavaScript inside the extension's `extension.js`. To a human reviewer or static scanner the malicious line renders as whitespace; the V8 / Node interpreter, however, executes it verbatim. This is the first observed weaponization of Unicode variation selectors as a packer for marketplace extensions.

**Four-channel resilient C2.** GlassWorm operators built a deliberately redundant C2 stack so that no single takedown could disable the botnet:

1. **Solana blockchain (primary discovery channel)** — Wallet `28PKnu7RzizxBzFPoLp69HLXp9bJL3JFtT2s5QzHsEA2` issues SPL transactions whose `memo` instruction field contains the current C2 URL. The malware queries a public Solana RPC endpoint, walks the wallet's transaction list, and decodes the most recent memo to obtain a fresh staging URL. Three known config-update transactions (`49CDiVWZpu…`, `3eVTqgEVdU…`, `3v3jCvKfdv…`) were observed between 2025-10-15 and 2025-11-06.
2. **Google Calendar dead drop** — Public calendar `https://calendar.app.google/M2ZCvM8ULL56PD1d6` owned by `uhjdclolkdn@gmail.com`. Event titles encode fallback C2 URLs. Removed during the takedown after coordination with Google's Threat Analysis Group.
3. **BitTorrent DHT** — The ZOMBI module joins the public Mainline DHT and uses peer announce / get_peers traffic against attacker-controlled info-hashes as a covert configuration channel. Disrupted by Shadowserver via DHT sinkholing.
4. **Commercial VPS** — Direct hardcoded fallback servers `217.69.3.218` and `199.247.10.166` (BL Networks / Vultr ranges) serving the second-stage archive at `/get_arhive_npm/` and `/get_zombi_payload/<base64>`. Exfiltration sinks on `140.82.52.31:80/wall` and `199.247.13.106:80/wall`.

**GlassWormRAT (Stage 2).** A WebSocket-based JavaScript RAT loaded from `http://217.69.3.218/get_arhive_npm/` after the bootstrap decodes the Solana memo. It establishes a wss:// session for live tasking and exposes commands for credential harvesting (NPM `~/.npmrc`, GitHub PATs from `gh` config and OS keyring, OpenVSX publisher tokens, Git credential helper, environment variables), crypto-wallet theft against 49 known browser extensions (MetaMask, Phantom, Coinbase Wallet, Trust Wallet, Solflare, Backpack, Keplr, Rabby, OKX, Brave Wallet, etc.), and lateral repo compromise — using the stolen GitHub credentials to push AI-generated, plausibly-worded malicious commits into 300+ repos starting 2025-10-31.

**ZOMBI module (Stage 3).** Final payload that converts the workstation into multi-protocol proxy infrastructure. ZOMBI fuses four sub-components: (a) a SOCKS5 server bound to a high port and tunneled out-bound to the C2; (b) Hidden VNC giving operators a full desktop session indistinguishable from the user's; (c) WebRTC peer routing for NAT traversal and P2P remote-execution; (d) BitTorrent DHT participation for resilient discovery. The resulting botnet was sold/used as a residential-proxy and malware-distribution backbone.

**Chrome extension implant.** GlassWormRAT side-loads an unpacked Chromium extension into developer profiles (Chrome, Brave, Edge, Arc) granting it `tabs`, `scripting`, `storage`, and `<all_urls>` host permissions. It exfiltrates full-page screenshots on tab change, keystrokes via injected content-scripts, and clipboard contents on every focus event — yielding 2FA codes, password-manager autofill, and recovery seeds.

**Persistence.** Run keys `HKCU\Software\Microsoft\Windows\CurrentVersion\Run` and `HKLM\Software\Microsoft\Windows\CurrentVersion\Run` re-launch the bootstrap; on macOS a LaunchAgent plist is dropped in `~/Library/LaunchAgents`. The Chrome extension itself acts as a soft persistence layer because it survives RAT removal.

**Attribution.** Multiple independent indicators point to a Russian-speaking actor: (a) Cyrillic comments in deobfuscated bootstrap, (b) malware self-terminates if `GetUserDefaultLangID()` / `Intl.DateTimeFormat().resolvedOptions().locale` falls inside the CIS bloc (RU, BY, KZ, UZ, AZ, AM, KG, TJ, MD, TM), (c) RedExt-family panel artefacts observed on the staging VPS, (d) victimology that excludes Russian-language repositories. Attribution confidence: MEDIUM (no formal nation-state nexus established; consistent with financially-motivated Russian-speaking crimeware crew with side ESPIONAGE tasking against a Middle Eastern government victim disclosed in November 2025).

**Takedown (2026-05-27).** CrowdStrike Counter Adversary Operations led the operation: Solana wallet activity was monitored and a poisoned config transaction was broadcast to redirect remaining beacons to sinkholes; Google TAG terminated `uhjdclolkdn@gmail.com` and the public calendar; Shadowserver sinkholed the BitTorrent DHT info-hashes and the two VPS subnets; OpenVSX and the VS Code Marketplace pulled all known malicious versions and rotated publisher tokens. Despite the disruption defenders should treat all developer credentials touched by an affected workstation as compromised — the worm's self-propagation guarantees dormant secondary infections in private repos and CI pipelines.

## MITRE ATT&CK

- T1195 Supply Chain Compromise
- T1195.001 Compromise Software Dependencies and Development Tools
- T1195.002 Compromise Software Supply Chain
- T1059.007 Command and Scripting Interpreter: JavaScript
- T1204.002 User Execution: Malicious File
- T1547.001 Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder
- T1543.001 Create or Modify System Process: Launch Agent
- T1176 Software Extensions
- T1027 Obfuscated Files or Information
- T1027.013 Obfuscated Files or Information: Encrypted/Encoded File
- T1497.001 Virtualization/Sandbox Evasion: System Checks
- T1614.001 System Location Discovery: System Language Discovery
- T1555.003 Credentials from Password Stores: Credentials from Web Browsers
- T1552.001 Unsecured Credentials: Credentials In Files
- T1528 Steal Application Access Token
- T1056.001 Input Capture: Keylogging
- T1518 Software Discovery
- T1217 Browser Information Discovery
- T1113 Screen Capture
- T1115 Clipboard Data
- T1071.001 Application Layer Protocol: Web Protocols
- T1102.001 Web Service: Dead Drop Resolver
- T1102.002 Web Service: Bidirectional Communication
- T1090 Proxy
- T1090.002 Proxy: External Proxy
- T1573.002 Encrypted Channel: Asymmetric Cryptography
- T1105 Ingress Tool Transfer
- T1041 Exfiltration Over C2 Channel
- T1567 Exfiltration Over Web Service
- T1550.001 Use Alternate Authentication Material: Application Access Token
- T1496 Resource Hijacking

## Free detection (Splunk SPL, Microsoft KQL, Sigma)

**GlassWorm C2 — Solana Dead-Drop / WebSocket Tasking / /wall Exfil to GlassWorm VPS** (`TL-2026-0603-SPL-003`)

Detects three GlassWorm C2 patterns in network telemetry: (1) HTTP POST to public Solana RPC endpoints carrying the known dead-drop wallet 28PKnu7RzizxBzFPoLp69HLXp9bJL3JFtT2s5QzHsEA2 or getSignaturesForAddress, (2) outbound connections to the four GlassWorm staging/exfil IPs (217.69.3.218, 199.247.10.166, 140.82.52.31, 199.247.13.106), or (3) WebSocket/HTTP requests to /get_arhive_npm/, /get_zombi_payload/, or /wall paths.

- **Languages:** Splunk SPL, Microsoft KQL, Sigma
- **ATT&CK:** T1071.001, T1102.001, T1102.002, T1090.002, T1041, T1567
- **Data sources:** zeek, proxy, firewall, mde_network, palo_alto
- **Severity:** critical
- **Confidence:** high

### Splunk SPL

```spl
index=proxy OR index=zeek OR index=firewall sourcetype IN ("zeek:http","bro:http:json","zeek:conn","stream:http","pan:traffic") earliest=-24h
| eval ioc_match=case(
    match(dest_ip, "^(217\.69\.3\.218|199\.247\.10\.166|140\.82\.52\.31|199\.247\.13\.106)$"), "glassworm_vps",
    match(uri_path, "(?i)(/get_arhive_npm/|/get_zombi_payload/|/wall$)"), "glassworm_endpoint",
    match(http_host, "(?i)(api\.mainnet-beta\.solana\.com|solana-api\.projectserum\.com|rpc\.ankr\.com/solana|solana-mainnet\.g\.alchemy\.com)") AND (match(http_request_body, "28PKnu7RzizxBzFPoLp69HLXp9bJL3JFtT2s5QzHsEA2") OR match(http_request_body, "getSignaturesForAddress")), "glassworm_solana_deaddrop",
    match(uri_full, "(?i)calendar\.app\.google/M2ZCvM8ULL56PD1d6"), "glassworm_gcal_deaddrop",
    1=1, null())
| where isnotnull(ioc_match)
| eval c2_channel=ioc_match
| stats count min(_time) as first_seen max(_time) as last_seen values(dest_ip) as dest_ips values(uri_path) as uris values(http_host) as hosts by src_ip, src_host, c2_channel
| eval threat="GlassWorm C2", severity="critical"
| table _time src_host src_ip c2_channel dest_ips hosts uris count first_seen last_seen threat severity
```

### Microsoft KQL

```kql
let glassworm_ips = dynamic(["217.69.3.218","199.247.10.166","140.82.52.31","199.247.13.106"]);
let glassworm_paths = dynamic(["/get_arhive_npm/","/get_zombi_payload/","/wall"]);
let solana_hosts = dynamic(["api.mainnet-beta.solana.com","solana-api.projectserum.com","rpc.ankr.com","solana-mainnet.g.alchemy.com"]);
DeviceNetworkEvents
| where Timestamp > ago(24h)
| where InitiatingProcessFileName in~ ("Code.exe","Cursor.exe","Windsurf.exe","Positron.exe","VSCodium.exe","node.exe","electron.exe","chrome.exe","msedge.exe","brave.exe","arc.exe")
| extend Channel = case(
    RemoteIP in (glassworm_ips), "glassworm_vps",
    RemoteUrl has_any (glassworm_paths), "glassworm_endpoint",
    RemoteUrl has_any (solana_hosts), "glassworm_solana_candidate",
    RemoteUrl has "calendar.app.google/M2ZCvM8ULL56PD1d6", "glassworm_gcal_deaddrop",
    "")
| where Channel != ""
| join kind=leftouter (
    DeviceEvents
    | where Timestamp > ago(24h)
    | where ActionType == "BrowserLaunchedToOpenUrl" or ActionType == "ConnectionInspected"
    | where AdditionalFields has "28PKnu7RzizxBzFPoLp69HLXp9bJL3JFtT2s5QzHsEA2" or AdditionalFields has "getSignaturesForAddress"
    | project DeviceId, SolanaWalletSeen = true
) on DeviceId
| extend Channel = iff(Channel == "glassworm_solana_candidate" and SolanaWalletSeen == true, "glassworm_solana_deaddrop", Channel)
| project Timestamp, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, RemoteIP, RemoteUrl, RemotePort, Protocol, Channel
| extend Threat = "GlassWorm C2", Severity = "critical"
```

### Sigma

```yaml
title: GlassWorm C2 Beacon — Solana Dead-Drop, WebSocket RAT, or /wall Exfil
id: 9f6c5a31-1aaa-4b0d-9d2c-9e9c0bf90603
status: experimental
description: Detects GlassWorm command-and-control traffic in three flavors — (1) HTTP POST to a public Solana RPC endpoint whose body references the known dead-drop wallet 28PKnu7RzizxBzFPoLp69HLXp9bJL3JFtT2s5QzHsEA2 or getSignaturesForAddress, (2) outbound TCP/HTTP to the four GlassWorm staging/exfil VPS IPs, or (3) requests to the GlassWorm /get_arhive_npm/, /get_zombi_payload/, or /wall URI paths. Originated by VS Code / Cursor / Windsurf / Node / Electron processes.
references:
    - https://thehackernews.com/2026/05/glassworm-malware-takedown-disrupts.html
    - https://www.koi.ai/incident/live-updates-glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-and-vscode-marketplaces
    - https://securityaffairs.com/184427/malware/glassworm-malware-has-resurfaced-on-the-open-vsx-registry.html
author: AII-Detector — ThreadLinqs Intelligence
date: 2026/05/27
tags:
    - attack.command_and_control
    - attack.t1071.001
    - attack.t1102.001
    - attack.t1102.002
    - attack.t1090.002
    - attack.exfiltration
    - attack.t1041
    - attack.t1567
logsource:
    category: proxy
detection:
    selection_ip:
        dst_ip:
            - '217.69.3.218'
            - '199.247.10.166'
            - '140.82.52.31'
            - '199.247.13.106'
    selection_path:
        cs-uri-stem|contains:
            - '/get_arhive_npm/'
            - '/get_zombi_payload/'
            - '/wall'
    selection_solana_host:
        cs-host|contains:
            - 'api.mainnet-beta.solana.com'
            - 'solana-api.projectserum.com'
            - 'rpc.ankr.com'
            - 'solana-mainnet.g.alchemy.com'
    selection_solana_body:
        cs-uri-query|contains:
            - '28PKnu7RzizxBzFPoLp69HLXp9bJL3JFtT2s5QzHsEA2'
            - 'getSignaturesForAddress'
    selection_gcal:
        cs-uri-stem|contains: '/M2ZCvM8ULL56PD1d6'
    condition: selection_ip or selection_path or (selection_solana_host and selection_solana_body) or selection_gcal
falsepositives:
    - Legitimate Solana developer tooling on developer endpoints (filter on wallet address — GlassWorm wallet is unique)
    - Security researchers reproducing IOCs in lab environments
level: critical
```

**Known false positives:**

- Legitimate Solana developer tooling — filter on wallet address (the wallet is unique to GlassWorm)
- Researchers reproducing IOCs in lab

**Tuning notes:** Critical-severity alert on first hit — these IOCs are unambiguous post-takedown. Enrich with TLS JA3/JA4 fingerprints for the WebSocket RAT once captured. Geofence the four VPS IPs to perimeter-block instead of detect-only once confirmed in your environment.

### 8 more detection rules (Splunk SPL, Microsoft KQL, Sigma), unlock with TL Creds

- GlassWorm Exploitation — VS Code / Cursor / Windsurf Spawning Shell or Downloader (locked: unlock with TL Creds)
- GlassWormRAT Post-Exploitation — Developer Credential File Access (.npmrc / gh hosts.yml / OpenVSX token / Git credentials) (locked: unlock with TL Creds)
- GlassWorm ZOMBI Module — SOCKS5 / Hidden VNC / WebRTC / BitTorrent DHT from Developer Endpoint (locked: unlock with TL Creds)
- GlassWorm Exploitation — Trojanized Marketplace Extension Install (Known IOC Package Names) (locked: unlock with TL Creds)
- GlassWormRAT macOS LaunchAgent Persistence + Chromium Unpacked Extension Sideload (locked: unlock with TL Creds)
- GlassWorm Lateral Movement — AI-Generated Malicious Commits via Stolen GitHub Token (locked: unlock with TL Creds)
- GlassWorm Exploitation — Invisible Unicode Variation Selectors in VS Code Extension JS (locked: unlock with TL Creds)
- GlassWorm Post-Exploitation — HKCU/HKLM Run Key Persistence by VS Code Descendant (locked: unlock with TL Creds)

Sign up free to unlock the detection rules: https://threadlinqs.com/?modal=signup

## Sample indicators (3 of 49)

Defanged, TLP:CLEAR.

- IP address: `217.69.3[.]218`
- Domain: `calendar[.]app[.]google`
- IP address: `199.247.10[.]166`

Full set of 49 indicators unlocks with TL Creds: https://threadlinqs.com/tl-creds

## Sources

- [GlassWorm Malware Takedown Disrupts Developer Supply Chain Attack Infrastructure](https://thehackernews.com/2026/05/glassworm-malware-takedown-disrupts.html)
- [First Self-Propagating Worm Using Invisible Code Hits OpenVSX Marketplace](https://www.koi.ai/blog/glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-marketplace)
- [Live Updates: GlassWorm, First Self-Propagating Worm Using Invisible Code Hits OpenVSX And VSCode Marketplaces](https://www.koi.ai/incident/live-updates-glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-and-vscode-marketplaces)
- [Self-Propagating GlassWorm Attacks VS Code Supply Chain](https://www.darkreading.com/application-security/self-propagating-glassworm-vs-code-supply-chain)
- [GlassWorm — Self-Propagating VSCode Extension Worm](https://www.truesec.com/hub/blog/glassworm-self-propagating-vscode-extension)
- [GlassWorm: The First Self-Propagating VS Code Extension Worm](https://www.veracode.com/blog/glassworm-vs-code-extension/)
- [Supply Chain Attack Targets VS Code Extensions With GlassWorm Malware](https://www.securityweek.com/supply-chain-attack-targets-vs-code-extensions-with-glassworm-malware/)
- [Defending Against GlassWorm: The Invisible Malware That's Rewriting Supply Chain Security](https://snyk.io/articles/defending-against-glassworm/)
- [GlassWorm Malware Has Resurfaced on the Open VSX Registry](https://securityaffairs.com/184427/malware/glassworm-malware-has-resurfaced-on-the-open-vsx-registry.html)
- [Self-Propagating Worm Found in Marketplaces for Visual Studio Code Extensions](https://www.infoworld.com/article/4076668/self-propagating-worm-found-in-marketplaces-for-visual-studio-code-extensions.html)
- [Detecting GlassWorm with YARA Rules](https://www.knostic.ai/blog/detecting-glassworm-yara-rules)

## Full data

The other 8 detection rules (Splunk SPL / Microsoft KQL / Sigma) unlock with TL Creds; a free account includes daily creds: https://threadlinqs.com/?modal=signup
Indicator values unlock with TL Creds, at a lower price on Red and Purple; AI agents can query rules and IOCs through the Threadlinqs MCP server (Purple): https://intel.threadlinqs.com/mcp

Canonical: https://intel.threadlinqs.com/threat/TL-2026-0603
