---
name: Guard Drive ACL Reconnaissance
tags:
  - google-drive
  - guard-share-links
  - acl
  - sharing
  - ingress
  - soc2
publishedAt: 2026-07-12
description: |
  # google-drive / guard-acl-recon

  **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

  ```jsonc
  {
    "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

  ```jsonc
  {
    "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

  ```jsonc
  {
    "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.
direction: ingress
apps:
  - google-drive
industries: []
bundles:
  - soc2
experimental: true
schemaVersion: 1.0.0
minimumGatewayVersion: 1.0.0b24
---

```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)
}
```
