Gate Google Drive Writes to an Authorized IdP Group
Baseline least-privilege policy for Google Drive MCP traffic.
- Direction
- ingress
- Rego package
google_drive.ingress.role_gate_writes- App
- google-drive
- Bundles
- soc2gdpr-ccpa
- Published
- Minimum gateway
- 1.0.0b24
- Schema version
- 1.0.0
- Checksum
sha256:78e9a9a0d9f00492a266ecc50c2d2c843cd662ac5b52eb2da26a83044a36c70c
google-driverole-gate-writesleast-privilegeingresssoc2gdpr-ccpa
What this policy does
Direction: ingress (tool_pre_invoke)
Default: deny; reads pass through, writes require group membership
Package: google_drive.ingress.role_gate_writes
What it does
Baseline least-privilege policy for Google Drive MCP traffic. Read-class tools
(search, list, metadata, content reads, downloads) pass through freely for every
caller. Every write-class tool on the covered suffix list — file/folder
creation, uploads, doc/sheet edits, moves, renames, copies, and comments — is
denied unless the caller's IdP-issued groups claim contains drive-writers.
This is a blocklist of known write suffixes: a write tool whose name is not on
the list (see Known limitations) is not classified as a write and passes through,
so pair this with a default-deny-unknown-tools policy for a strict posture.
A caller with a missing subject, missing claims, or missing/empty groups
claim fails closed: no group, no write. The check runs at ingress, so a denied
write never reaches the Drive MCP server and never creates, modifies, or comments
on anything.
Why gate writes: Drive writes let an agent plant prompt-injection payloads in documents other agents and users will later read, and stage data into broadly shared folders as a pre-exfiltration step. Comments additionally notify collaborators — including external ones — so even "small" writes are externally visible actions.
Compliance alignment
- SOC 2 CC6.1 — supports logical access security over protected assets by restricting Drive modification to an authorized group on the agent channel; CC6.3 — supports role-based access and least privilege: write access is tied to live IdP group membership, read access is the default posture.
- HIPAA §164.502(b)/§164.514(d) — supports minimum-necessary, role-based limits on a store that routinely holds PHI exports; §164.308(a)(4) — information access management; §164.312(a)(1) — access control enforced per call against the caller's identity.
- GDPR Art. 25 — supports data protection by design/default on the agent channel (write capability off by default); Art. 29 / 32(4) — supports processing only on the controller's instructions: unauthorized principals cannot direct the agent to alter Drive data.
Tool name matching
The DTwo gateway prefixes tool names with the configured MCP server name
(e.g. gdrive-mcp-create_file), so this policy matches case-insensitive
suffixes to stay portable across deployments. Classification reads both the
PARC input.resource.name field and its co-populated legacy alias
input.payload.name: a call is write-class if either ends with a covered
suffix, so the gate still fires if one field is absent. Write-class suffixes
covered:
- Google official Drive MCP server / Claude connector:
create_file,copy_file(the official server exposes no delete/move/rename/permission tools). - isaacphi/mcp-gdrive:
gsheets_update_cell. - piotr-agier/google-drive-mcp:
createtextfile,updatetextfile,uploadfile,createfolder,moveitem,renameitem,copyfile,creategoogledoc,updategoogledoc,inserttext,appendspreadsheetrows,updategooglesheet,addcomment,replytocomment.
Anything not on the write list — including all read tools and unknown tools — passes through. Verify the exact names your gateway sends with the dump-input debug technique before relying on this in production, and add suffixes here if your Drive server exposes additional write tools.
Identity shape
The policy reads input.subject.claims.groups and expects an array of group
name strings (the common IdP shape). Membership is checked with an exact,
case-sensitive string match against drive-writers. All lookups use
object.get chains, so a missing subject, claims, or groups resolves to
an empty list and the write is denied. The membership check additionally
requires groups to be a JSON array (is_array): a groups value that
arrives as a single string or as an object map fails the array check and is
denied (fail closed), so it cannot grant a write by value collision.
Argument shape
This policy decides on the tool name and the caller's identity only; it does not inspect tool arguments, so it is insensitive to argument-name differences across Drive server implementations.
Examples
Allowed — read tool, no identity needed
{
"input": {
"action": "tool_pre_invoke",
"resource": { "name": "gdrive-mcp-search_files", "type": "tool" },
"payload": { "name": "gdrive-mcp-search_files", "args": { "query": "quarterly report" } }
}
}
allow = true, no reason.
Allowed — write tool, caller is in drive-writers
{
"input": {
"action": "tool_pre_invoke",
"subject": { "sub": "google-apps|ana@acme.com", "claims": { "groups": ["drive-writers"] } },
"resource": { "name": "gdrive-mcp-create_file", "type": "tool" },
"payload": { "name": "gdrive-mcp-create_file", "args": { "name": "notes.txt" } }
}
}
allow = true, no reason.
Denied — write tool, caller has no groups claim
{
"input": {
"action": "tool_pre_invoke",
"subject": { "sub": "google-apps|bob@acme.com", "claims": { "email": "bob@acme.com" } },
"resource": { "name": "gdrive-mcp-create_file", "type": "tool" },
"payload": { "name": "gdrive-mcp-create_file", "args": { "name": "notes.txt" } }
}
}
allow = false, reason = "Google Drive write tools are restricted to members of the 'drive-writers' group. ...".
Composition
This policy is single-purpose: it gates write-class tools by group. Useful companions:
freeze-destructive-ops— handles the destructive tier (deleteItem,deleteSheet,deleteRange, ...); this policy deliberately does not cover deletes.- An egress PII/secret redaction policy on Drive content-returning tools
(
read_file_content,download_file_content,gdrive_read_file), since bulk read is Drive's primary exfiltration risk.
Known limitations
- Group name is an import-time placeholder. Replace
drive-writerswith your IdP's real group name (inauthorized_write_groupand the deny reason) when importing. The match is exact and case-sensitive. groupsmust be an array of strings under thegroupsclaim key. IdPs that emit the claim as a single space- or comma-separated string, as an object map, or under a namespaced key (e.g.https://acme.com/groups) will never match, so all writes are denied (fail closed) — a safe direction, but it locks out legitimate writers until you adjust. If your IdP uses a namespaced or differently named group claim, change theobject.get(claims, "groups", [])key incaller_may_writeto match. Confirm your IdP's claim shape and key withdtwo-list-claimsor the dump-input technique.- Official-server argument field names are unverified. Google's reference
does not publish per-tool parameter schemas; this policy avoids argument
inspection for that reason, but companions that inspect Drive arguments should
verify shapes via
tools/listfirst. - Claude connector write-tool suffixes are unverified. The landscape note
flags that the Anthropic-hosted "Google Drive" connector's tool suffixes are
not verified against official Anthropic docs and diverge between write-ups
(e.g.
get_metadatavsget_file_metadata). This policy assumes the connector's create tool matches the Google-server suffixcreate_file; if it instead ships the write under a different suffix, that write passes through ungated (the same blocklist residual described below). Confirm the connector's live write-tool names withtools/listand add any divergent suffix towrite_suffixes. - Generic suffixes can over-match on shared pipelines. Suffixes like
uploadfile,copyfile, oraddcommentmay also match similarly named tools from non-Drive MCP servers attached to the same pipeline, gating them too. That failure mode is deny-for-non-members (safe direction), but scope the pipeline or tighten the suffixes if it bites. - Destructive tools are out of scope. Deletes are governed by the companion
freeze-destructive-opspolicy, not here. - Blocklist residual — unlisted write tools pass through ungated. Enforcement
is a curated allowlist of write suffixes; any write tool whose name is not on
that list is treated as a read and passes through for every caller. Concrete
residuals on real servers: the multi-product
piotr-agier/google-drive-mcpserver also exposes Slides content writes and calendar writes (createCalendarEvent,updateCalendarEvent) that this Drive-scoped policy does not gate, and any newly added, renamed, or preview upstream write tool is ungated until its suffix is added here. This is the standard blocklist weakness and the reason the coverage matrix pairs PF-12 with PF-28 (default-deny-unknown-tools): attach a default-deny-unknown-tools companion (and route calendar/Slides writes through their own app policies) if you need a guarantee that no unrecognized write reaches Drive. Verify your gateway's live tool inventory withtools/listand extendwrite_suffixesaccordingly. - A call with no resolvable tool name at all passes through. Classification
reads both
input.resource.nameand its legacy aliasinput.payload.name; a call is only unclassifiable (and therefore allowed) when both fields are absent or empty — fail-open on classification, not on identity. The gateway populates both for every dispatched tool call, so this is not reachable by a normal caller, and a companion default-deny-unknown-tools policy also closes it.
Compliance note. This policy supports alignment with the cited framework controls on the MCP path only. No policy or bundle makes an organization compliant with any framework; web-UI, native-API, and in-app access are outside the gateway's reach by design. Validate against your own compliance program before relying on it.
Policy source (Rego)
package google_drive.ingress.role_gate_writes
# Deny-by-default: only the explicit allow rules below permit the request.
default allow := false
# IdP group whose members may call Google Drive write tools.
# PLACEHOLDER — replace with your IdP's real group name at import time
# (and update the deny reason below to match).
authorized_write_group := "drive-writers"
# Write-class tool suffixes across the Drive MCP servers in real use.
# The gateway prefixes tool names with the configured server name, so we
# match case-insensitive suffixes for portability. Read-class tools are
# intentionally absent — anything not listed here passes through.
write_suffixes := [
# Google official Drive MCP server / Claude connector
"create_file",
"copy_file",
# isaacphi/mcp-gdrive
"gsheets_update_cell",
# piotr-agier/google-drive-mcp (camelCase upstream; compared lowercased)
"createtextfile",
"updatetextfile",
"uploadfile",
"createfolder",
"moveitem",
"renameitem",
"copyfile",
"creategoogledoc",
"updategoogledoc",
"inserttext",
"appendspreadsheetrows",
"updategooglesheet",
"addcomment",
"replytocomment",
]
# Candidate tool-name fields, lowercased. `resource.name` is the PARC field;
# `payload.name` is its co-populated legacy alias (both are set on tool hooks).
# Classifying on either means a write is still caught if one field is absent —
# this only ever moves a call toward the write class (deny for non-members),
# never the reverse, so it cannot introduce a new allow.
tool_name_candidates contains lower(n) if {
n := object.get(object.get(input, "resource", {}), "name", "")
n != ""
}
tool_name_candidates contains lower(n) if {
n := object.get(object.get(input, "payload", {}), "name", "")
n != ""
}
# A tool call is write-class when any candidate name ends with a listed suffix.
is_drive_write_tool if {
some name in tool_name_candidates
some suffix in write_suffixes
endswith(name, suffix)
}
# Caller is authorized to write: the IdP-issued `groups` claim contains the
# authorized group. object.get chains make missing subject/claims/groups
# resolve to an empty list, so absent identity fails closed (no group, no write).
caller_may_write if {
claims := object.get(object.get(input, "subject", {}), "claims", {})
groups := object.get(claims, "groups", [])
# Require the documented array-of-strings shape. Without this guard a
# `groups` object map whose *value* equals the group name (e.g.
# {"role": "drive-writers"}) would satisfy `some group in groups`
# (which iterates object values) and grant the write. is_array makes
# every non-array shape (single string, object map) fail closed, matching
# the Identity-shape contract documented above.
is_array(groups)
some group in groups
group == authorized_write_group
}
# Read-class and unknown tools pass through freely.
allow if {
not is_drive_write_tool
}
# Write-class tools require membership in the authorized group.
allow if {
is_drive_write_tool
caller_may_write
}
reasons contains "Google Drive write tools are restricted to members of the 'drive-writers' group. Ask a user who is in that group to make this change for you, or request 'drive-writers' membership from your identity administrator. If this tool call was wrongly classified as a write, ask your InfoSec team to review this policy's suffix list." if {
is_drive_write_tool
not caller_may_write
}
reason := joined if {
count(reasons) > 0
reason_list := sort([r | some r in reasons])
joined := concat("; ", reason_list)
} Canonical source: policy.md on GitHub · raw · raw on this site (.md)
Related policies
Airtable: Redact PII in Record Reads
Scans the responses of the Airtable record-read tools — the calls that return row fields values — and rewrites high-confidence PII shapes to a fixed…
Asana: Redact PII in Task & Comment Reads
On the Asana MCP read path, this transform scans the free-text business fields that ride back in task, comment/story, and status-update responses — notes,…
BigQuery: Redact PII in Query Results
Scans the content returned by BigQuery's result-returning tools and rewrites high-confidence PII shapes to fixed, non-recoverable redaction tokens before the…
Block Agent Email to External Recipients
Blocks agent-initiated Microsoft 365 email sends when any recipient address falls outside a corporate-domain allowlist.
Block BigQuery Exfiltration and Cross-Project Writes
Inspects the raw GoogleSQL string carried by BigQuery SQL tools and denies any statement that moves data out of the tenant's own project — even when the call…
bigqueryguard-warehouse-exportingresssqlexfiltrationsoc2pci-dssgdpr-ccpa
Block Bulk Export & External Staging (Snowflake)
Blocks Snowflake SQL-execution tool calls whose query text moves whole tables off the Snowflake perimeter — bulk export to cloud storage or a stage, and…
snowflakeguard-warehouse-sqlexportexfiltrationingresssoc2pci-dssgdpr-ccpa