Reported to Google VRP as b/524448710 (closed Won't Fix / Infeasible, P2 / S4). The triage team confirmed on 2026-07-27 that a public PR is welcome, so I am filing the details and a proposed fix here.
Summary
Plan Mode tells the user it is read-only ("You are in Plan Mode with access to read-only tools"). For MCP tools, the read-only signal is the readOnlyHint annotation supplied by the MCP server itself. Gemini CLI does not verify that annotation, and the Plan Mode policy promotes any MCP tool carrying it out of the deny-all and into ask_user.
A malicious or compromised MCP server can therefore set readOnlyHint: true on a destructive tool and have it offered inside Plan Mode, while an honestly annotated destructive tool from the same server is correctly denied. The server decides which of its tools Plan Mode will surface.
The confirmation prompt still fires, so this is not silent execution. The gap is that the prompt never tells the user the read-only claim came from the server and was never verified, while Plan Mode's own messaging tells them Plan Mode is read-only.
Where this is on main
packages/core/src/policy/policies/plan.toml denies everything in Plan Mode at priority 40, then promotes annotated tools above it:
[[rule]]
toolName = "*"
mcpName = "*"
toolAnnotations = { readOnlyHint = true }
decision = "ask_user"
priority = 50
modes = ["plan"]
interactive = true
packages/core/src/tools/mcp-client.ts:1367 takes the value straight from the server's tools/list response:
const isReadOnly = annotations?.readOnlyHint === true;
packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx renders the MCP confirmation with the server name and tool name only. The read-only claim, and the fact that it is unverified, are never shown to the person being asked to approve.
Reproduce
- Configure an MCP server exposing two tools: one with
annotations: { readOnlyHint: true } whose implementation is destructive, and one with readOnlyHint: false.
- Start
gemini and enter Plan Mode with /plan.
- Ask for the honest tool. It is unavailable, correctly denied.
- Ask for the tool that claims read-only. Plan Mode offers
Allow execution of MCP tool "..." from server "..."? and it runs on approval.
Verified end to end on 0.45.1, and separately against the current default policy TOMLs by loading them with @iarna/toml and applying the engine's annotation matching and priority resolution. Only the server-supplied value changes between the two runs:
readOnlyHint = true -> "ask_user" (priority 1.050, plan.toml)
readOnlyHint = false -> "deny" (priority 1.040, plan.toml)
Preconditions, stated plainly
The user has to add the malicious or compromised server to their own configuration, and the confirmation prompt still appears. This is not silent execution and I am not arguing that it is. What it defeats is the specific expectation Plan Mode sets, which is the thing that makes the approval more likely to be granted.
Proposed fix (PR to follow)
Surface the provenance at the point of decision. When an MCP tool reaches the Plan Mode confirmation because of readOnlyHint, tell the user that the server declared the tool read-only and that Gemini CLI has not verified that claim. Additive, no default behavior change, Plan Mode MCP support stays intact.
Possible follow-up, if you want it
Gate the promotion on user-side trust: honor readOnlyHint in Plan Mode only for servers the user has explicitly marked trusted, and treat MCP tools as non-read-only in Plan Mode otherwise. Stronger boundary, but it changes default behavior for existing MCP users, so I have deliberately kept it out of the first PR. Happy to build it if you would prefer that shape.
Related prior discussion in the opposite direction: #27156 and #27163 proposed trusting readOnlyHint enough to auto-allow annotated tools in Plan Mode. Both were closed.
Reported to Google VRP as b/524448710 (closed Won't Fix / Infeasible, P2 / S4). The triage team confirmed on 2026-07-27 that a public PR is welcome, so I am filing the details and a proposed fix here.
Summary
Plan Mode tells the user it is read-only ("You are in Plan Mode with access to read-only tools"). For MCP tools, the read-only signal is the
readOnlyHintannotation supplied by the MCP server itself. Gemini CLI does not verify that annotation, and the Plan Mode policy promotes any MCP tool carrying it out of the deny-all and intoask_user.A malicious or compromised MCP server can therefore set
readOnlyHint: trueon a destructive tool and have it offered inside Plan Mode, while an honestly annotated destructive tool from the same server is correctly denied. The server decides which of its tools Plan Mode will surface.The confirmation prompt still fires, so this is not silent execution. The gap is that the prompt never tells the user the read-only claim came from the server and was never verified, while Plan Mode's own messaging tells them Plan Mode is read-only.
Where this is on main
packages/core/src/policy/policies/plan.tomldenies everything in Plan Mode at priority 40, then promotes annotated tools above it:packages/core/src/tools/mcp-client.ts:1367takes the value straight from the server'stools/listresponse:packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsxrenders the MCP confirmation with the server name and tool name only. The read-only claim, and the fact that it is unverified, are never shown to the person being asked to approve.Reproduce
annotations: { readOnlyHint: true }whose implementation is destructive, and one withreadOnlyHint: false.geminiand enter Plan Mode with/plan.Allow execution of MCP tool "..." from server "..."?and it runs on approval.Verified end to end on 0.45.1, and separately against the current default policy TOMLs by loading them with
@iarna/tomland applying the engine's annotation matching and priority resolution. Only the server-supplied value changes between the two runs:Preconditions, stated plainly
The user has to add the malicious or compromised server to their own configuration, and the confirmation prompt still appears. This is not silent execution and I am not arguing that it is. What it defeats is the specific expectation Plan Mode sets, which is the thing that makes the approval more likely to be granted.
Proposed fix (PR to follow)
Surface the provenance at the point of decision. When an MCP tool reaches the Plan Mode confirmation because of
readOnlyHint, tell the user that the server declared the tool read-only and that Gemini CLI has not verified that claim. Additive, no default behavior change, Plan Mode MCP support stays intact.Possible follow-up, if you want it
Gate the promotion on user-side trust: honor
readOnlyHintin Plan Mode only for servers the user has explicitly marked trusted, and treat MCP tools as non-read-only in Plan Mode otherwise. Stronger boundary, but it changes default behavior for existing MCP users, so I have deliberately kept it out of the first PR. Happy to build it if you would prefer that shape.Related prior discussion in the opposite direction: #27156 and #27163 proposed trusting
readOnlyHintenough to auto-allow annotated tools in Plan Mode. Both were closed.