dtwo Policy Store

Guard Drive ACL Reconnaissance

Denies Google Drive get file permissions tool calls unless the caller's IdP groups claim contains infosec. All other tool calls pass through unchanged.

Direction
ingress
Rego package
google_drive.ingress.guard_acl_recon
App
google-drive
Bundle
soc2
Published
Minimum gateway
1.0.0b24
Schema version
1.0.0
Checksum
sha256:e0aaeddeff19e80205a00317ffe4a616e0a4c04670c5ed05d5ce8915af54bf64

google-driveguard-share-linksaclsharingingresssoc2

What this policy does

Direction: ingress (tool_pre_invoke) Default: deny on match, allow otherwise Package: google_drive.ingress.guard_acl_recon

What it does

Denies Google Drive get_file_permissions tool calls unless the caller's IdP groups claim contains infosec. All other tool calls pass through unchanged.

Agents rarely need ACL data, and the permissions response is ideal exfiltration-targeting reconnaissance: it enumerates collaborator email addresses (PII) plus a map of exactly which files are shared externally. This policy is the Google Drive instantiation of the guard-share-links family (PF-05): no current Drive MCP server exposes a permissions-write (sharing) tool, so on Drive the family gates the read-side share surface — ACL reconnaissance — instead of link creation.

The check runs at ingress, before the call reaches the Drive MCP server, so denied callers never receive the ACL data.

Compliance alignment

  • SOC 2 CC6.7 — supports the restriction on transmission/movement/removal of information: sharing-state maps and collaborator rosters stay off the agent channel except for the InfoSec group.
  • SOC 2 P6.1 — supports controls over personal-information disclosure to third parties: collaborator email addresses (PI) are not enumerable by arbitrary agent sessions.
  • GDPR Art. 5(1)(f) / Art. 32 — supports security of processing by keeping collaborator email addresses and external-sharing state (personal data) off the agent channel except for the InfoSec group; Art. 5(1)(c) — supports data minimisation of the personal data returned in ACL responses. CPRA §1798.121 — supports limiting disclosure of contact identifiers on the agent channel.

Tool name matching

