Package contents

Check V12 · execution family · automatic · one of the 17 VS Code Marketplace checks

The question this check asks: what is inside the package you would install — which files under node_modules are executables or scripts, which files anywhere are native code, and how big is the whole thing? Listed from the archive's own directory; not read, and not run.

Why it matters

A .vsix is a zip, and what runs when an extension activates is JavaScript inside it — which this tier does not read. What a file list can show is the part of a package that executes without being JavaScript: Windows executables and scripts (.exe .dll .scr .bat .cmd .vbs .ps1 .com .pif), shell scripts, JARs and installers (.sh .jar .msi), and native code (.so .dylib .node) — and where each sits. Inside node_modules/ these are ordinarily the leftovers of a dependency that was not bundled away; outside it, they are native code the extension itself ships.

The campaign that shaped this check is the one a file list cannot see, and this page says so first. ReversingLabs (Petar Kirhmajer, 10 December 2025) described 19 theme extensions across four publishers — malkolm, pandaexpress, prada555 and priskinski — every one at version 1.0.0, active since February 2025 and discovered on 2 December. Each shipped a modified copy of the npm package path-is-absolute inside its bundled node_modules; that package's banner.png was not an image but an archive holding two binaries, one launched through the cmstp.exe LOLBin and the other a Rust trojan. Four of the nineteen used @actions/io instead and split the binaries across .ts and .map files. Nothing was downloaded at install: the dependencies were pre-packaged in the .vsix. What a file list sees of all that is node_modules/path-is-absolute/banner.png — a PNG. Nothing in the listing is an executable, and V12 would not have flagged it. These were themes, so V7 would have seen no declared code either. In ReversingLabs' own count, detections of malicious software on VS Code went from 27 in 2024 to 105 in the first ten months of 2025.

The second shape is the same lesson from the other side. Koi Security's MaliciousCorgi pair (January 2026, as quoted by BleepingComputer and The Hacker News) — whensunset.chatgpt-china at 1,340,869 installs and zhukunpeng.chat-moss at 151,751 — both worked as advertised while hidden code read every opened file, Base64-encoded it and posted it to a server, with a server-triggered mode that exfiltrated up to 50 workspace files per command. That lived in the bundle's JavaScript. It is likewise invisible to this check. What V12 does with what it can see is name what executes in the package and grade it by whether the listing has earned its age — and the tool for reading what any of it does is the deep scan.

How RepoGates scores it

The file list comes from the package's central directory. The gallery names the .vsix asset; two ranged GETs — the last 64 KB, which holds the end-of-central-directory record, then the central directory itself — return every entry's path, size and method. The Marketplace's CDN answers 206, an 18 MB package lists for about 400 KB, the package is never downloaded, nothing is extracted to disk, and a zip64 archive is refused rather than guessed at. Across the 100 most-installed extensions the median listing is 71 files; ms-python's is 2,420. Three rows read that list:

vsx-dep-executable:<path> — an executable, script or native file inside a node_modules/ folder. INFO at 0 points on an established listing (a publishedDate 90 days or more ago), and MEDIUM at 5 points on a newer one:

"V12; an executable or script inside node_modules/ — a note on an established listing (4 of the top-100 ship playwright/applicationinsights/mpg123 helpers there, measured 2026-09-18), MED on a new one; the 2025 campaign hid JavaScript there, which no file list can tell from a dependency"

vsx-native-binary:<path> — native code outside a dependency folder, graded the same way, INFO established and MEDIUM at 5 points new:

"V12; native code in the package — noted on an established extension, MED on a new one"

vsx-oversize — a package over 25 MB, always a note:

"V12; informational"

Each of the first two is capped at three rows, worst first. A script beside the extension's own code is not a finding: ms-python ships a deactivate.ps1 next to its own code, and a row that fired on it would be a row that fires on the flagship. The verdict rule is the one every V-check shares — the worst fired severity decides it: any CRITICAL reads BLOCK, any HIGH or MEDIUM reads REVIEW, INFO alone reads PASS; the score, 100 minus every fired penalty and floored at zero, is reported beside it (green at 80 and above, amber 50–79, red below 50). A lone MEDIUM row here reads REVIEW at 95; a note reads PASS. V12 feeds two dimensions — Open in an editor (with V7, V8 and V13–V16) and Install and run (with V6–V9 and V11) — each taking the worst of its checks and reading PASS only when every one of them ran. When the package listing cannot be fetched, V12 and V13–V16 are reported as skipped, not passed, and neither dimension can read PASS.

False positives we know about

