Subscribe
← All Case Files
High CASE #056 · FILED 08 AUG 2026 · 5 MIN READ

gemini-mcp-tool piped tool arguments into a shell, and a single quote was enough for remote code execution

Summary

gemini-mcp-tool is an MCP server that lets AI coding assistants drive Google’s Gemini CLI — reading local files, running git commands, and invoking build scripts on a developer’s behalf. Trend Micro’s Zero Day Initiative disclosed that the tool’s execAsync wrapper passed MCP tool-call arguments into Node’s child_process.exec, which spawns a shell, without adequate sanitization. Any caller able to reach the server’s tools/call endpoint could inject shell metacharacters into that argument and run arbitrary commands as the service account, with no authentication required. A related flaw let the same input path read and exfiltrate arbitrary local files via the tool’s @file reference parser. The maintainer shipped a fix in version 1.1.6; ZDI’s coordinated disclosure went public on 9 January 2026, roughly six months after the initial report.

What was observed

The vulnerable code path took the arguments object from an incoming JSON-RPC tools/call request and forwarded a value from it into execAsync, which called child_process.exec with a single interpolated command string rather than execFile or spawn with an argument array:

// simplified shape of the flaw
exec(`gemini ${userSuppliedArgument}`, callback);
// exec() spawns /bin/sh (or cmd.exe on Windows) and hands it one string;
// the shell — not the OS — decides where the command ends

Because exec hands the whole string to a shell for parsing, wrapping the argument in quotes did not close the hole: a value like foo'; rm -rf /tmp/x; echo ' breaks out of the quoting and appends a second command that the shell happily runs. On Windows, the tool’s cmd.exe argument handling had the equivalent gap — unquoted metacharacters could escape the intended command. A companion bug in the @file reference parser used to let Gemini pull local files into context lacked a working-directory boundary, so a crafted reference could point outside the project folder and exfiltrate arbitrary files readable by the service account.

ZDI rated the primary flaw CVSS 9.8 — network-reachable, no authentication, no user interaction — because the MCP transport this tool commonly runs behind (an HTTP or SSE bridge fronting the local stdio process, used in shared developer and CI/CD environments) puts the vulnerable endpoint on a reachable network path. Some researchers noted the exploit failed against payloads sent through polished MCP clients like Claude Desktop or Gemini’s own chat UI, which do some client-side filtering of suspicious tool calls. That is not a defense: an attacker with direct access to the server’s RPC port bypasses the client entirely, and indirect prompt injection can manipulate the LLM itself into emitting the malicious argument on the attacker’s behalf. Client-side politeness is not a security boundary when the server-side sink is unguarded.

Mitigation

Upgrade to gemini-mcp-tool 1.1.6 or later, which replaces the shell-spawning exec call with execFile/spawn and adds working-directory containment for @file references. Until patched, do not expose the tool’s RPC port beyond a trusted local process, and monitor for unexpected child processes spawned by the service account. More generally: any MCP server that wraps a CLI tool is one exec() call away from becoming a command-injection sink, and the arguments it receives should be treated as adversarial regardless of whether they were typed by a person or generated by a model — an LLM tricked by prompt injection produces exactly the same malicious string a human attacker would type directly.

FIRST OBSERVED: 09 JAN 2026  ·  STATUS: PATCHED