---
title: "Security and Visibility"
description: "How the MCP gateway protects your data: permissions checked on every call, other spaces invisible, no network access for tools, deletion reversible."
---

# Security and Visibility

Giving an agent direct access to the storage engine means assembling the "lethal trifecta": private data × untrusted note content × an outbound channel. Any one axis is harmless on its own, but together they let an injection inside a note walk your data out the door. The Notarium MCP gateway breaks **every** axis by construction, not by configuration. This isn't a convenience wrapper — it's a trust boundary.

## The trifecta broken by construction

- **No outbound channel.** Every tool ships with `openWorldHint:false` — no tool reaches the network. There's no moving or copying between spaces, so internal data leakage is closed off too. There's nowhere to walk data to.
- **Untrusted content defused.** The server's instructions are static and **never** mixed with note content: nothing from a note is folded into tool descriptions or into the server `instructions`. That way an injection in a note's body never becomes a command to the agent.
- **Destructive actions are always reversible.** `delete_note` sends a note to the trash; restoring it and purging it for good are done by a **human**, not the agent. That's the "agent does nothing irreversible" line.

## Permission checks on every call

Permissions are checked twice. First, `tools/list` is filtered by the token's ceiling — a `read` token simply doesn't see the writing tools. Then every `tools/call` additionally checks access to the specific space (`can(principal, action, {space})`). The permission formula is `effective = scopes(token) ∩ grants(principal)`: the token's scope (its ceiling of actions) intersected with live membership in spaces. Revoking a grant narrows the token instantly.

Management actions (issuing tokens, managing members) sit **above** `write` — a leaked `write`-level token can't issue a new token or grant access.

## Denial = 404, not 403

An access denial is returned as a **404** ("no such thing"), not a 403 ("not allowed"). That way the response codes can't be used to enumerate which notes or spaces exist beyond the permissions you've been granted. Another user's space is simply unreachable and indistinguishable from one that doesn't exist.

```mermaid
flowchart TD
  call[tools/call] --> listed{tool within the<br/>token's ceiling?}
  listed -->|no| gone[tool absent from tools/list]
  listed -->|yes| acl{can principal,<br/>action, space?}
  acl -->|no| notfound[404 · anti-enumeration]
  acl -->|yes| exec[execute · provenance to the log]
```

## Defusing untrusted content

Everything that goes to the agent — title, snippet, content, frontmatter — is sanitized before it's sent: the angle brackets of pseudo-control tags (`<system>`, `<instructions>`, and the like) are defused. A note where someone typed in a "system instruction" reaches the agent as ordinary text, not as a command.

## Edit history is visible

Every edit records who made it — a specific person or agent — in the [edit history](/docs/concepts/versioning/). `get_note` and `recall` can return who edited a note: a human or an agent, and which one. An injection that passed through an agent stays visible and traceable.

> [!important] What this means in practice
> Even an agent fully compromised by a prompt is bounded by its token: it won't reach the network, won't reach another space, won't make an irreversible deletion, and won't grant itself permissions. The worst it can do is a reversible edit within its own permissions, with full provenance in the log.

## The boundary: not E2EE

Notarium **deliberately doesn't do** end-to-end encryption. A smart server — search, semantics, history, agents — needs access to plaintext. Privacy here is built on self-hosting and owning your files, not on E2EE. The gateway's threat model protects against a compromised **agent**, not against a compromised host, which you already trust with your files anyway.

## Next

- [Connecting an agent](/docs/agents/connect/) — tokens, permissions, and the OAuth facade.
- [Retrieval audit](/docs/agents/audit/) — observability into what the agent searched for.
- [Intent tools](/docs/agents/intent-tools/) — why the toolset is exactly this.