In the 18 September 2026 measurement of the 100 most-installed extensions V12 fired as a note on 20: a dependency executable on 7, a native binary on 12, an oversized package on 1. Four of the dependency-executable rows are the ones that set the grading: Live Server, Code Runner, Live Share and indent-rainbow ship playwright's install_media_pack.ps1 and PrintDeps.exe, applicationinsights' generateSchema.ps1 and mpg123's makedll.sh inside node_modules — unbundled dependencies, and legitimate. Before the grading those four read REVIEW and the run was 87 PASS, 13 REVIEW; after it, all 20 read PASS and the run is 99, 1, 0. The cost on the other side is stated rather than hidden: a genuinely new extension that ships an unbundled dependency with a .ps1 in it reads REVIEW at 95 for its first 90 days. That is accepted, because the same shape on a new listing is exactly what the 2025 campaign looked like from outside — minus the part a listing cannot see.

What this check does not cover

What any of it does. V12 knows names, sizes and locations, and nothing else: banner.png is a PNG to it, a payload renamed .json passes, and so does an executable renamed .txt. The JavaScript bundle is not read on this tier — MaliciousCorgi's exfiltration and the fake-image campaign's loader both lived there, and neither would have produced a row here. There are no per-file hashes or signatures (V6 covers the package's signature as a whole). Each row kind is capped at three paths. A zip64 archive yields no listing at all, and V12 is then reported as skipped. Reading the files — every one of them, for what they do — is the deep scan's job.

RepoGates assesses a Marketplace extension on request — through the API, the MCP server (platform="vsx") and the preflight for code --install-extension. It does not see an extension installed from the editor's own UI, or one that auto-updates; the board on marketplace pages is not built yet; Open VSX (where VSCodium, Cursor and Windsurf install from) is a different registry and is not assessed. The extension's code bundle is not read on this tier: a PASS means the provenance and the declared surface are clean, never that the JavaScript was inspected.

Check it yourself

The listing page's Resources column has a Download Extension link; what you get is a zip, and the extension's own files sit under extension/ inside it:

unzip -l publisher.extension-1.2.3.vsix \
  | grep -E 'node_modules/.*\.(exe|dll|scr|bat|cmd|vbs|ps1|sh|jar|msi|com|pif|so|dylib|node)$'
unzip -l publisher.extension-1.2.3.vsix \
  | grep -E '\.(exe|dll|so|dylib|node)$'
ls -l publisher.extension-1.2.3.vsix

The first line is what the dependency-executable row reads, the second the native-binary row, the third the size. What you are looking at is a listing. To know what a file does, you have to open it — and an archive that calls itself a PNG opens exactly as one would expect.

Questions

Would V12 have caught the 2025 fake-image campaign? No. ReversingLabs' 19 theme extensions (10 December 2025) shipped a modified path-is-absolute inside node_modules whose banner.png was an archive holding two binaries. What a file list sees of that is node_modules/path-is-absolute/banner.png — a PNG. Nothing in the listing is an executable, so this check would not have fired, and neither would V7: these were themes that declared no code. Reading the files is the deep scan's job, not this tier's.

Why is an executable inside node_modules only a note on an established extension? Because legitimate extensions ship them. In the 18 September 2026 measurement of the 100 most-installed, Live Server, Code Runner, Live Share and indent-rainbow carry playwright's install_media_pack.ps1 and PrintDeps.exe, applicationinsights' generateSchema.ps1 and mpg123's makedll.sh inside node_modules — unbundled dependencies. Before the grading those four were REVIEWs; now the row is a note on a listing 90 days or older and MEDIUM at 5 points only on one too new to have earned it.

Does RepoGates download the package to list it? No. A .vsix is a zip, and a zip's central directory sits at its end. Two ranged GETs — the last 64 KB for the end-of-central-directory record, then the directory itself — return every entry's path and size: an 18 MB package lists for about 400 KB, nothing is extracted to disk, and a zip64 archive is refused rather than guessed at. A third ranged GET per file fetches the small agent files V13–V16 read. The JavaScript bundle is never fetched.

Related checks

V7 Declares code execution — what the listing says about running code, where V12 lists what is there to run · V13 Agent config files — the other thing read out of the same package, by a third ranged GET · C15 Committed binaries — the GitHub roster's reading of binaries in a tree · C9 Release-asset binaries — binaries in what you download from GitHub, the closest analogue to a package.

Add RepoGates to Chrome Pricing

Numbers on this page: the 18 September 2026 measurement of the 100 most-installed extensions (99 PASS, 1 REVIEW, 0 BLOCK; V12 as a note on 20; median listing 71 files); ReversingLabs' fake-image write-up (Petar Kirhmajer, 10 December 2025) and Koi Security's MaliciousCorgi figures as quoted by BleepingComputer and The Hacker News (23–26 January 2026), as published; weights from the product's scoring table.