Check V15 · agent family · automatic · one of the 17 VS Code Marketplace checks
The question this check asks: does an MCP or agent settings file packed inside this extension — .mcp.json, .cursor/mcp.json, the JSON files under .claude/ — define a command that fetches something from the network and runs it?
V15 is the same detection function as GitHub's C20 and Hugging Face's H16, run on configuration files read out of the .vsix. An MCP server definition is, by design, a command an agent's launcher runs as you, and the class this check names executes before the trust prompt: the finding cites CVE-2025-59536 and CVE-2025-64109, the two published cases of an agent launching a project's configured commands before the person had agreed to trust the folder. A single line — bash -c "curl … | sh" — is the whole attack, and it reads as plumbing to anyone skimming the file.
The package context is the part worth being precise about. An installed extension's directory is not a project an agent is started in, so an .mcp.json packed inside one is inert on install: nothing reads it as a server definition until that directory becomes the working directory of an agent that loads project configuration. That is why V13 records the file's presence as a note. Two of the 100 most-installed extensions ship one — Microsoft's cmake-tools and makefile-tools — and a package carries whatever its build did not exclude. But the file is still a command line waiting for a launcher: copied into a project as a template, opened as a folder to read the extension's source with an agent alongside, or shipped in a package whose author intends exactly that, it runs. V15 keeps the CRITICAL because the payload does not depend on where the file was found.
V15 parses each JSON agent file V13 finds in the package — never a regex over raw text — and walks the document for objects carrying a command, joining it with its args: an MCP server entry and a Claude Code hook are both that shape, and a string that merely appears inside the file, such as an entry in a permissions allowlist, is never a command. A line fires when it both fetches — curl, wget, iwr, irm, Invoke-WebRequest, Invoke-RestMethod — and executes what it fetched: a pipe into an interpreter, an inline program (bash -c, python -c, PowerShell's -Command or -EncodedCommand) on the same line as the fetch, or PowerShell's iex. The finding is CRITICAL, costs 30 points, and quotes the offending line, so the report says which command rather than that something somewhere looked wrong. Any CRIT drives the score to 0, so a package that trips only this check reads BLOCK; the default personal profile sets this check's action to warn, so the verdict stands, the file and the line are named, and the decision is put to you rather than made for you. The scoring table's evidence note:
"pre-trust execution class; 1 legit npx -y FP on top-100 keeps it under an instant red"
Unparseable JSON yields nothing, deliberately — a launcher would not read it either. V15 sits in the Open in an editor and Hand to an AI agent dimension verdicts, each of which takes the worst of its checks, so a hit turns both to BLOCK. If the package listing cannot be fetched the check is reported as skipped, not passed; a package with no agent file in it has nothing to launch, and the check passes.
None on the package contents this check has scanned. In the 18 September 2026 measurement of the 100 most-installed extensions — 99 PASS, 1 REVIEW, 0 BLOCK, every listing read — the two .mcp.json files found, cmake-tools' and makefile-tools', were parsed, defined no command that fetches from the network, and passed; V15 fired zero times, and the run's single REVIEW was V5 on abusaidm.html-snippets. The one legitimate npx -y false positive the evidence note records is a GitHub top-100 measurement, and the react/react keyword false positive that reshaped C20's parsing to read only command values is a GitHub lesson; neither is restated as a Marketplace number, but the parsing discipline they produced is what runs here, unchanged.
It sees the launch line, not the server. A plain npx some-package runs code from a registry too — the package is the payload in that case — and does not fire, because nothing on the line fetches a URL. What a launched server does once running is invisible here, and so is a fetch-and-run written as prose in an instruction file rather than as a command value. The extension's own activation code is not read on this tier: an extension whose JavaScript downloads and runs something — GlassWorm v2's "thin loader", which retrieved a .vsix payload from a GitHub release and installed it with --install-extension (Socket, 25 April 2026, on Open VSX) — is the bundle, not a configuration file, and no check on this tier sees it. Configuration outside the package, a file under a name not on the list, a file larger than 64 KB (listed by V13, contents not read), and the ninth and later agent files in a package are not parsed. And the check reads the configuration at request time; it does not see an agent launch the server later.
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.
Without installing anything: the listing page's Resources column carries a Download Extension link, and a .vsix is a zip with the extension's own files under extension/. Read every command and args as a shell line:
unzip -p EXTENSION.vsix extension/.mcp.json \
| jq -r '.mcpServers | to_entries[] | "\(.key): \(.value.command) \(.value.args // [] | join(" "))"'
The same for extension/.cursor/mcp.json and any extension/.claude/*.json. Any line containing curl, bash -c, iex or npx -y deserves a second read before you do the one thing that would make the file matter: start an agent in the extension's directory. And per the standard, keep the agent on a version that asks before running project configuration, with project-scoped MCP autoload off until you trust the folder.
Does an MCP config that runs npx fire this check? Not on its own, for the same reason it does not on GitHub's C20 or the Hub's H16: launching a package with npx is how most legitimate MCP servers start. The check fires when a single command line both fetches from the network — curl, wget, Invoke-WebRequest — and executes what it fetched: a pipe into an interpreter, an inline bash -c that fetches and runs, or PowerShell's iex. The finding quotes the exact line.
Why would a VS Code extension ship an .mcp.json at all? Because a package carries whatever its build did not exclude, and a repository developed with an AI coding agent beside it often has one. Two of the 100 most-installed extensions ship an .mcp.json — Microsoft's cmake-tools and makefile-tools — and both were parsed, defined no command that fetches from the network, and passed. Inside an installed extension the file is inert until that directory becomes a project an agent is started in; V13 records the presence as a note, and V15 reads the contents anyway.
Does RepoGates see the extension when VS Code installs it? No. RepoGates assesses a Marketplace extension on request — through the API, the MCP server 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; and Open VSX, where VSCodium, Cursor and Windsurf install from, is a different registry and is not assessed. It reads the configuration at request time; it does not see an agent launch the server later.
V13 Agent config files — the files this check parses; presence alone is a note in a package · V16 Credential redirect — the same files pointing an API base URL or key somewhere else · C20 MCP shell-launch config — the same function, reading a git tree instead of a package · H16 MCP shell-launch config — the same function on the Hub's file list.
Add RepoGates to Chrome Pricing
Numbers on this page: CVE-2025-59536 and CVE-2025-64109 as named in the finding; the 18 September 2026 measurement of the 100 most-installed VS Code Marketplace extensions (99 PASS, 1 REVIEW, 0 BLOCK; V15 fired 0 times; 2 .mcp.json files read); Socket Research, 25 April 2026 (GlassWorm v2's loader, on Open VSX); weights and actions from the product's scoring and policy tables.