Check G20 · agent surface family · severity CRITICAL · automatic · one of the 22 GitLab checks
The question this check asks: does a checked-in MCP or agent settings file in this gitlab.com project — .mcp.json, .cursor/mcp.json, the files under .claude/ — define a command that fetches something from the network and runs it?
This class executes before the trust prompt. In CVE-2025-59536 (CVSS 8.7) Claude Code ran project code from .claude/settings.json and .mcp.json before the user had accepted the dialog asking whether to trust the folder; it was fixed in 1.0.111. In CVE-2025-64109 (CVSS 8.8) the Cursor CLI auto-executed the commands in .cursor/mcp.json with no confirmation at all. An MCP server definition is, by design, a command your agent's launcher will run as you; a definition whose command reaches out to a URL and executes the reply is curl | sh with an agent's name on it. The launcher is the agent on your machine, and the host the file was downloaded from is no part of the mechanism: a .mcp.json unpacked from a gitlab.com archive is read exactly as one from GitHub. The vetting standard's fix is to patch — Claude Code 2.0.65 or later, Copilot CLI 1.0.43 or later, current Cursor — and to disable project-scoped MCP autoload; this check is the part you can do before the download.
G20 fetches each configuration file the project's tree names through gitlab.com's files API, /repository/files/:path/raw — the same check and the same code as C20, on a snapshot built from GitLab's API — parses the JSON, and reads the command lines it defines: command plus args, joined. A line fires when it both fetches (curl, wget, Invoke-WebRequest and its aliases) and executes what it fetched: a pipe into a shell, an inline bash -c "curl … && ./x", or PowerShell's iex. The finding is CRITICAL, costs 30 points — a project that trips nothing else scores 70 and reads amber — and quotes the offending line: “MCP/agent config launches a shell fetch — pre-trust execution class (CVE-2025-59536 / CVE-2025-64109): bash -c "curl -s https://… | sh"”. The verdict is BLOCK-grade; the default personal policy sets this check to warn, so the download is held and the line is shown, and the strict organisation profile blocks. The evidence note in the scoring table:
“pre-trust execution class; 1 legit npx -y FP on top-100 keeps it under an instant red”
Measured on 19 September 2026 across the 100 most-starred gitlab.com projects, it fired on none. The agent files those projects carry are AGENTS.md, CLAUDE.md and, on three projects, .claude/settings.json; the settings files were fetched, parsed and read for their command lines, and no line both fetches and runs. Unparseable JSON yields nothing, deliberately: a launcher would not read it either, and guessing with a pattern over raw text is exactly what the next section is about.
Two, both from GitHub, and both apply here because the rule is one rule. The first shaped the weight: in the Phase 0 controls one of the 80 most popular repositories ships an MCP configuration that legitimately starts its server with npx -y, so a bare npx no longer fires. The second reshaped the rule. On 2 September 2026 an earlier version of this check — which matched a command key anywhere in the file and the word bash anywhere else — scored React 30 points down, because .claude/settings.json in react/react holds seventeen entries like Bash(yarn test:*): an allowlist of what an agent may run, read as a list of executions. Our own repository's settings file fired it too. The check now parses the document and reads only command lines, on both platforms in the same commit, and the three .claude/settings.json files in gitlab.com's top-100 are the evidence that the fix travelled: none fired. A configuration whose command genuinely fetches and runs — some bootstrap scripts do — will still fire, and should: the finding shows you the line.
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 in the line fetches a URL. What the launched server does once running is invisible here. Configuration outside the project, and configuration under a filename we do not read, are not seen. Nor is a fetch-and-run that lives in an agent instruction file's prose rather than a command field; the standard's advice to read those files before starting an agent is not replaced by this or any check. And a project whose tree the API does not answer — one of the 100, spacecowboy/Feeder — has this check listed as not checked, not passed.
And RepoGates as a whole gates browser downloads only — it does not see git clone, package managers, curl, or fetches made by AI agents outside the browser. On gitlab.com the board and the download gate are a later, separate store release: today the verdict on a gitlab.com project is served by the API and the MCP server. It reads the configuration before the download; it does not see the agent launch the server.
RepoGates runs the same 22 checks on a gitlab.com project that it runs on a GitHub repository, from gitlab.com's public API, under the key gl/{namespace…}/{project}. What that API withholds from an anonymous caller — fork status, a user namespace's account age, and OpenSSF Scorecard, which does not cover gitlab.com — is listed as not checked, never assumed. A self-managed GitLab is another hostname and is not assessed. The repository's code is not read on this tier: a PASS means the provenance and the declared execution surface are clean.
Without installing anything: open .mcp.json and .cursor/mcp.json on gitlab.com and read every command and args as a shell line. From a terminal, through the same files API the check uses — the project path and the file path are both URL-encoded, so .cursor/mcp.json is .cursor%2Fmcp.json:
P='NAMESPACE%2FPROJECT'; REF=main
for f in .mcp.json .cursor%2Fmcp.json; do
curl -sf "https://gitlab.com/api/v4/projects/$P/repository/files/$f/raw?ref=$REF" \
| jq -r '.mcpServers | to_entries[] | "\(.key): \(.value.command) \(.value.args // [] | join(" "))"'
done
Then, per the standard: patch your agent to a version that asks before running project configuration, and disable project-scoped MCP autoload until you trust the folder. Any line containing curl, bash -c, iex or npx -y deserves a second read before that.
Does an MCP config that runs npx fire this check? Not on its own. Launching a package with npx is how most legitimate MCP servers start, and one of the 80 most popular GitHub repositories in our controls does exactly that with npx -y. 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 a shell, an inline bash -c that fetches and runs, or PowerShell's iex. The finding shows you the exact line, and the rule is the same whether the file came from gitlab.com or GitHub.
Why did this check once block React, and does that matter on gitlab.com? An earlier version matched keywords across the whole file, so a command key on one line and the word bash on another fired together. React's own .claude/settings.json holds seventeen entries like Bash(yarn test:*) — an allowlist of what may run, read as executions — and scored 30 points off, measured on 2 September 2026. The check now parses the JSON and reads only the command lines. It matters on gitlab.com because the parser is the same code on both platforms: three of the 100 most-starred gitlab.com projects ship a .claude/settings.json, each was parsed, and none fired. We mention React because a false positive on the most popular repository on GitHub is the kind of thing a vendor should say out loud.
Does RepoGates stop git clone? No. RepoGates gates browser-initiated downloads, and on gitlab.com the board and the download gate are a later, separate store release: today a gitlab.com project's verdict is served by the API and the MCP server. It does not see git clone, package managers, curl, or fetches made by AI agents outside the browser. It reads the configuration before the download; it does not see the agent launch the server.
C20 MCP shell-launch config — the GitHub original · G21 Credential redirect — the same files pointing an API base URL or key somewhere else (CVE-2026-21852) · G18 Agent config files — the files this check parses · G10 Devcontainer and Workspace devfile auto-execution — pre-trust execution one layer down, with GitLab's own devfile beside it.
Add RepoGates to Chrome Pricing
Numbers on this page: CVE-2025-59536 and CVE-2025-64109 as published; Phase 0 controls of 14 August 2026 (one npx -y configuration among 80 popular GitHub repositories); the react/react measurement of 2 September 2026 recorded in the engine's source; the 100 most-starred gitlab.com projects measured 19 September 2026 (three settings files, zero hits); weights and actions from the product's scoring and policy tables.