Problem
MCP servers that connect to databases (Supabase, Postgres, etc.) often use overly permissive credentials. When an AI assistant has access to a database MCP, a single prompt can extract full table contents, sensitive user data, or schema information. This is especially dangerous with vibe-coded applications where the MCP configuration was auto-generated without security review.
Common exposure vectors:
- MCP server using the
service_rolekey instead of a restricted role - No row-level security (RLS) policies on Supabase tables
- Unrestricted
SELECT *capabilities across all tables - MCP tools that accept raw SQL queries without allowlisting
Solution
Step 1: Create a dedicated read-only database role for MCP connections
-- Create a restricted role for MCP access
CREATE ROLE mcp_reader WITH LOGIN PASSWORD 'secure-mcp-password';
-- Grant read-only access to specific tables only
GRANT SELECT ON public.products, public.categories TO mcp_reader;
-- Explicitly deny access to sensitive tables
REVOKE ALL ON public.users, public.payments, public.auth_tokens FROM mcp_reader;
Step 2: Enable row-level security on Supabase
-- Enable RLS on tables the MCP can access
ALTER TABLE public.orders ENABLE ROW LEVEL SECURITY;
-- Only expose non-sensitive order data
CREATE POLICY "mcp_read_orders" ON public.orders
FOR SELECT
USING (status = 'completed' AND customer_email IS NOT NULL);
Step 3: Use query allowlists in your MCP server configuration
{
"mcpServers": {
"database": {
"command": "mcp-server-postgres",
"args": ["--connection-string", "postgresql://mcp_reader:password@host/db"],
"env": {
"ALLOWED_OPERATIONS": "SELECT",
"ALLOWED_TABLES": "products,categories,public_orders",
"MAX_ROWS": "100"
}
}
}
}
Step 4: Audit what your MCP can access
# Connect as the MCP role and test what's visible
psql -U mcp_reader -d your_database -c "\dt"
psql -U mcp_reader -d your_database -c "SELECT * FROM users LIMIT 1;"
# This should return: ERROR: permission denied for table users
Why It Works
Principle of least privilege applied to MCP connections ensures the AI assistant can only read the data it needs. A dedicated database role with explicit grants prevents accidental exposure of sensitive tables. Row-level security adds a second layer by filtering rows even on permitted tables. Query allowlists prevent the MCP from executing arbitrary SQL, closing the door on prompt-injection-driven data exfiltration.
Context
- The Supabase MCP server by default uses your project's connection string which may have admin-level access
- MCP security vectors are actively being researched; see Simon Willison's work on prompt injection and MCP
- Always separate credentials: your application's database user, your admin user, and your MCP user should all be different roles
- Consider logging MCP queries to detect unusual access patterns
- This applies to any database-connected MCP, not just Supabase (Neon, PlanetScale, raw Postgres, etc.)