Security

MCP lets the model choose real actions. Trusting “whatever server connected” is the usual incident. This chapter is a defensive checklist: approval, sandboxing, allowlists, and supply chain. It does not walk through attacks. For the long official text see Security Best Practices and Authorization.


Default stance

PrinciplePractice
Trusted servers onlyOfficial org, a vendor you already use, an internal repo you reviewed
Least-privilege tokensRead over write; expiry; split by repo or project
Humans approve toolsWrites, mail, payments, production changes: ask first
No secrets in resourcesResources are often pasted whole into context
No secrets in gitYou may commit the command in .cursor/mcp.json, not ghp_ / sk-

Treat MCP as a plugin process plus a network identity. You are not approving “a JSON blob”; you are approving code that will run as you (or call APIs as you).


Tool approval (human in the loop)

A host should show the tool name, arguments, and which server. Habits that help:

  1. Read the arguments: is that path the folder you meant? is that URL yours?
  2. Separate read-only tools from side-effecting ones; keep the latter on ask every time
  3. Do not permanently Allow an entire server just to click less, unless every tool is harmless and read-only
  4. After the task, take back any permission you widened temporarily

OpenCode, Codex, and Claude Code each have their own permission / allowlist syntax—see those courses. Here the rule is: approval is a feature, not friction.


Sandbox and files

A local server can read every path you handed it.

  • Filesystem: root at allowed-notes, not the home directory
  • Your own server: after Path.resolve(), reject paths that leave the allowed root (.. included)
  • Browser / Playwright: a dedicated profile; do not reuse one already logged into production
  • Remote HTTP: bind 127.0.0.1 first; anything on the public internet needs auth (official docs recommend OAuth)

On stdio, stdout is the wire. Logs go to stderr. Never print a token into a string a host might treat as context.


Allowlists (host side)

If anyone on the team can add MCP, the platform should decide which servers may run, instead of hoping everyone finished the README.

Codex-style idea (confirm field names in the product):

allowed_mcp_servers = ["workshop", "filesystem"]

Practical notes:

  • Production agents: an explicit list, no surprise npx packages
  • Split user vs project config; project files may be in git, tokens stay user-local
  • Allowlist remote URLs too, so a chat cannot steer the host at an unknown origin

Supply chain

npx -y @someone/mcp-whatever is the same class of decision as pip install: you are running third-party code.

PracticeWhy
Pin versionsAvoid a fresh latest on every -y
Check the publisher@modelcontextprotocol/... versus look-alike scopes
Install fewer serversEach one widens the tool surface
Internal mirrorsEnterprises pin allowed packages in a private registry
Review upgradesLockfile diffs are dependency reviews

Remote MCP also inherits OAuth proxy mistakes: a confusing consent screen or a reused client id can make a user think they authorized A while a token is used elsewhere. Defense: read the authorization host and scopes, disable registration you do not need, validate the issuer per the official Authorization spec. Do not skip the vendor consent step.


Data in resources and prompts

  • Design a resource as docs this host is allowed to see, not as a debug dump
  • When a secret is required: the tool calls the API and returns redacted business fields
  • Do not concatenate untrusted HTML into a prompt template and treat it as instructions

Deprecating Sampling also shrinks the “server drives the host’s model” surface. New projects should not implement Sampling.


Short list before you share a server

  1. List every tool in Inspector; drop experimental writes or prefix them dangerous_*
  2. Tokens live in the environment and you can explain their scopes
  3. The host asks on writes; it does not silently allow
  4. Logs and resources contain no secrets
  5. The README states the allowed root and the intended hosts

Next

评论