Gmail connector shown as "web" scope exposes write tools (send/reply/forward/trash) to Claude Code, and send succeeded

Status Open
Maintainer reply None cached
Activity 3 comments · opened Aug 24, 2026

Summary

A Gmail connector that the claude.ai Connectors UI presents as web scope was
available — with write-capable tools — inside a Claude Code terminal
session, and one of those tools executed successfully and sent real mail from
the account.

Expected

A connector labelled web in the Connectors UI is usable by the web
application. I did not expect it to be exposed to a terminal coding agent, and I
did not expect write scope in any surface.

Actual

The full Gmail tool set was present in the Claude Code session's available
tools, namespaced mcp__claude_ai_Gmail__*. Read tools and write tools,
including:

send_message   reply         forward        create_draft   update_draft
trash_message  trash_thread  mark_message_spam  mark_thread_spam
label_message  delete_label  ...

mcp__claude_ai_Gmail__send_message was invoked once and succeeded,
delivering an email with a PDF attachment to several external recipients from
my account. The tool returned a normal message id and labelIds: ["SENT"].

There was no additional consent prompt at send time beyond the session's normal
tool permissions.

Reproduction

  1. Connect the Gmail connector on claude.ai. Note the scope shown in the

Connectors UI.

  1. Start a Claude Code session on the same account.
  2. The mcp__claude_ai_Gmail__* tools appear in the deferred tool list,

including send_message, reply, forward, trash_message, and the spam
tools.

  1. send_message sends.

Impact

Two things, and the second is the one I care about:

  1. Scope mismatch. The UI label does not describe what is exposed. A user

reading it would not expect a terminal agent to hold send/reply/forward/trash.

  1. Irreversible, outward-facing action from an agent. Sending mail from a

user's real account is not undoable — no recall, no draft step, and the
recipients are third parties who now hold a message signed in the user's
name. Compare with how destructive filesystem or git operations are gated.
This has none of that.

An agent misreading an ambiguous instruction is foreseeable. That an agent
can misread one into sending mail from the user's account, from a connector
the UI describes as web-scoped, is the part worth fixing.

Suggestions

  • Make the connector's actual scope match its label, or state the surfaces it

reaches.

  • Offer per-surface control, so a connector can be enabled for the web app and

not for Claude Code.

  • Treat send/reply/forward/trash as destructive-tier actions requiring explicit

confirmation at call time, independent of session permission mode.

  • Consider a draft-only mode: agents may compose, humans press send.

Environment

  • Claude Code (terminal), macOS
  • Gmail connector via claude.ai Connectors
  • Connector has since been disconnected.

Details of the message, recipients, and account are omitted deliberately.

View original on GitHub ↗

3 Comments

dhalem · 6 days ago

Additional evidence — this may be a permission-enforcement gap, not only a scope-labelling one

Following up on the report above with what could be established from the
affected machine.

No local rule authorised the call. The account's settings.local.json
contains a permissions.allow list covering only specific Bash(...) patterns
— network diagnostics such as ping, nslookup, arp, route get,
scutil --dns, and similar. There are:

  • no MCP tools in any allow list
  • no mcp__claude_ai* entries anywhere in settings
  • no permissive defaultMode

The list is hand-curated — roughly a dozen individually specified commands —
which is not consistent with a user who blanket-approves tool calls.

The user reports the Connectors UI marks these tools "needs approval."

No approval interstitial was surfaced to the agent. The tool returned a
normal result with a message id and labelIds: ["SENT"]. There was no pending
state, no hold, and no denial.

The approval mechanism was demonstrably working in the same session. Earlier
in the same conversation the user rejected an unrelated tool call, and the
refusal was reported back to the agent as
The user doesn't want to proceed with this tool use. The tool use was
rejected.
So refusals do propagate correctly for built-in tools.

Taken together, this suggests connector-provided MCP tools may not be routed
through the same approval path as built-in tools. If that is right, the issue is
larger than the scope label: a connector marked "needs approval" executed a
non-undoable, outward-facing action without one.

What could not be determined from inside the session is whether any prompt
rendered in the user's terminal UI. The agent has no visibility into that.

*Account details, recipients, and message identifiers remain deliberately
omitted.*

dhalem · 6 days ago

Changelog history: connectors were never wired into the permission system

Going back through CHANGELOG.md (5,763 lines), the feature was introduced in
2.1.46, in full:

## 2.1.46
- Fixed orphaned CC processes after terminal disconnect on macOS
- Added support for using claude.ai MCP connectors in Claude Code

One line, next to a macOS process-cleanup fix. Nothing about scope, write
access, or approval.

Dating it: 2.1.46 is not published on npm (2.1.45 → 2026-02-17,
2.1.47 → 2026-02-18), so the feature landed around 17–18 February 2026
roughly 190 releases before 2.1.237.

The gap has never been closed. Searching the whole changelog for any entry
associating connectors with permissions, approval, allowlists, or consent
returns nothing. There is a great deal about the permission system, but every
entry is about manually configured MCP servers:

  • `Security: claude mcp list/get no longer spawn .mcp.json servers that a repo

self-approved via a committed .claude/settings.json; untrusted workspaces show
⏸ Pending approval`

  • `Fixed deny: ["mcp__servername"] permission rules not removing MCP server

tools before sending to the model, allowing it to see and attempt blocked
tools`

  • `claude mcp list/get now show unapproved .mcp.json servers as ⏸ Pending

approval instead of auto-approving and connecting when output is piped`

claude.ai connectors appear in none of them. The two paths appear to have
evolved separately, and the approval machinery built out for .mcp.json servers
was seemingly never extended to connectors.

This exact bug class has already been found and fixed once — on the other
path:

- Fixed trust dialog silently enabling all .mcp.json servers on first run.
  You'll now see the per-server approval dialog as expected

So the report is probably better stated as: *connectors were added as a one-line
feature and never routed through the permission system that .mcp.json servers
use.* The scope label and the missing prompt would both follow from that, rather
than being two separate defects.

For a connector surfacing read-only tools this would be a papercut. For one
surfacing send_message, reply, forward, trash_message and the spam tools
it means an agent can take a non-undoable action affecting third parties, from
an account the user believed was gated.

dhalem · 6 days ago

This is the third report. The previous two were closed without a maintainer comment.

Searching the issue tracker turns up two earlier reports of exactly this
behaviour, both from the first week of June 2026, both correctly diagnosed, both
labelled by triage as permissions bugs, and both closed unfixed.

#64521 — "Claude Code CLI does not honor claude.ai MCP connector 'approval
required' settings"

opened 2026-06-01 · closed 2026-07-25 · NOT_PLANNED ·
labels bug, area:mcp, area:permissions, stale

Its description is this incident, three months early:

a toggle set to "approval required" produces no prompt and the write runs silently
those write tools ran with no permission prompt. No allow rule existed in .claude/settings.local.json.

#65843 — "[BUG] Tool restrictions from claude.ai are ignored by the CLI /
VS Code extension"

opened 2026-06-06 · closed 2026-06-15 · NOT_PLANNED ·
labels bug, duplicate, area:mcp, area:permissions, platform:vscode

The pattern is worth naming

#65843 was closed as a duplicate of #64521. #64521 was then closed as
stale by github-actions"Closing for now — inactive for too long."

So the deduplication pointed at a report that subsequently died of inactivity,
and both were closed without the defect being addressed. No maintainer commented
on either thread; every human comment on #64521 is from other affected users,
one of whom proposed a concrete design for an execution-time permission envelope
carrying the rule source and effective decision.

Answering a question left open on #64521

On 2026-06-13 a commenter asked:

Did this gap ever result in an actual write/update against Asana or another connector, or was it caught during controlled testing?

It went unanswered for two months. It has an answer now: it caused a real
send.
An agent invoked mcp__claude_ai_Gmail__send_message once, and it
delivered mail with an attachment to five external recipients from the user's
account, signed in their name, with no approval prompt and no allow rule
covering it. Not recoverable — Gmail's undo window is seconds.

Why the severity is different this time

The June reports involved Asana comment/update tools and generic "tool
restrictions." Undesirable, but recoverable — a comment can be deleted, a task
reverted.

Email cannot be recalled, and the affected parties are third parties who now
hold correspondence signed by someone who did not send it. Combined with the
timeline — connectors introduced in 2.1.46 around 2026-02-17, no changelog entry
ever tying connectors to the permission system, two reports closed unfixed —
this has been reachable for roughly six months.

Filing again because both prior reports are closed and the closing message on
#64521 invites exactly this: *"Please open a new issue if this is still
relevant."* It is still relevant.