Malicious VS Code Extensions

Four published campaigns · roster measured 18 September 2026

What this is. Four research teams have separately published malicious extensions for VS Code: ReversingLabs found 19 with a trojan hidden inside a bundled dependency (December 2025), Koi Security found two AI-chat extensions with 1.5 million installs quietly copying every file a developer opened (January 2026), Secure Annex found a vibe-coded ransomware test uploaded as an extension (November 2025), and Socket has tracked the GlassWorm family through 2026 — 73 sleeper clones of popular extensions in April alone. This page states what our 17-check roster (V1–V17) finds against the named exemplars from those reports, its false-positive rate on the 100 most-installed extensions, and the one thing the measurement made plain first: on the Microsoft Marketplace every named exemplar has already been removed, and the live volume of this campaign family is on Open VSX, a registry this roster does not read; Open VSX has its own seventeen checks since 1 November 2026. Neither number below is a guarantee — see "What this doesn't mean".

The four campaigns

  • ReversingLabs, 10 December 2025 — a trojan in a fake PNG. Nineteen theme extensions under four publishers, active since February 2025 and discovered on 2 December, each shipping a modified copy of the npm package path-is-absolute inside its bundled node_modules. Its banner.png "wasn't an image file. Instead, it is an archive containing two malicious binaries" — one run through the cmstp.exe living-off-the-land binary, the other a Rust trojan. Nothing was downloaded at install; the dependency was pre-packaged. The same post counts detections of malicious software on the Marketplace at 27 in 2024 and 105 in the first ten months of 2025.
  • Koi Security, January 2026 — "MaliciousCorgi". whensunset.chatgpt-china (1,340,869 installs) and zhukunpeng.chat-moss (151,751), both working as advertised while hidden code read every opened file, Base64-encoded it and posted it to a server in China; a server-triggered mode exfiltrated up to fifty workspace files per command. Figures as quoted from Koi by BleepingComputer and The Hacker News on 23–26 January 2026: every Koi write-up has redirected to Palo Alto Networks since the acquisition closed on 14 April 2026, so the primary could not be re-read.
  • Secure Annex, 5 November 2025 — "Ransomvibing". suspublisher18.susvsex, description "Just testing": on activation it zipped, uploaded and AES-encrypted a test folder, polled a private GitHub repository for commands with an embedded token, and shipped two AI-generated decryptors. Microsoft removed it on 6 November.
  • Socket, 25 April 2026 — GlassWorm v2 sleeper clones. Seventy-three clones of popular extensions carrying the originals' display names and icons, published benign by publishers created that month and later updated to a loader that fetches a .vsix from a GitHub release and installs it into VS Code, Cursor, Windsurf and VSCodium; six were confirmed malicious at publication. The example pair is MS-CEINTL.vscode-language-pack-tr (Microsoft, 1.1 million installs) against Emotionkyoseparate.turkish-language-pack. All 73 were on Open VSX, as were the 72 Socket found in March delivered through extensionPack dependencies. The original GlassWorm (Koi, October 2025) hid its loader in invisible Unicode variation selectors and read its command server from Solana transaction memos; the Eclipse Foundation's own account (27 October 2025) puts the reported download count at 35,800 and the incident closed on 21 October.

What the roster catches, alone

Run without the campaign blocklist below — the roster's own signals only, against the Marketplace's live gallery on 18 September 2026 — on every Microsoft-Marketplace identifier the primary write-ups name (ReversingLabs' nineteen, MaliciousCorgi's two, susvsex, the three ahban ransomware listings, Datadog's three MUT-9332 Solidity extensions, Checkmarx's solid281, three WhiteCobra listings, four GlassWorm listings from Secure Annex's November table, and Yeeth's four Solidity Pro stealers from August 2026 — 40 in all), plus four controls:

ListingSourceVerdictWhy
malkolm.theme-artschool-remake and 18 siblingsReversingLabs, Dec 2025not assessablethe gallery returns no record — removed by Microsoft; a MED finding, action warn, never a pass
whensunset.chatgpt-china · zhukunpeng.chat-mossKoi, Jan 2026not assessableremoved; the same MED, warn
suspublisher18.susvsexSecure Annex, Nov 2025not assessableremoved 6 November 2025
17 further listings, six reportsReversingLabs, Datadog, Checkmarx, Kaspersky/Koi, Secure Annex, Yeethnot assessableevery one removed by the time it was measured
MS-CEINTL.vscode-language-pack-trcontrol — the extension GlassWorm v2 clonedPASS 100domain-verified publisher, signed, validated, source declared
equinusocio.vsc-material-themecontrol — pulled by Microsoft in February 2025 by mistake, restored in MarchPASS 1004.3 million installs; the "obfuscated code" was a bundled SDK
7finney.ethcodecontrol — compromised by a pull request in June 2025, repaired in 0.5.1PASS 100the repaired listing, as published
juanblanco.soliditycontrol — the extension the Open VSX fake outrankedPASS 1001.8 million installs, eleven years old

