GlassWorm-Linked VS Code & Open VSX Color Theme Cluster
Executive Summary
Socket Threat Research tied a cluster of VS Code and Open VSX color theme extensions to the GlassWorm supply-chain campaign. A theme only needs declarative JSON, yet VS Code lets it ship JavaScript, and the editor has no fine-grained permission model for what that code does. Two extensions were confirmed malicious: Aurora Nocturne Night Theme (Windows downloader) and the Visual Studio Marketplace build of Cosmic Nebula Themes (GlassWorm loader). Socket linked six cluster identities in Open VSX, including versions of Coca-Cola Christmas, Aurora Borealis Studio Theme and Cosmic Nebula Themes. The reporting is dated 2026-10-03 to 2026-10-05.
Aurora Nocturne ran at editor start, carried a roughly 59 KB obfuscated out/extension.js with part of its payload hidden in zero-width Unicode characters, contacted fingercakes4sale[.]store, wrote the response to %TEMP%\temp_batch.cmd and launched it through cmd.exe with a hidden window. Cosmic Nebula declared a JavaScript entry point with activation on every session, decrypted an embedded stage with AES-256-CBC, ran it via eval(), skipped Russian-language and Russian-timezone hosts, then read a Solana transaction memo as a dead drop to resolve rotating next-stage infrastructure, so operators can change servers without publishing a new extension version. Socket rates the Cosmic Nebula build GlassWorm with high confidence and the wider cluster only as GlassWorm-associated.
This pack is built on developer-endpoint behavior, not on file hashes: the editor as the parent of cmd.exe or a shell, the temp_batch.cmd write and execution, DNS to the named payload host, Solana lookups from an editor process, and executables run out of extension folders. Earlier GlassWorm waves (for example the extension-dependency abuse reported in March 2026) appear only as background, and none of their indicators ship here.
Defender priority: run Q1 to Q4 now across all developer endpoints (zero tuning needed), inventory extensions on every VS Code-family editor including themes, and if a malicious theme ran, treat the host as compromised and rotate every credential, token and key that developer could reach. Removing the extension is not enough.
Source Review & Web Hunter Notes
Source limitation, stated plainly: the primary Socket research page (socket.dev/supply-chain-attacks/glassworm-v2) returned HTTP 403 (a bot challenge page) to automated fetch and could not be read. Every claim below rests on secondary coverage, one item of which (hendryadrian.com) is a verbatim digest of the Socket blog post and carries Socket's IOC list. Nothing was taken from the blocked page, and no snapshot was written for it.
| Tier | Source | Key finding | Carry forward |
|---|---|---|---|
| T2 | hendryadrian.com (Socket digest, 2026-10-03) | Keypoints, MITRE list, IOC list incl. domain, URL path, dropped file, four SHA-256, Solana address, six extension IDs | yes |
| T2 | gbhackers.com (2026-10-05) | Infection chain, Cosmic Nebula loader detail, out/extension.js SHA-256, defender guidance | yes |
| T2 | cyberpress.org (2026-10-05) | Corroborates two confirmed malicious extensions, 59 KB file, hidden cmd.exe launch, Open VSX counts | yes |
| T2 | securityonline.info | Delivery, attribution confidence, detection guidance, CrowdStrike context (GlasswormRAT, May 2026 disruption) | yes |
| T3 | csoonline.com (2026-03-16) | Earlier GlassWorm wave (extension dependency abuse); background only | background only, no IOCs imported |
| blocked | socket.dev glassworm-v2 | HTTP 403 to automated fetch | no |
Decisions. (1) The build brief also mentioned XWorm RAT links, a SOCKS proxy and an HVNC client; none of those terms appear in any fetched snapshot, so they are not asserted here and no detection depends on them. (2) The brief said the Solana address, AES key and hashes were withheld; the hendryadrian digest of Socket's post does list them, so they are shipped with their actual source. (3) The Solana address and AES material are shared with earlier GlassWorm activity per the sources, so they are used as hunt context, not as import rows. (4) All fetched pages were screened for instruction-like text; none was found.
Hunt Brief & Attack Chain
Hypotheses
- H1 (high): a compromised Windows developer host shows a VS Code-family editor spawning cmd.exe against
temp_batch.cmd(Q1, Q2, Q3). - H2 (high): the same host resolves
fingercakes4sale[.]storeshortly before the batch file is written (Q4, Q3). - H3 (medium): a GlassWorm-style loader host shows an editor process resolving Solana infrastructure (Q6).
- H4 (medium): a rare child process, or an executable run from an extension folder, appears under an editor (Q5, Q7, Q8).
- H5 (medium): a cluster-linked extension identity is installed (Q9).
| Step | Behavior | Telemetry | Hunt angle |
|---|---|---|---|
| 1 Delivery | Name-squatted or brand-themed theme on Marketplace or Open VSX; promotional post pushed four Open VSX themes | None at endpoint | Extension inventory (S7, Playbook A) |
| 2 Activation | Executable JS entry point, activationEvents "*", runs every session | None directly | Package inspection (S7) |
| 3 Decode / decrypt | Zero-width Unicode decode, AES-256-CBC stage, eval() | None (in-process) | Gap, see S15 |
| 4 Evasion | Russian language and timezone check, exit if matched | None | Gap, see S15 |
| 5 Dead drop | Solana transaction memo read to resolve next-stage address | DnsRequest | Q6 |
| 6 Download | Aurora Nocturne contacts the payload host and fetches content | DnsRequest | Q4 |
| 7 Drop and run | Content written to %TEMP%\temp_batch.cmd, run by cmd.exe, hidden window | ProcessRollup2, DnsRequest (the write itself is not covered by any documented file-write event) | Q1, Q2, Q3; write is a gap, see S15 |
| 8 Follow-on | In-memory JS with Node.js access; credential, token and wallet theft known for GlassWorm; GlasswormRAT per CrowdStrike | ProcessRollup2 (children) | Q5, Q7, Q8 |
Consolidated IOC Table
Atomic indicators below are traced to the saved source snapshots. Cross-platform reuse note: the Solana address and AES material are reported as shared with earlier GlassWorm waves, so they are hunt context, not import rows.
| Type | Value | Confidence | Action | Context |
|---|---|---|---|---|
| Domain | fingercakes4sale[.]store | high | detect | Aurora Nocturne payload host; 4 secondary sources |
| URL | hxxps://fingercakes4sale[.]store/dsyuC | high | detect | Aurora Nocturne download location. Not importable to Falcon IOC Management |
| File path | %TEMP%\temp_batch.cmd | high | detect | Dropped and executed batch script; behavioral (Q1 to Q3) |
| SHA-256 | 5e68ca8c2097caccdb74d2752b85b85595a4bf646b442b8431a2416e87dbf268 | medium | detect | Aurora Nocturne out/extension.js loader; two sources. Sensor hash telemetry covers PE files, so a JavaScript hash is unlikely to match |
| SHA-256 | a276b76d3b00f302bb4dfb3690125c85ff472b16049c3c37476ac5e51096df07 | low | hunt | Aurora Nocturne package hash; single source |
| SHA-256 | 684c877a52d226d50584cb886ca8ec5bec6355d4de853f406734c79d5b387804 | low | hunt | Cosmic Nebula Themes; single source |
| SHA-256 | da2d950e50326171adbff9c2bfd6f28998e32623ea7c2c475b9159a45cfb86bb | low | hunt | Cosmic Nebula Themes; single source |
| Solana address | BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC | medium | hunt | Dead-drop address in Cosmic Nebula loader; shared with earlier GlassWorm per Socket. Context only |
| Crypto material | wDO6YyTm6DL0T0zJ0SXhUql5Mo0pdlSz, 4c4b9a3773e9dced6015a670855fd32b | low | pivot | Loader parameters per one digest; key vs IV role unconfirmed. Pivot only |
| HTTP headers | ivbase64, secretkey | low | pivot | Stage-retrieval response headers per one digest |
| Repository | vovanloc2234-sudo/Cosmic-Nebula-Themes | low | pivot | Cosmic Nebula source repository (public source may not match shipped package) |
| Extension IDs | holiday-themes.theme-coca-cola-christmas, lohsebhipolg2s.theme-aurora-borealis, aurora-them-creator.theme-aurora-nocturne, solidity-syntax.deep-focus, charcoal-mint-studio.theme-charcoal-mint, cosmic-themes.theme-cosmic-nebula | medium | hunt | Cluster-linked Open VSX identities; not all weaponized |
| Undisclosed | Final-stage payload, rotating C2 behind the memo, hashes for Coca-Cola Christmas / Aurora Borealis builds | n/a | n/a | Not published in any fetched source; not invented. See S15 |
Affected Surface & Telemetry Matrix
| Surface | Telemetry | Priority | Gap risk |
|---|---|---|---|
| Windows dev workstations (VS Code, Cursor, Windsurf, VSCodium) | ProcessRollup2, DnsRequest | High | Low for process and DNS; extension file contents invisible, and the dropped .cmd script is not a PE so no file-write event fires on it |
| macOS developer laptops | ProcessRollup2, DnsRequest | Medium | Reported downloader is Windows-specific; loader is cross-platform Node.js |
| Linux dev boxes, devcontainers, remote hosts | ProcessRollup2 | Medium | Remote extension hosts may not run a sensor |
| Open VSX consumers (Cursor and other VS Code forks) | Extension inventory | High | No sensor view of registry installs; needs inventory |
ATT&CK Mapping
| Tactic | Technique | Observed behavior | Query or control |
|---|---|---|---|
| Initial Access | T1195.002 Compromise Software Supply Chain | Theme extensions on Marketplace and Open VSX | Q9, Playbook A/B |
| Execution | T1059.007 JavaScript | eval() of decrypted stage, Node.js VM | Q5, Q7 (gap in-process) |
| Execution | T1059.003 Windows Command Shell | cmd.exe runs temp_batch.cmd | Q1, Q2, Q3 |
| Defense Evasion | T1027 Obfuscated Files | 59 KB obfuscated JS, zero-width Unicode | Gap (static analysis) |
| Defense Evasion | T1140 Deobfuscate/Decode | Zero-width decode, AES-256-CBC | Gap (in-process) |
| Discovery | T1614.001 System Language Discovery | Russian locale/timezone exit | Gap |
| Command and Control | T1102.001 Dead Drop Resolver | Solana transaction memo | Q6 |
| Command and Control | T1105 Ingress Tool Transfer | Download from payload host to temp_batch.cmd | Q3, Q4 |
Native Audit-Log Hunts
- Extension inventory:
code --list-extensions --show-versionsper editor, and for Cursor and other forks their equivalent CLI. Run Playbook A to flag themes that ship a JavaScript entry point. - Package inspection: in each installed extension folder read
package.json:mainorbrowserset on a theme,activationEventscontaining"*", and anyout/extension.jsnear 59 KB on a theme. Inspect the installed package, not the public repo; Socket reports they diverged. - Marketplace removal status: Microsoft removed the reported Marketplace themes; confirm installed copies are gone and that the editor blocked the removed IDs.
- Network and proxy logs: search for
fingercakes4sale[.]storeand for editor user-agents calling Solana RPC endpoints. - Version drift: re-run inventory after every extension update; Socket notes clean themes can turn malicious later.
CrowdStrike LogScale CQL Hunt Queries
Looks for: A VS Code-family editor (Code, Cursor, Windsurf, VSCodium) as the parent of cmd.exe where the command line references temp_batch.cmd, the exact drop-and-run behavior reported for the Aurora Nocturne Night Theme downloader.
// HUNT: Editor spawns cmd.exe running temp_batch.cmd (GlassWorm theme downloader) // MITRE: T1059.003, T1195.002, T1105 // CONF: high // FP: low // COST: low // REQUIRES: ProcessRollup2 on Windows developer endpoints // FALSE POSITIVES: none expected; a color theme has no legitimate reason to spawn a batch file #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | event_platform=Win | ParentBaseFileName=/^(code|code - insiders|cursor|windsurf|codium|vscodium)(\.exe)?$/i | FileName=/^cmd\.exe$/i | CommandLine=/temp_batch\.cmd/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine, TargetProcessId, SHA256HashData])
Looks for: Parent-agnostic execution of temp_batch.cmd through cmd.exe. Catches a variant that re-parents through node.exe or an Electron helper, where the editor is not the direct parent.
// HUNT: cmd.exe executing temp_batch.cmd (parent-agnostic) // MITRE: T1059.003 // CONF: high // FP: low // COST: low // REQUIRES: ProcessRollup2 on Windows // FALSE POSITIVES: an unrelated internal script that happens to share the filename (verify the parent chain) #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | event_platform=Win | FileName=/^cmd\.exe$/i | CommandLine=/temp.{0,3}temp_batch\.cmd/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine, TargetProcessId])
Looks for: Both halves of hypothesis H2 on one host: the DNS lookup of the payload domain, and a cmd.exe that runs temp_batch.cmd. Correlating them raises confidence well above either signal alone. Why this is not a file-write query: the loader writes the batch file from inside the editor's in-process Node runtime, and a .cmd script is not a PE, ELF, archive or document, so no documented Falcon file-write event (NewExecutableWritten, PeFileWritten, ElfFileWritten, ZipFileWritten, DocumentFileWritten) fires on it. The write itself is recorded as a gap in S15 rather than detected with an event name this pack cannot verify.
// HUNT: payload-host DNS lookup correlated with temp_batch.cmd execution on the same host // MITRE: T1105, T1059.003, T1071.001 // CONF: high // FP: low // COST: medium // REQUIRES: Falcon sensor on Windows developer hosts (DnsRequest + ProcessRollup2) // FALSE POSITIVES: near none; requires both the named attacker domain and the named batch filename on one host // TUNING: selfJoinFilter correlates by host (aid) over the search window, not by exact process tree or ordering; confirm the DNS lookup precedes the cmd.exe start before escalating, and widen the window if the drop and run are minutes apart #event_simpleName=/^(DnsRequest|ProcessRollup2|SyntheticProcessRollup2)$/ | selfJoinFilter(field=[aid], where=[ {#event_simpleName=DnsRequest DomainName=/fingercakes4sale\.store$/i}, {FileName=/^cmd\.exe$/i CommandLine=/temp_batch\.cmd/i} ]) | table([@timestamp, aid, ComputerName, UserName, #event_simpleName, DomainName, ParentBaseFileName, FileName, CommandLine])
Looks for: DNS resolution of the one named payload domain, and the process that asked for it. The reported URL path is /dsyuC on that host; DNS telemetry carries only the name.
// HUNT: DNS lookup of fingercakes4sale[.]store (Aurora Nocturne payload host) // MITRE: T1105, T1071.001 // CONF: high // FP: low // COST: low // REQUIRES: DnsRequest telemetry // FALSE POSITIVES: security researchers or sandboxes resolving the domain on purpose #event_simpleName=DnsRequest | DomainName=/(^|\.)fingercakes4sale\.store$/i | table([@timestamp, aid, ComputerName, DomainName, ContextBaseFileName, ContextProcessId])
Looks for: Rare child-process pairs under a VS Code-family editor on Windows: cmd, PowerShell, wscript, cscript, mshta, node, curl, certutil, bitsadmin. A theme loader that runs decoded JavaScript and hands off to the shell lands here even when the filename changes. FP: the integrated terminal, Git, task runners and debuggers legitimately spawn shells and node. Review the rare tail, not the head.
// HUNT: Editor process spawns shell, script host or downloader // MITRE: T1059.003, T1059.007, T1059.001, T1105 // CONF: medium // FP: medium // COST: medium // REQUIRES: ProcessRollup2 on Windows developer endpoints // FALSE POSITIVES: integrated terminal, git, npm/node tasks, debuggers, language servers // TUNING: baseline 14 days, then exclude the CommandLine values your developers legitimately use (for example CommandLine=/git\.exe|conhost|--ms-enable-electron-run-as-node/i) and sort ascending so rare spawn pairs surface first #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | event_platform=Win | ParentBaseFileName=/^(code|code - insiders|cursor|windsurf|codium|vscodium)(\.exe)?$/i | FileName=/^(cmd|powershell|pwsh|wscript|cscript|mshta|node|curl|certutil|bitsadmin)\.exe$/i | groupBy([aid, ComputerName, ParentBaseFileName, FileName], function=[count(as=Spawns), max(@timestamp, as=LastSeen), collect([CommandLine])]) | sort(Spawns, order=asc, limit=200)
Looks for: The Cosmic Nebula loader reads a Solana transaction memo to learn its next-stage address. A code editor has no business resolving Solana RPC hosts; the sources advise alerting on developer machines that query the Solana blockchain unexpectedly. FP: developers building web3 or Solana projects will resolve these hosts from their own tooling, usually from node or a terminal, not from the editor process itself.
// HUNT: Editor process DNS lookup for Solana RPC / blockchain hosts // MITRE: T1102.001 // CONF: medium // FP: medium // COST: low // REQUIRES: DnsRequest with ContextBaseFileName (validate the field in your tenant) // FALSE POSITIVES: web3 and Solana developers; Solana extensions that call RPC on purpose // TUNING: exclude hosts in a web3 developer group (aid list or sensor grouping tag) and any approved Solana extension; keep the editor-parent filter so terminal-launched tooling stays out #event_simpleName=DnsRequest | DomainName=/solana/i | ContextBaseFileName=/^(code|code - insiders|cursor|windsurf|codium|vscodium|code helper.*|cursor helper.*)(\.exe)?$/i | groupBy([aid, ComputerName, ContextBaseFileName, DomainName], function=[count(as=Lookups), max(@timestamp, as=LastSeen)]) | sort(Lookups, order=desc, limit=200)
Looks for: Processes whose image sits under a .vscode, .cursor, .windsurf or .vscode-oss extensions folder. A theme extension has no native executable to run, so any hit from a theme folder is a strong lead; hits from language-tooling extensions are the noise. FP: language servers and debuggers ship native binaries inside extension folders (Go, Rust, C/C++, Python).
// HUNT: Process image launched from an editor extensions directory // MITRE: T1195.002, T1059 // CONF: medium // FP: medium // COST: low // REQUIRES: ProcessRollup2; the dot after the profile folder matches the path separator so no slash is needed // FALSE POSITIVES: language servers, debug adapters, formatter binaries bundled by legitimate extensions // TUNING: exclude known publisher folders (for example ImageFileName=/ms-python|golang\.go|rust-lang|ms-vscode\.cpptools/i) and keep any hit whose folder name contains "theme" #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | ImageFileName=/\.(vscode|cursor|windsurf|vscode-oss|vscode-insiders).extensions/i | groupBy([aid, ComputerName, ImageFileName, ParentBaseFileName], function=[count(as=Runs), max(@timestamp, as=LastSeen), collect([CommandLine])]) | sort(Runs, order=asc, limit=200)
Looks for: The reported downloader is Windows-specific, but the loader runs full Node.js in-process on every platform. On macOS and Linux the same pivot is an editor helper process launching sh, bash, zsh, curl, wget or osascript. FP: the integrated terminal is a shell child of an editor helper process by design.
// HUNT: macOS/Linux editor helper spawns shell, curl, wget or osascript // MITRE: T1059.004, T1059.002, T1105 // CONF: medium // FP: medium // COST: medium // REQUIRES: ProcessRollup2 on macOS and Linux sensors // FALSE POSITIVES: integrated terminal, Git operations, task runners, extension install scripts // TUNING: exclude interactive terminal launches (CommandLine=/^-?(zsh|bash)( -l)?$/) and sort ascending so one-off curl or osascript spawns surface first #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | event_platform=/^(Mac|Lin)$/ | ParentBaseFileName=/^(code|cursor|windsurf|codium|electron|code helper.*|cursor helper.*)$/i | FileName=/^(sh|bash|zsh|curl|wget|osascript)$/i | groupBy([aid, ComputerName, ParentBaseFileName, FileName], function=[count(as=Spawns), max(@timestamp, as=LastSeen), collect([CommandLine])]) | sort(Spawns, order=asc, limit=200)
Looks for: The six Open VSX identities Socket tied to the cluster, seen in a process path or an --install-extension command line. Socket states not every version was weaponized, so a hit means inventory and inspect that package, not auto-confirm. FP: Coca-Cola Christmas and Aurora Borealis Studio were not weaponized in the versions Socket examined; the solidity-syntax.deep-focus name resembles a legitimate Solidity ecosystem name. Confirm version and package contents before escalating.
// HUNT: Cluster-linked extension identities in process paths or install commands // MITRE: T1195.002 // CONF: medium // FP: medium // COST: low // REQUIRES: ProcessRollup2 (extension host and CLI launches expose the extension folder in the image path or command line) // FALSE POSITIVES: unweaponized versions of the same identities; similarly named legitimate extensions // TUNING: confirm the installed version against Socket's weaponized builds; treat a hit as an inventory lead and inspect package.json activationEvents and the main entry point #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | CommandLine=/holiday-themes\.theme-coca-cola-christmas|lohsebhipolg2s\.theme-aurora-borealis|aurora-them-creator\.theme-aurora-nocturne|solidity-syntax\.deep-focus|charcoal-mint-studio\.theme-charcoal-mint|cosmic-themes\.theme-cosmic-nebula/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine])
CrowdStrike Custom IOA Recommendations
Q1 to Q3 are behavior-pinned and rotate-proof, so they are IOA candidates. Q5 to Q9 stay Investigate-only until baselined.
IOA-1 · Editor spawns cmd.exe running temp_batch.cmd HIGH PRIORITY
Pattern: Process Creation, parent image matches the editor list, image cmd.exe, command line contains temp_batch.cmd. Deployment: deploy directly in detect mode; no baseline needed. Exclusions: none. Alert framing: [CRITICAL] Detection: GlassWorm theme loader, editor ran temp_batch.cmd.
IOA-2 · Batch file written to temp by an editor-launched process
Pattern: File Creation, file name temp_batch.cmd in a user temp directory. Deployment: detect mode. Exclusions: none identified.
IOA-3 · Editor spawns a shell or script host (promote after baseline)
Pattern: Q5 logic. Deployment: run Q5 for 14 days, build the exclusion list from observed developer tooling, then promote.
Machine-Readable IOC Appendix
type,value,action,severity,expiration,description,tags domain,fingercakes4sale.store,detect,high,2027-04-05,Aurora Nocturne Night Theme payload host,campaign:GlassWorm-VSCodeThemes sha256,5e68ca8c2097caccdb74d2752b85b85595a4bf646b442b8431a2416e87dbf268,detect,medium,2027-04-05,Aurora Nocturne out/extension.js loader (JS file; low match odds),campaign:GlassWorm-VSCodeThemes sha256,a276b76d3b00f302bb4dfb3690125c85ff472b16049c3c37476ac5e51096df07,hunt,low,2027-01-05,Aurora Nocturne package hash (single source),campaign:GlassWorm-VSCodeThemes sha256,684c877a52d226d50584cb886ca8ec5bec6355d4de853f406734c79d5b387804,hunt,low,2027-01-05,Cosmic Nebula Themes hash (single source),campaign:GlassWorm-VSCodeThemes sha256,da2d950e50326171adbff9c2bfd6f28998e32623ea7c2c475b9159a45cfb86bb,hunt,low,2027-01-05,Cosmic Nebula Themes hash (single source),campaign:GlassWorm-VSCodeThemes sha256,REPLACE_WITH_COCA_COLA_CHRISTMAS_BUILD_SHA256,hunt,medium,2027-01-05,UNDISCLOSED hash for Coca-Cola Christmas build,campaign:GlassWorm-VSCodeThemes sha256,REPLACE_WITH_AURORA_BOREALIS_STUDIO_BUILD_SHA256,hunt,medium,2027-01-05,UNDISCLOSED hash for Aurora Borealis Studio build,campaign:GlassWorm-VSCodeThemes domain,REPLACE_WITH_SOLANA_MEMO_RESOLVED_C2,detect,high,2027-04-05,UNDISCLOSED rotating C2 resolved from Solana memo,campaign:GlassWorm-VSCodeThemes
# Behavioral signatures (not atomic; do not import as IOCs) editor_parent -> cmd.exe with CommandLine containing temp_batch.cmd file write: %TEMP%\temp_batch.cmd, then cmd.exe execution with hidden window DnsRequest: fingercakes4sale.store (and URL path /dsyuC upstream) editor process (Code, Cursor, Windsurf, VSCodium) resolving Solana RPC hosts theme extension with "main"/"browser" set and activationEvents ["*"] ~59 KB single-line obfuscated out/extension.js in a theme package loader behavior: zero-width Unicode decode, AES-256-CBC stage, eval(), Russian locale/timezone exit Solana address (context only, shared with earlier GlassWorm): BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC
Cluster-linked Open VSX identities (not all weaponized): holiday-themes.theme-coca-cola-christmas lohsebhipolg2s.theme-aurora-borealis aurora-them-creator.theme-aurora-nocturne solidity-syntax.deep-focus charcoal-mint-studio.theme-charcoal-mint cosmic-themes.theme-cosmic-nebula Confirmed malicious: Aurora Nocturne Night Theme, Cosmic Nebula Themes Live but not weaponized when examined: Coca-Cola Christmas, Aurora Borealis Studio Theme Malware: GlassWorm loader; GlasswormRAT (per CrowdStrike, via securityonline)
# Extension audit checklist 1. List extensions on every VS Code-family editor (code, cursor, windsurf, codium). 2. For each theme: package.json main/browser present? activationEvents contains "*"? 3. Any out/extension.js ~59 KB on a theme? Compare shipped package to public repo. 4. Search proxy/DNS for fingercakes4sale.store; editor processes resolving Solana hosts. 5. If a malicious theme ran: isolate, rotate GitHub, npm, Open VSX tokens, cloud keys, SSH keys, wallet data.
Detection Validation Gates
| Gate | Requirement |
|---|---|
| Telemetry ready | Confirm ProcessRollup2 and DnsRequest flow from developer host groups. Confirm DnsRequest exposes ContextBaseFileName in your tenant before relying on Q6. Do not expect a file-write event for the dropped .cmd script: it is not a PE, so the documented write events do not cover it (see S15). |
| Benign baseline | Run Q5, Q7, Q8 over 14 to 30 days and fill the TUNING exclusions with observed developer tooling. |
| Positive tests | Safe simulation only: from a lab host, have code.exe or a renamed copy launch a harmless cmd.exe /c echo with a file named temp_batch.cmd in a temp folder. Do not run any real extension payload. |
| Promotion path | Investigate-only to Custom IOA after two clean baseline weeks. IOA-1 and IOA-2 can deploy immediately. |
Hardening: Tiered
- Inventory every VS Code-family editor extension and flag themes with a JS entry point or activationEvents "*" (Playbook A). MITRE M1047 Audit. Best-practice, no formal benchmark.
- Deploy Custom IOA-1 and IOA-2 in detect mode. MITRE M1049 Antivirus/Antimalware.
- Remove and block any cluster-linked identity from section 4; rotate secrets of anyone who ran one.
- Enforce an extension allowlist through the VS Code managed policy (Playbook B). MITRE M1033 Limit Software Installation. Verify the policy name against your editor version.
- Pilot restricting editor traffic: block Open VSX and unneeded marketplaces for managed fleets that only need Microsoft Marketplace. MITRE M1031 Network Intrusion Prevention.
- Move to a private or mirrored extension registry that serves only reviewed versions. MITRE M1051 Update Software, M1033.
- Cut developer credential blast radius: short-lived tokens, hardware-backed SSH keys, no long-lived npm or Open VSX publish tokens on laptops. MITRE M1026 Privileged Account Management.
Deployable Playbooks
Playbook A · extension audit
# Playbook A: flag theme extensions that ship executable JavaScript (read-only)
# Prerequisites: PowerShell 5.1+, read access to the user profile folders
# Reboot required: No
# Rollback: none required, this playbook only reads files
$roots = @("$env:USERPROFILE\.vscode\extensions","$env:USERPROFILE\.cursor\extensions","$env:USERPROFILE\.windsurf\extensions","$env:USERPROFILE\.vscode-oss\extensions")
foreach ($r in $roots) {
if (-not (Test-Path $r)) { continue }
Get-ChildItem $r -Directory | ForEach-Object {
$pj = Join-Path $_.FullName 'package.json'
if (-not (Test-Path $pj)) { return }
$j = Get-Content $pj -Raw | ConvertFrom-Json
$isTheme = $null -ne $j.contributes.themes
$hasCode = ($null -ne $j.main) -or ($null -ne $j.browser)
$always = $j.activationEvents -contains '*'
if ($isTheme -and ($hasCode -or $always)) {
[pscustomobject]@{ Extension=$_.Name; Main=$j.main; ActivatesAlways=$always }
}
}
}
Playbook B · extension allowlist policy
Prerequisites: admin or GPO rights. Reboot required: No. Rollback: delete the AllowedExtensions value.
# Playbook B: restrict VS Code to an allowlist of extensions (managed policy)
# Prerequisites: local admin or GPO rights; VS Code build that supports the AllowedExtensions policy (verify in your version's policy docs)
# Reboot required: No (restart the editor)
# Rollback: Remove-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\VSCode -Name AllowedExtensions
New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\VSCode" -Force | Out-Null
$allow = '{"REPLACE_WITH_APPROVED_PUBLISHER":true,"REPLACE_WITH_PUBLISHER.REPLACE_WITH_EXTENSION":true}'
New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\VSCode" -Name AllowedExtensions -Value $allow -PropertyType String -Force | Out-Null
# Verify
Get-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\VSCode" | Select-Object AllowedExtensions
Playbook C · Custom IOA deployment
Playbook C: deploy IOA-1 and IOA-2 in Falcon 1. Prerequisites: Custom IOA rights in Falcon Prevention policy admin. 2. Create rule group (Windows). Add rule: Process Creation, parent image regex (code|cursor|windsurf|codium|vscodium)\.exe, image cmd\.exe, command line temp_batch\.cmd. 3. Add rule: File Creation, file name temp_batch\.cmd, in a temp directory. 4. Set action Detect, severity High. Assign the group to a pilot host group. Detect, never Prevent, and High rather than Critical: the whole indicator set rests on secondary coverage of one research post, so nothing in this pack carries a blocking posture or a critical rating (see S2). 5. Reboot required: No. 6. Rollback: disable the rule or unassign the rule group; no endpoint state changes.
Containment Runbook
| Phase | Actions | Owner | Evidence |
|---|---|---|---|
| Isolate | Network-contain the host with Falcon containment; block fingercakes4sale[.]store at DNS and proxy | SOC / IR | Containment timestamp, block rule ID |
| Preserve | Collect the extension folder, %TEMP%\temp_batch.cmd if present, editor logs, and process tree for the editor session | IR | RTR session log, file hashes |
| Eradicate | Uninstall the extension, delete the dropped batch file, remove persistence found in the batch contents, re-inspect all other extensions on the host | IR / Endpoint Eng | Post-clean scan, extension inventory |
| Recover | Rotate GitHub, npm and Open VSX tokens, SSH keys, cloud and CI/CD secrets and wallet data reachable from the developer account; re-image if the batch content shows further execution | IAM / IR | Token revocation log |
| Lessons learned | Deploy Playbook B allowlist; confirm IOA-1 and IOA-2 are live | Security Eng | Change record |
Detection Coverage Map
| Technique | Behavior | CQL | IOA | Coverage |
|---|---|---|---|---|
| T1195.002 | Cluster-linked extension installed | Q9 | No | Partial name-based; inventory is the real control |
| T1059.003 | cmd.exe runs temp_batch.cmd | Q1, Q2 | Yes (IOA-1) | Good |
| T1105 | Payload host lookup, correlated with the batch run | Q3, Q4 | Yes (IOA-2) | Good for the lookup and the execution |
| T1105 (write) | Creation of %TEMP%\temp_batch.cmd itself | n/a | No | GAP the loader writes it from the editor's in-process Node runtime, and a .cmd script is not a PE, ELF, archive or document, so none of the documented Falcon file-write events fire on it. Detected one step later, at execution (Q1, Q2) and by correlation (Q3) |
| T1059.007 | Editor spawns shell / node | Q5, Q7, Q8 | No | Partial FP medium |
| T1102.001 | Solana dead-drop lookup | Q6 | No | Partial needs ContextBaseFileName |
| T1027 / T1140 | Zero-width decode, AES stage, eval() | n/a | No | GAP in-process, not visible to the sensor |
| T1614.001 | Russian locale / timezone check | n/a | No | GAP not observable |
| Hashes | JavaScript file hashes | n/a | No | GAP sensor hash events cover PE files |
Undisclosed indicators, stated plainly. The following are not published in any fetched source and are not invented: hashes for the Coca-Cola Christmas and Aurora Borealis Studio builds, the rotating C2 resolved from the Solana memo, the recovered final-stage payload (Socket did not recover it), and any Falcon-matchable hash for the JavaScript files. They ship as labelled REPLACE_WITH_ placeholders in the CSV. The reported Solana address and AES-like strings come from one digest of Socket's post and are shared with earlier GlassWorm activity, so they are context, not import rows. Validation gates are in section 11.
Hunt Summary Ticket
TITLE: GlassWorm-linked VS Code / Open VSX color theme cluster
SEVERITY: HIGH, developer-endpoint supply chain, credential theft capability
SCOPE: VS Code-family editors (Code, Cursor, Windsurf, VSCodium) on
Windows, macOS, Linux developer hosts
HYPOTHESIS: A host that ran a trojanized theme shows an editor process
spawning cmd.exe against temp_batch.cmd, DNS to
fingercakes4sale[.]store, or an editor resolving Solana hosts.
QUERIES: Q1-Q9 (Section 8); IOA-1 to IOA-3 (Section 9)
DO FIRST: 1. Run Q1-Q4 fleet-wide (7 days), no tuning needed.
2. Run Playbook A extension audit on developer hosts.
3. Run Q9 for cluster-linked extension identities.
4. Baseline Q5-Q8 for 14 days, then tune.
FINDINGS: REPLACE_WITH_FINDINGS_SUMMARY_AFTER_HUNT_EXECUTION
GAPS: In-process decode/decrypt/eval, locale checks, JS file hashes,
Solana-resolved C2 and final payload (Section 15).
ACTIONS: Deploy IOA-1/IOA-2; allowlist extensions (Playbook B);
rotate credentials on any confirmed host.
OWNER: REPLACE_WITH_HUNT_OWNER
VERSION: v0.1 (Draft) 2026-10-05
Changelog
References
| Tier | Source | Used for | Access date |
|---|---|---|---|
| blocked | Socket Threat Research, glassworm-v2 (HTTP 403, not read) | Intended primary; blocked to automated fetch, nothing taken from it | 2026-10-05 |
| T2 | hendryadrian.com, Socket digest | IOC list, MITRE list, keypoints | 2026-10-05 |
| T2 | GBHackers | Infection chain, out/extension.js hash | 2026-10-05 |
| T2 | Cyber Press | Corroboration, Open VSX scale | 2026-10-05 |
| T2 | Security Online | Attribution, guidance, CrowdStrike context | 2026-10-05 |
| T3 | CSO Online (2026-03-16) | Background on an earlier wave only | 2026-10-05 |
Five fetched sources were saved verbatim to GlassWorm-VSCodeThemes-Hunt-sources/ for the provenance gate.
Generated 2026-10-05 by HuntPack · defensive content only