Launch arguments

Check M8 · execution surface family · severity CRITICAL · automatic · one of the 10 MCP-server checks

Maps to OWASP LLM03 OWASP LLM06 ATLAS AML.T0050 ATLAS AML.T0110.001 Launch arguments that download code and run it are the tool's implementation, not its description.

The question this check asks: when your client starts this server, does the command it runs download code from somewhere and run it?

Why it matters

A listing can declare runtime and package arguments as well as the package. A line that pipes curl into a shell, or hands a downloaded script to an interpreter, runs whatever that address serves today, with none of the package checks in between. That is the shape installer campaigns use, and in a listing it is the server's implementation, not its description.

How RepoGates scores it

For every declared package the line is rebuilt as a client builds it — the runtime hint, its arguments, the package, the package's arguments — and read, with each argument on its own, by the same fetch-and-run reading the package roster uses for install scripts. A match is mcpr-launch-fetch-exec:<package>, CRITICAL and 25 points, and the verdict is BLOCK, with the line shown, shortened.

False positives we know about

A vendor's documented installer fetched over https and run in the launch line still fires: the check reads the shape, not who the host is. An override records the reason.

What this check does not cover

What the launched package does once it runs. Arguments added in your own configuration. A command that finds what to run at run time (a path built from pieces): no reading of the text can follow it.

Scope, the same on every page of this roster: RepoGates does not see git clone, package managers or curl — outside Claude Code with the RepoGates plugin, whose hook refuses a clone or install that names a blocked repository on the command line, before it runs. The hook sees Bash tool calls in that one client and nothing else. On a claude mcp add line, a remote address that a listed server declares is judged with that listing's verdict riding along, and is still an ask: anyone may declare any address in a listing, and the server answering there runs on its operator's machine. A listing whose verdict is BLOCK is denied. An address no listed server declares is asked about. A server added by editing a configuration file or through /mcp is not a shell line the hook sees. Edit and Write are read for one thing only — an API key about to be saved — checked on the machine and never sent; that guard asks, it never denies. This roster reads what the official MCP registry publishes about a server — its record, its version history, the repository and packages it declares, the remote addresses it names — and never the server's code or what it does once it runs. A remote-only server is REVIEW at best, never a pass. The registry carries no download count, star count or popularity of any kind, so there is no lookalike check. A server the registry no longer serves is not assessed, never a pass. A PASS means nothing matched on what was read.

Check it yourself

curl -s "https://registry.modelcontextprotocol.io/v0/servers/NAMESPACE%2FNAME/versions/latest" | jq '[.server.packages[]? | {runtimeHint, runtimeArguments, identifier, packageArguments}]'

Questions

What shape fires this check? A download piped into a shell or interpreter, or a fetched script handed to one, in the launch line or in any single argument.

Why is it critical when the other launch checks are medium? Because the line runs code from an address with no package checks in between. It is the implementation of the server, not a description of it.

Does RepoGates run the line to see? No. The line is read as text and never run.

Related checks

M6 Version pinning · M4 Launched package · P5 Install-time code.

Add RepoGates to Chrome Pricing

Sources for this page: the severities and weights from the product's own roster and scoring tables, and the official MCP registry's published record format. See also the MCP servers intelligence page.