Skip to content

Audit MCP servers for database data leakage

reference

MCP servers with database access can inadvertently expose entire SQL databases if misconfigured

databasesecuritymcpsupabasedata-leakage
26 views

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_role key 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.)
About this share
Contributormblode
Repositorymblode/shares
CreatedFeb 10, 2026
View on GitHub