Block Destructive and Export SQL on Notion Data Sources
Inspects Notion data-source query tool calls (notion-query-data-sources on the hosted server, query-data-source on the official local server) and denies any…
Inspects Notion data-source query tool calls (notion-query-data-sources on the hosted server, query-data-source on the official local server) and denies any…
Notion's hosted MCP server (notion-search) does not just search Notion pages — through Notion AI connectors it also searches connected Slack, Google Drive,…
Denies calls to the Notion member-directory tool (notion-get-users, matched by the -get-users suffix) unless the caller's IdP groups include an admin or IT…
notionfence-sensitive-scopesaccess-controlpiiingresssoc2gdpr-ccpa
Denies notion-update-page calls whose command argument is replace content — the one edge on Notion's hosted MCP server that overwrites a page's entire body…
Scans the responses of the Notion hosted MCP server's content-returning read tools and rewrites personally identifiable information to fixed redaction tokens…
Reusable DTwo policies for Notion MCP servers — principally Notion's hosted MCP server (https://mcp.notion.com/mcp), the official implementation that backs the Claude connector, plus the official local server and community servers where their tool names line up. The MCP surface is read tools (notion-search, notion-fetch, notion-query-data-sources running raw SQL, notion-get-users, notion-get-teams, notion-get-comments, meeting-notes queries) and write tools (create/update/move/duplicate pages, create/update databases, data sources, and views, and comments). Its risk profile is dominated by aggregation and silent irreversibility, not deletion: there is no explicit delete or trash tool, but notion-search reaches into connected Slack, Google Drive, and Jira content (bypassing those apps' own MCP governance), notion-get-users returns workspace member and guest emails, notion-query-data-sources runs SQL over databases that hold HR, finance, and CRM records, and notion-update-page with command: replace_content overwrites a page's entire body in one call — recoverable only through page history and invisible to the agent.
| Policy | Direction | Purpose | Framework bundles |
|---|---|---|---|
| constrain-connected-search | ingress | Deny notion-search calls scoped to connected external tools (Slack, Google Drive, Jira); native Notion searches and all other tools pass through. |
soc2, gdpr-ccpa, hipaa |
| fence-user-directory | ingress | Deny member-directory reads (notion-get-users) unless the caller's IdP groups include an admin or IT group. |
soc2, hipaa, gdpr-ccpa |
| freeze-content-overwrite | ingress | Deny notion-update-page calls with command: replace_content (silent full-page overwrite); additive edits and property updates pass through. |
sox, soc2, hipaa, gdpr-ccpa |
| guard-datasource-sql | ingress | Deny destructive, schema, or export SQL on Notion data-source queries; read-only SELECTs pass through. |
pci-dss, sox, gdpr-ccpa, soc2 |
| redact-pii-egress | egress | Redact emails, phone numbers, and other PII from Notion content-returning read responses (transform-only). | soc2, hipaa, gdpr-ccpa |
DTwo prefixes tool names with the MCP server name configured on the gateway. The hosted server bakes a notion- hyphenated prefix into every tool name, so a server registered as notion surfaces tools like notion.notion-search, notion.notion-update-page, and notion.notion-get-users. The policies in this directory match on the suffix (-search, -update-page, -get-users, -query-data-sources, etc.) so they stay portable across naming conventions — but you should always confirm the exact tool name your gateway sends using the dump-input debug technique before deploying.
Portability caveat: the official local server (makenotion/notion-mcp-server) uses un-prefixed REST-ish names (search, query-data-source), and the community servers diverge further — suekou/mcp-notion-server uses a notion_ underscore prefix, and awkoy/notion-mcp-server funnels every action through a notion_execute meta-tool that tool-name matching cannot fence. Where a policy covers a non-hosted server it says so; residual pass-throughs on those servers are recorded in each policy's Known limitations.
Most of these policies are single-purpose and require no IdP claims. The identity-gated ones read input.subject.claims.groups with placeholder group names: fence-user-directory grants the member directory to admin and it, and redact-pii-egress exempts hr and legal from redaction. Replace these with your own IdP group names at import time. Missing claims fail closed for grants (no group → not exempt / not cleared).
To add a Notion policy:
apps/notion/<policy-slug>/ with policy.md and a tests.yaml test file.apps: ["notion"] in the policy frontmatter, plus any industry / bundle slugs that apply.pnpm manifest from the repo root.See CONTRIBUTING.md for the full process.