MCP Security Best Practices, Sandboxing & Secret Management Guide
Comprehensive security guide for Model Context Protocol deployments: credential isolation, indirect prompt injection defense, least-privilege token scoping, container sandboxing, and stdio process auditing.
#1. Threat Modeling for Autonomous LLM Tool Execution
Equipping AI coding assistants with tool execution capabilities introduces distinct security considerations that traditional web applications do not face. The primary threat vectors include:
• Indirect Prompt Injection: Malicious text contained inside third-party resources (e.g., issue descriptions, web pages, or database records) designed to hijack the LLM's instructions and trigger unauthorized tool calls.
• Unintended State Mutation: Accidental modification or deletion of production data caused by model hallucinations or ambiguous prompts.
• Credential Exfiltration: Attempts to coax language models into printing secret environment variables or configuration files into chat transcripts.
Never rely on language model prompt adherence alone for security. Enforce structural permission boundaries in code, network isolation, and database role permissions.
#2. MCP Attack Surface & Defense-in-Depth Architecture
A robust MCP security posture enforces multiple layers of structural defense. Security cannot depend solely on the language model's ability to resist adversarial prompts.
The following threat matrix diagram illustrates how layered defenses prevent system compromise even when an adversarial prompt injection succeeds in hijacking model output:
+--------------------------------------------------------------------+ | MCP Attack Surface & Defense-in-Depth Architecture | +--------------------------------------------------------------------+ | [ Attacker Vector ] [ Multi-Layer Defense Guardrails ]| | | | Malicious Web Page / Data | | | | | v | | +-----------------------+ | | | Indirect Prompt | ----> Layer 1: Prompt Context Boundary | | | Injection Payload | Separates instructions from data | | +-----------------------+ | | | | | v | | +-----------------------+ | | | Attempted Destructive | ----> Layer 2: Human-in-the-Loop Gate | | | Tool Call (DROP TABLE)| Client displays confirmation UI | | +-----------------------+ | | | | | v | | +-----------------------+ | | | Subprocess Execution | ----> Layer 3: Least-Privilege Role | | | In Local Stdio Pipe | DB user has SELECT ONLY | | +-----------------------+ Container is --read-only | | | | | v | | [ Unauthorized Mutation BLOCKED by Database Permission Denied ] | +--------------------------------------------------------------------+
#3. Secret Isolation & Credential Management Best Practices
Authentication credentials should follow the principle of strict local isolation:
1. Local Storage Only: Store API tokens and database connection strings exclusively within your local workstation configuration files (claude_desktop_config.json, .cursor/mcp.json) or operating system secret stores.
2. Never Hardcode Secrets in Repositories: Add configuration paths containing secrets to .gitignore and run pre-commit hooks (such as gitleaks or trufflehog) to prevent accidental Git commits.
3. Principle of Least Privilege: Whenever your workflow only requires querying data, generate read-only API keys or database roles (e.g. granting only SELECT privileges in PostgreSQL).
#4. Database Hardening: Creating Least-Privilege PostgreSQL Roles
When connecting MCP servers to production or staging databases, NEVER configure connection strings with superuser or administrative credentials. Instead, create a dedicated read-only role with strict query timeouts and schema restrictions:
The following SQL configuration creates a hardened database role specifically tailored for AI assistant querying:
-- 1. Create dedicated read-only role for AI assistant CREATE ROLE mcp_readonly WITH LOGIN PASSWORD 'secure_generated_pass'; -- 2. Grant connection and read-only schema usage GRANT CONNECT ON DATABASE production_db TO mcp_readonly; GRANT USAGE ON SCHEMA public TO mcp_readonly; GRANT SELECT ON ALL TABLES IN SCHEMA public TO mcp_readonly; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO mcp_readonly; -- 3. Restrict execution timeouts to prevent resource exhaustion ALTER ROLE mcp_readonly SET statement_timeout = '5000ms'; ALTER ROLE mcp_readonly SET idle_in_transaction_session_timeout = '10000ms';
#5. Zero-Downtime Token Rotation Protocol
In production enterprise environments, establish a standardized protocol for rotating credentials used by AI assistants:
1. Provision Secondary Key: Generate a new API token with identical permissions in your service provider's developer console.
2. Update Client Config: Update the env dictionary inside your MCP client configuration file.
3. Validate Connection: Execute a test query in Claude Desktop or Cursor to confirm the handshake succeeds with the new credential.
4. Decommission Stale Key: Revoke the old token in your provider console to eliminate stale credential exposure.
{
"mcpServers": {
"github-enterprise": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-github"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_newly_rotated_token_v2",
"GITHUB_API_URL": "https://github.enterprise.corp/api/v3"
}
}
}
}#6. Human-in-the-Loop & Destructive Action Safeguards
Client applications implement human-in-the-loop validation barriers before executing potentially dangerous tool operations:
• Explicit Approval Prompts: In Claude Desktop and Cursor Agent mode, mutating operations (such as file writes, Git pushes, or database updates) present a visual confirmation dialog showing exact argument payloads before execution.
• Sandboxed Execution: Stdio servers execute in local isolated child processes, ensuring that unauthorized filesystem access or shell commands are blocked by OS-level user permission boundaries.
• Audit Logging: Retain stderr telemetry logs to maintain an auditable timeline of every tool invoked during automated coding sessions.
#Frequently Asked Questions
By default, a local stdio process runs with the OS permissions of your user account. To strictly restrict filesystem access, use filesystem-specific MCP servers that explicitly accept an allowed directory whitelist (e.g., npx @modelcontextprotocol/server-filesystem /path/to/project), or run the server inside a Docker container.