Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 133 additions & 0 deletions docs/runbooks/securing-mcp-setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# Runbook: Securing an MCP / Connector Setup

*A worked audit of my own AI-assistant tool configuration, applying the
[MCP trust-boundary threat model](../threat-models/mcp-trust-boundaries.md) to a
live setup. The threat model is the theory; this is the same five boundaries as
a checklist that was actually run. Findings are real — including one that was
remediated during the audit itself, and the ones that required no action, which
is itself a finding.*

## 1. The setup under audit

Host: **Claude Desktop**, using platform-managed connectors. At audit time:

| Connector | State at audit start | Surface it grants |
|---|---|---|
| Google Drive | Connected | Read access to personal documents |
| Claude in Chrome | Connected | Agentic browsing — the model acts in a live browser session |
| Gmail | Connected → **disconnected during audit** | Read access to mail |
| Google Calendar | Connected → **disconnected during audit** | Read access to schedule |
| GitHub | Available, not connected | — |

Architecture note that shapes everything below: these are **OAuth-brokered,
platform-managed connectors**, not locally-run community MCP servers. The
classic worst finding of these audits — a personal access token sitting in
plaintext in a local JSON config — is structurally absent here, because no
local config holds credentials at all: authorization happens via OAuth consent,
and tokens are held platform-side. That is the vendor doing B3 (credential
custody) correctly on my behalf. The audit therefore concentrates where the
risk actually lives in this pattern: **scopes, surfaces, and the model
boundary.**

## 2. The audit — five boundaries, applied

### B1 · User ↔ Host — does the assistant act on more than I mean?
**Checked:** which connectors can take *actions* versus only *read*.
**Found:** Drive is a read surface; Chrome is an action surface (the model can
navigate, click, and submit in a real browser).
**Action:** treat the two differently — see B5 and the standing rules. Reading
my documents and acting in my browser are not the same trust decision, and the
audit's main outcome is refusing to blur them.

### B2 · Host ↔ Server — what third-party code am I trusting?
**Checked:** provenance of every connected integration.
**Found:** all connected surfaces are first-party (platform-built), not
community packages. The supply-chain exposure (LLM03) that dominates the threat
model's B2 — typosquatted servers, poisoned updates, unreviewed npm installs —
is **not present** because nothing third-party is installed. But the inventory
itself produced the audit's main remediation: **Gmail and Calendar were
connected with no active workflow consuming them** — surface granted, utility
zero.
**Action:** both disconnected during the audit; they return the day a workflow
needs them, not before. GitHub stays dark for the same reason. Least privilege
as "not connected" rather than "connected but carefully" — and where that
wasn't the standing state, the audit made it so.

### B3 · Server ↔ Downstream — where do credentials live, and how wide?
**Checked:** local filesystem for credential material; the Google account's
third-party access page for what the Drive consent actually granted.
**Found:** no tokens on disk (OAuth pattern, above). The Drive grant is
account-wide read — broader than the handful of folders I actually use with
the assistant.
**Action:** accepted, documented: Drive's consent model doesn't offer
folder-scoping on this integration, so the real choice is account-wide or
nothing. The compensating control is behavioral and reviewable — periodic
review of the grant (calendar reminder, quarterly, alongside the standing
review of all third-party app access), and disconnection if usage stops.
**This is the audit's honest gap:** the scope is wider than the need, the
narrowing control doesn't exist, and saying so beats pretending the OAuth
badge means least privilege.

### B4 · Server ↔ Server — can one surface's output steer another?
**Checked:** whether both connected surfaces coexist in the same conversations.
**Found:** they can — a session may both read Drive content and drive the
browser. Content from one becomes context that influences actions in the
other.
**Action:** covered by the B5 rule below; the cross-contamination case here
collapses into the tool-output rule because there are only two surfaces and
one of them is the action surface.

### B5 · Model ↔ Tool output — untrusted content re-entering the loop
**Checked:** which surface ingests content I don't control.
**Found:** the browser is the wide-open channel — every page visited is
third-party content entering the model's context, and the browser is
simultaneously the surface that *acts*. This is the threat model's
no-classic-analogue boundary, live in my own setup: a hostile page could
attempt instruction injection against the same session that can click.
**Action (the audit's main hardening):** standing rules of use rather than
configuration — because no configuration option closes B5:
1. **Sensitive-session isolation** — agentic browsing does not run in sessions
where Drive content or credentials-adjacent workflows are present.
2. **Irreversible actions get a human gate** — anything that submits,
purchases, sends, or deletes is confirmed by me, not auto-approved.
3. **Untrusted-site skepticism** — the browser surface is for known
destinations; letting the agent roam arbitrary search results is treated
as feeding untrusted input directly to the action loop.

## 3. Findings summary

| # | Finding | Severity | Disposition |
|---|---|---|---|
| 1 | No plaintext credentials anywhere on disk | — | OAuth pattern; the classic finding is structurally absent |
| 2 | No third-party/community servers installed | — | Supply-chain surface minimal; standing rule governs additions |
| 3 | Drive grant broader than actual use (account-wide read) | Low | Accepted + quarterly review; no narrower option exists on this integration |
| 4 | Browser surface = untrusted input feeding an action-capable loop (B5) | Medium | Behavioral rules 1–3; no configuration control exists for this boundary |
| 5 | **Gmail and Calendar connected but unused** — OAuth grants against the account's highest-sensitivity data (mail, schedule) with no workflow consuming them | Low–Medium | **Remediated — disconnected during the audit.** The orphaned-integration discipline applied at home: unused grants are attack surface with zero utility; the before/after is two fewer standing grants |

## 4. Standing rules (the part that outlives the audit)

- **Connect on demand, disconnect on disuse.** A connector nobody used this
quarter gets disconnected at the quarterly review.
- **New server = vendor onboarding.** Any future third-party MCP server gets
the B2 treatment before install: provenance, publisher, what scopes it asks
for, where its credentials would live. The threat model's mitigations table
is the checklist.
- **The action surface is special.** Anything that can *do* (browser today;
any write-capable connector tomorrow) inherits the three B5 rules
automatically.
- **Quarterly third-party access review** across the Google account — the
same review that covers every OAuth grant now explicitly includes AI
connectors.

## 5. Scope and limitations

- This audits **one person's setup at one point in time** — a workstation
pattern, not an enterprise MCP deployment. Fleet-scale controls (server
allowlisting via policy, centralized tool-call audit logs, per-agent
identity) are the threat model's mitigations table, not this runbook.
- The OAuth-connector pattern outsources B3 to the platform. That is a real
security benefit and a real dependency — this setup trusts the platform's
token custody, and says so.
- B5 has **no configuration fix** in any current host. The rules above are
behavioral controls, honestly labeled as such — which is the state of the
art, not a deficiency of this setup.
Loading