FlawOpen
● AI & Local Runtime

MCP Security: Threat Boundaries for Local Tools

Understand how MCP host, client, and server trust boundaries can expose data, and how to constrain local tools, permissions, and user consent. MCP does not itself grant every server filesystem access: exposure depends on the server’s configured capabilities, process privileges, host behavior, and user approval.

💡 Plain English Explainer (ELI5)

An MCP client is like a receptionist connecting an AI application to a specialist service. The connection does not make every file available automatically: the server can access what its process and configuration permit. But if you install a local server with broad file or command permissions, and the host passes untrusted content to a model that can call its tools, a mistaken or manipulated tool choice can expose data within that granted scope. MCP’s maintainers classify configured STDIO command execution and intended server capabilities as expected behavior; a real vulnerability requires crossing an access boundary the implementation promised to enforce. MCP Security Policy and Trust Model; MCP Security Best Practices.

Core Concepts & Key Terms

Host, Client, Server
The host is the AI application, the client is its protocol connector, and the server provides tools or resources. The protocol connection is not itself an operating-system sandbox.
STDIO transport
The host launches a configured local server process and exchanges protocol messages over standard input and output. The process normally has the privileges of its execution environment.
Tool scope
The specific operations, paths, accounts, and network destinations that a server can reach. Limit this at both the application layer and the operating-system boundary.
Confused deputy
A privileged service uses its own authority for a request without correctly binding the operation to the caller’s authorization. MCP guidance documents this risk in authorization flows.

Step-by-Step Attack Flow

Step 1

1. Untrusted data enters the host

A user asks an AI application to summarize an issue, email, or repository. That content may include instructions, but it remains untrusted data; prompt injection is a threat-model condition, not proof of an MCP protocol vulnerability.

Step 2

2. The model selects an available tool

The host presents tools from connected servers. The model may choose a tool based on its interpretation of the task; the MCP Security Policy treats unexpected model-driven tool choice as an application-control issue, not a protocol flaw.

Step 3

3. The server applies its actual authority

A local server performs its documented operation under the permissions of its process and configuration. If a filesystem tool is scoped to a project, that is its intended boundary; if it is granted a wider scope, those wider capabilities are deployment risk.

Step 4

4. Data reaches the model or another tool

The returned content can influence later model steps. Exposure occurs only if the server can read the data and the host or an additional permitted tool lets it leave the intended boundary. The current specification calls for explicit user consent before invoking any tool; add stronger confirmation for high-impact actions. See the official MCP security attack flows and mitigations.

Source Code: Flaw vs. Secure Implementation

OVERLY BROAD IMPLEMENTATION
// RISKY: resolves a model-supplied path but never confines it to the workspace.
import * as fs from "node:fs/promises";
import * as path from "node:path";

async function readWorkspaceFile(inputPath: string) {
  const target = path.resolve(WORKSPACE_ROOT, inputPath);
  return fs.readFile(target, "utf8");
}
HARDENED IMPLEMENTATION
// Defense in depth: canonicalize, check the boundary, reject final symlinks,
// and run the process with OS-level read-only access to only this workspace.
import * as fs from "node:fs/promises";
import { constants } from "node:fs";
import * as path from "node:path";

const workspaceSetting = process.env.MCP_WORKSPACE_DIR;
if (!workspaceSetting) throw new Error("MCP_WORKSPACE_DIR is required");
const root = await fs.realpath(workspaceSetting);
const noFollow = constants.O_NOFOLLOW;
if (noFollow === undefined) {
  throw new Error("Use an OS sandbox on platforms without O_NOFOLLOW");
}

async function readWorkspaceFile(inputPath: string) {
  if (path.isAbsolute(inputPath)) throw new Error("Absolute paths are not allowed");
  const candidate = path.resolve(root, inputPath);
  const relative = path.relative(root, candidate);
  if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
    throw new Error("Path escapes the workspace");
  }

  const canonical = await fs.realpath(candidate);
  const canonicalRelative = path.relative(root, canonical);
  if (canonicalRelative === ".." || canonicalRelative.startsWith(`..${path.sep}`) || path.isAbsolute(canonicalRelative)) {
    throw new Error("Resolved path escapes the workspace");
  }

  const handle = await fs.open(canonical, constants.O_RDONLY | noFollow);
  try {
    return await handle.readFile("utf8");
  } finally {
    await handle.close();
  }
}

Engineering Hardening Checklist

← Browse Full Security Directory Explore Reference Blueprints →

Primary sources: MCP Security Policy and Trust Model; MCP Security Best Practices; MCP Specification 2026-07-28: Security and Trust & Safety.

See also AI Agent Security: MCP & Prompt Injection — FlawOpen AI Agent Tool Security: Least Privilege and Isolation Claude Code MemoryTrap: AI Memory Poisoning AI Agent Sandboxing: Containers, gVisor & MicroVMs AI Agent Tool Scoping: Least Privilege & Auth