The policy matches case-insensitively on the bare *permissions suffix. That single suffix catches every ACL-read shape seen or plausible on Drive:

  • *get_file_permissions — the verified tool name on the Google official Drive MCP server (https://drivemcp.googleapis.com/mcp/v1), and the reported name on the Anthropic-hosted Claude connector.
  • *get_permissions — the shorter variant the Claude connector may report (its suffixes are known to diverge from the Google server names, e.g. get_metadata vs get_file_metadata).
  • *list_permissions / *list_file_permissions / *listPermissions — the underlying Drive REST verb is permissions.list, so a community or future connector could just as plausibly expose the read under a list-style name. These are unverified alternate names, but the bare-permissions suffix denies them anyway, so an alternate verb can't sneak past the gate.

No benign Drive tool across the surveyed servers ends in permissions, so gating the bare suffix closes the connector-name gap without over-matching. The DTwo gateway prefixes tool names with the configured MCP server name (e.g. google-drive-mcp-get_file_permissions), and that prefix is not standardized — suffix matching keeps the policy portable. Verify the exact name your gateway sends with the dump-input debug technique before relying on this in production. If your Drive MCP server exposes ACL reads under a name that does not end in permissions, add its suffix to acl_read_suffixes in policy.md.

Identity gating

The exemption reads input.subject.claims.groups and requires a group whose lowercased value equals infosec. The check fails closed: if subject, claims, or groups is missing — or groups is not an array — the caller is not exempt and the call is denied.

Argument shape

The policy decides on the tool name and the caller's identity only; it does not inspect arguments. Google does not publish per-tool parameter schemas for the Drive MCP server — the documented workflow implies get_file_permissions takes a file ID, but the exact field name is unverified and irrelevant to this policy's logic.

Examples

Allowed — unrelated Drive tool

{
  "input": {
    "action": "tool_pre_invoke",
    "resource": { "name": "google-drive-mcp-search_files", "type": "tool" },
    "payload": {
      "name": "google-drive-mcp-search_files",
      "args": { "query": "fullText contains 'roadmap'" }
    }
  }
}

allow = true, no reason.

Allowed — InfoSec caller reading ACLs

{
  "input": {
    "action": "tool_pre_invoke",
    "resource": { "name": "google-drive-mcp-get_file_permissions", "type": "tool" },
    "subject": {
      "sub": "google-apps|sec@example.com",
      "claims": { "groups": ["engineering", "infosec"] }
    },
    "payload": {
      "name": "google-drive-mcp-get_file_permissions",
      "args": { "fileId": "1AbC..." }
    }
  }
}

allow = true, no reason.

Denied — caller outside the infosec group

{
  "input": {
    "action": "tool_pre_invoke",
    "resource": { "name": "google-drive-mcp-get_file_permissions", "type": "tool" },
    "subject": {
      "sub": "google-apps|dev@example.com",
      "claims": { "groups": ["engineering"] }
    },
    "payload": {
      "name": "google-drive-mcp-get_file_permissions",
      "args": { "fileId": "1AbC..." }
    }
  }
}

allow = false, reason = "Reading Drive file permissions is restricted (...)".

Composition

This policy is single-purpose. Useful companions for a least-privilege Drive pipeline:

  • An egress PII/secret redaction policy on content-returning tools (read_file_content, download_file_content) so file bodies are also covered (PF-02). Extend it to get_file_metadata if your MCP server returns owner/sharing fields (see Known limitations) — that redacts the metadata-recon residual this ingress policy cannot reach.
  • An ingress bulk-export cap on search_files page sizes to slow mass enumeration (PF-08).
  • A write-gating policy on create_file / copy_file by IdP group (PF-12).

Known limitations

  • Group names are placeholders — replace infosec with your IdP's group name at import time. The exemption only works if your IdP actually emits a groups array claim in the access token; many IdPs (including Auth0) require explicit configuration to do so. Until then the policy denies get_file_permissions for everyone — safe, but with no break-glass path.
  • Argument shape unverified. Google publishes no per-tool parameter schemas for the Drive MCP server; the assumed file-ID input is not relied on by this policy.
  • Connector tool-name divergence. Third-party write-ups of the Claude connector report slightly divergent suffixes for some tools (e.g. get_metadata vs get_file_metadata); the connector's names are not verified against official Anthropic docs. To stay ahead of this the policy gates the bare permissions suffix rather than a fixed get_-prefixed name, so get_file_permissions, get_permissions, and any list-style variant (list_permissions / list_file_permissions / listPermissions, all unverified but plausible given the permissions.list REST verb) are all denied. The only residual name gap is an ACL-read tool that does not end in permissions at all; confirm the exact name with the dump-input technique and add its suffix to acl_read_suffixes in policy.md if your traffic shows such a variant.
  • Read-side only. No current Drive MCP server exposes permission-editing or share-link-creation tools. If Google later ships them, this policy must be extended (or a companion added) to deny anonymous/public link creation per the PF-05 family spec — today that exfil path only exists via the web UI, outside the gateway's reach.
  • String-valued groups claims deny. If your IdP emits groups as a single string rather than an array, the exemption never fires (fail closed). Normalize the claim at the IdP or adapt caller_is_acl_reviewer in policy.md.
  • Recon residual via file-resource projection (adjacent tools). This policy gates only tools whose name ends in permissions — the dedicated ACL-read surface. But the Google Drive file resource itself carries owners, sharingUser, shared, and (when the caller selects the field) a permissions[] array, and every tool that returns a file resource can project those fields — not just get_file_metadata but also search_files and list_recent_files (both back onto Drive files.list, which accepts the same fields selector). So a non-InfoSec caller can recover the same collaborator emails and external-share state this policy withholds by asking get_file_metadata, search_files, or list_recent_files for the sharing fields. Whether a given MCP server actually forwards a fields selector and includes those fields is unverified (Google publishes no per-tool response schema), so these tools are deliberately allowed here rather than blanket-denied — denying search_files outright is the job of a separate bulk-export/enumeration brake (PF-08), not this policy. Close this residual with an egress redaction/field-stripping companion on all file-resource-returning tools (get_file_metadata, search_files, list_recent_files; see Composition); do not treat this ingress policy alone as sealing off ACL reconnaissance.

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.guard_acl_recon

# Deny-by-default: only the explicit allow rules below permit the request.
default allow := false

# Placeholder group name — replace with your IdP's group at import time.
acl_reviewer_group := "infosec"

# Drive ACL-read tools we gate. `get_file_permissions` is the verified name on
# the Google official Drive MCP server; the Claude connector is reported to use
# a slightly shorter variant (`get_permissions`). The underlying Drive REST verb
# is `permissions.list`, so an alternate server could just as plausibly expose
# the read as `list_permissions` / `list_file_permissions` / `listPermissions`.
# Rather than enumerate every prefix (get_/list_/…), we gate the bare
# `permissions` suffix: no benign Drive tool across the surveyed servers
# (search_files, list_recent_files, get_file_metadata, read_file_content,
# download_file_content, create_file, copy_file, gdrive_*, gsheets_*, and the
# piotr-agier camelCase set) ends in `permissions`, so this carries no
# false-positive risk within this app while catching every casing/verb variant.
# The gateway prefixes tool names with the configured MCP server name (e.g.
# `google-drive-mcp-`), so we match on the suffix to stay portable. Verify the
# exact name on your gateway with the dump-input debug technique.
acl_read_suffixes := ["permissions"]

is_acl_read_tool if {
    name := lower(input.resource.name)
    some suffix in acl_read_suffixes
    endswith(name, suffix)
}

# Allow any tool that isn't a Drive ACL read.
allow if {
    not is_acl_read_tool
}

# Allow ACL reads only for members of the reviewer group.
allow if {
    is_acl_read_tool
    caller_is_acl_reviewer
}

# Fail closed: missing subject, claims, or groups — or a non-array groups
# claim — means the caller is not exempt.
caller_is_acl_reviewer if {
    claims := object.get(object.get(input, "subject", {}), "claims", {})
    groups := object.get(claims, "groups", [])
    is_array(groups)
    some group in groups
    lower(group) == acl_reviewer_group
}

reasons contains "Reading Drive file permissions is restricted: the response enumerates collaborator email addresses and which files are shared externally. Sharing-state review is an admin task — ask your Drive administrator to review the file's sharing settings, or ask your InfoSec team to add you to the infosec group if your role requires ACL access." if {
    is_acl_read_tool
    not caller_is_acl_reviewer
}

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)

Used in these guides