Read plainly: on the Microsoft Marketplace, every published exemplar was removed after disclosure and before we looked, so the roster meets each one as "not assessable" — which is a REVIEW-level finding with the action warn, and never a pass. There is no still-live exemplar on the Microsoft side to score. The four controls — a cloned victim, a wrongly-pulled-then-restored theme, a repaired compromise and an outranked original — all pass, which is the shape a roster should have before anyone trusts its warnings.

What actually blocks these, in the product

All 40 listings above, and the 24 single-purpose publishers behind them, are named entries in RepoGates' campaign blocklist (platform: vsx; confidence: confirmed where the identifier is in a primary source we could read, suspected where it is quoted from one we could not) — the layer that runs ahead of the roster and an account's own allowlist. That matters for a removed listing because of something ReversingLabs documented in August 2025: the name of a removed extension can be re-registered by anyone. An entry here denies the re-registered name before the roster is consulted, and an extension whose declared source repository is listed is CRIT on V5. The roster table above is what the checks alone found; this list is the product's actual behaviour on these names.

What the roster would have seen — and would not

Stated as inference, because the listings are gone. Every named Microsoft-side exemplar was published under a publisher created for it, with no verified domain and no declared source repository, and declared that it runs code — the shape V1, V2, V5 and V7 escalate on a listing under 90 days old, and the shape none of the 100 most-installed extensions has. That is provenance, not proof. What the roster would NOT have seen is the payload itself. ReversingLabs' trojan was a PNG inside a dependency folder — a file list shows a PNG, and V12 says plainly that it lists what executes inside a package without reading it. MaliciousCorgi's exfiltration lived in the extension's JavaScript, which this tier does not read. GlassWorm's loader hid in invisible Unicode inside JavaScript, not inside the agent rule files V14 reads. Reading the bundle is a deep scan, which is decided and not started for extensions; until it exists, a PASS here means the provenance and the declared surface show none of what these checks look for, never that the code was inspected.

False positives on the top 100

Run against the 100 most-installed extensions on the Marketplace (18 September 2026, locally through the same code that answers /v1/vsx/score): 0 BLOCK, 1 REVIEW, 99 PASS, no partial scans, every package's file list read, 1.1 seconds median. The one REVIEW is abusaidm.html-snippets: an established listing whose publisher has no verified domain and which declares no source repository — nothing ties the package to anyone, and the roster says so at MED.

The first run of the same day said 87 PASS, 13 REVIEW, and all thirteen were legitimate extensions caught by rules aimed at the wrong thing. Four — Live Server, Code Runner, Live Share, indent-rainbow — ship unbundled dependencies whose node_modules carry playwright's, applicationinsights' and mpg123's build helpers, and V12 was treating any executable there as the ReversingLabs hiding place, which it cannot recognise anyway. Four — GitHub Copilot, Claude Code, ChatGPT and one more — declare no source repository because they are closed source by design; V5 now treats that as a note for a domain-verified publisher. Five — prettier, vscode-icons, Markdown Preview Enhanced and Microsoft's own CMake Tools and Makefile Tools — ship a CLAUDE.md, an AGENTS.md or an .mcp.json inside the package, and V13 was scoring that as it scores a repository; an installed extension's directory is never the workspace an agent opens, so it is now a note, and the files are still read. Those three gradings, and the reason for each, are in the check pages; the numbers above are from the run after them.

Open VSX

GlassWorm v2's 73 clones, the 72 extensions Socket found delivered through pack dependencies in March 2026, the sleepers that activated in March, and the fake "Solidity Language" behind a US$500,000 theft in July 2025 were all on Open VSX — the registry VSCodium, Cursor and Windsurf install from. Since 1 November 2026 RepoGates assesses Open VSX by seventeen checks of its own (O1–O17), read from Open VSX's own record rather than the Microsoft one, because a listing there may be a different package under the same id. A code --install-extension line or a Marketplace URL is assessed against the Microsoft record; an Open VSX URL is assessed against Open VSX's, and a codium, cursor or windsurf --install-extension line against both. The threat model and the measurement are on the Open VSX page.

What this doesn't mean

The Marketplace validates and signs every extension it publishes, and every campaign above passed that validation; V6 and V11 read it as necessary, never as sufficient. An extension that scores PASS today was checked today, on its publisher, its listing, its declared surface and the file list of its package — never a claim that its JavaScript is benign, never a claim about the version it auto-updates to tomorrow, and never a claim about a listing installed from the editor's own UI, which no hook and no preflight sees.