airlock-rls-mcp
Checks Supabase apps for security leaks: scans a deployed URL and its JS bundles for an exposed Supabase service_role key (service_role JWT or sb_secret_... key) without printing the full key, and audits a Supabase Postgres database for RLS-off tables, permissive always-true policies, and anon/authenticated tenant leaks using only catalog metadata (pg_tables, pg_policies, grants).
Airlock RLS MCP — Supabase leak checks inside your AI coding agent
Let Cursor, Claude Code, or any MCP client check a Supabase app for leaks while it builds it. It catches the most common vibe-coding footgun: a
service_rolekey shipped to the browser, and Row Level Security that's off or wide open.
The engine is Airlock RLS (npm i airlock-rls), the CI gate for Supabase RLS. This package is a thin MCP wrapper around it.
Two tools
scan_site_for_exposed_key — give it a deployed URL. It reads the page and its JS bundles for an exposed Supabase service_role key (a service_role JWT or an sb_secret_... key). No database, no credentials, just the public URL. A hit means anyone who reads it bypasses every RLS policy. It never prints the full key.
audit_supabase_rls — give it a Postgres connection string. It fails on RLS-off tables, permissive (always-true) policies, and anon/authenticated tenant leaks. It reads only catalog metadata (pg_tables, pg_policies, grants), never your row data, so a read-only role is enough.
Related MCP server: supership-scan
Add it to your MCP client
{
"mcpServers": {
"airlock": {
"command": "npx",
"args": ["-y", "airlock-rls-mcp"]
}
}
}That's the same block for Cursor (~/.cursor/mcp.json), Claude Desktop (claude_desktop_config.json) and other MCP clients. With Claude Code:
claude mcp add airlock -- npx -y airlock-rls-mcpThen ask the agent things like "scan https://myapp.com for an exposed Supabase key" or "audit the RLS on this database" and it calls the tools.
Requirements
Node.js 18 or newer.
Develop
npm install
npm run smoke # starts the server and checks both tools are advertisedMore
Guides on Supabase RLS, a live cross-tenant demo, and the hosted Airlock Monitor (continuous checks of your live database): shipsealed.com
License
MIT © Mateus Zingano
Available Tools
2 toolsaudit_supabase_rlsA
Audit a Supabase/Postgres database's Row Level Security. Fails when a table has RLS disabled, when a policy is permissive (USING (true) / WITH CHECK (true) or anything that reduces to always-true), when an anon or authenticated policy does not scope rows to the caller (tenant leak), and on exposed materialized views. Reads ONLY catalog metadata (pg_tables, pg_policies, grants, functions, views) — never your row data. A read-only connection string is enough.
| Name | Required | Description | Default |
|---|---|---|---|
| allow | No | Policy names that are intentionally permissive (e.g. a public status page). Prefer the qualified form "table.policy". | |
| db_url | Yes | Postgres connection string for the project to audit (e.g. postgresql://... — get it from `supabase status` locally or your project's connection settings). A read-only role is enough. | |
| schema | No | Schema to audit (default: public). | public |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and largely meets it: it discloses auth/permission needs (read-only role suffices), data-access scope ('reads ONLY catalog metadata... never your row data'), and the detection semantics. It does not describe the response shape or how findings are reported, which is a residual gap for a mutation-free but output-heavy tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tight sentences ordered by importance: purpose, detection scope, data-access boundary, and permission requirement. Nothing is repeated from the title or schema and every sentence carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-param audit tool with no output schema, the description covers purpose, detection rules, data scope, and permissions well. The main omission is what the call actually returns (finding structure/severity/remediation), which with no output schema would have been helpful to state.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all three parameters (db_url, allow, schema) are already documented in the schema, including the qualified 'table.policy' convention for allow. The description adds no parameter-level detail beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (audit) and resource (Supabase/Postgres Row Level Security) and immediately enumerates the exact conditions it flags, so an agent knows precisely what a call returns semantically. The single sibling (scan_site_for_exposed_key) is a different domain, so no sibling disambiguation is needed.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear when-to-use context by defining the failure conditions the tool detects, plus the practical prerequisite that 'a read-only connection string is enough.' It stops short of explicit when-not or alternative routing, but for a single-purpose audit tool the usable context is present.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
scan_site_for_exposed_keyA
Scan a DEPLOYED website's HTML and JavaScript bundles for an exposed Supabase service_role key (a service_role JWT or an sb_secret_... key). Needs only the public URL — no database, no credentials. A found key is a critical leak: it bypasses ALL Row Level Security, giving anyone who reads it full read/write to the database. Use this right after deploying a Supabase app, or whenever an AI-generated app might have bundled a secret into the frontend. Never prints the full key.
| Name | Required | Description | Default |
|---|---|---|---|
| site_url | Yes | Public https URL of the deployed site to scan (e.g. https://myapp.com). Only public http(s) hosts are allowed. | |
| max_scripts | No | How many JS bundles to read (default 50). If the site has more, the result says how many went unscanned instead of implying it looked at all. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does well: it discloses that no credentials/database are needed, that finding a key is a critical leak bypassing all RLS, and that the full key is never printed. It stops short of stating side-effect-free/read-only behavior explicitly, but 'Needs only the public URL' strongly implies it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core action and target, then layers in requirements, impact, and usage timing. Every sentence adds information, though the impact explanation is slightly elaborate for a definition concerned with invocation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a scan tool with no annotations and no output schema, the description covers purpose, requirements, impact, and output behavior ('never prints the full key'). Return-format details are only partially covered, but the schema's max_scripts note and the key-printing caveat largely fill the gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so site_url and max_scripts are already documented (baseline 3). The description adds value by clarifying that the required input is just the public URL with no credentials or database, reinforcing the parameter's nature beyond the schema text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (scan), resource (deployed website's HTML and JavaScript bundles), and target (exposed Supabase service_role key/JWT/sb_secret_ key). This is clearly distinguishable from the sibling audit_supabase_rls, which audits database policy rather than frontend bundle leakage.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit timing guidance: 'right after deploying a Supabase app' or 'whenever an AI-generated app might have bundled a secret into the frontend.' It provides clear context for when to reach for it but does not explicitly contrast with or exclude the sibling tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
v0.1.1- First observed
audit_supabase_rls - First observed
scan_site_for_exposed_key
TDQS
Scored across 2 tools
The two tools target entirely different surfaces: one greps a deployed website's HTML/JS bundles for leaked keys, the other inspects a Postgres/Supabase catalog for RLS misconfigurations. There is no overlap in inputs, resources, or failure modes, so an agent can never misselect between them.
Both names are snake_case and verb-first (scan_site_for_exposed_key, audit_supabase_rls), which is a predictable convention. The only minor deviation is that one embeds a prepositional phrase while the other is a flat verb+object, but the pattern is still readable and consistent.
Two tools is thin even for a narrowly scoped security-audit server; there is no tool for configuring scope, aggregating findings, or emitting a structured report. Each tool clearly earns its place, but the surface is smaller than the domain implies.
The two core checks (frontend key leak, database RLS) are well covered, but a Supabase security audit naturally extends to storage bucket policies, auth/edge-function configuration, and security-definer function review, none of which exist here. Agents must treat this as a partial audit rather than full coverage.
Maintenance
Related MCP Connectors
Scan a deployed app URL for exposed keys, open Supabase tables and missing security headers.
Security scanner for AI agents: prompt injection, leaked secrets, PII, and SSRF-risk URL detection.
Scan a site or AI-built app for exposed databases, keys and MCP endpoints, then verify the fixes.
Scan any public site for AI-agent visibility; get scored findings, a machine-readable fix pack, and
Related MCP Servers
- AlicenseAqualityCmaintenanceMCP server that lets AI coding agents (Claude Code, Cursor, Cline) audit Supabase projects for security misconfigurations AND apply the fixes — without leaving the agent. Tools: audit_project, list_findings, preview_fix (BEGIN/ROLLBACK safety), apply_fix (with confirmation), apply_all_fixes (transactional bulk). Closes the audit-fix loop entirely in the agent — other Supabase scanners only report.510 npm1MIT
- AlicenseNot gradedqualityFmaintenancePredeploy security scanner for AI-generated code. 80+ vulnerability patterns across secrets, auth, injection, config, Supabase, and logging. Runs locally, code never leaves your machine. Optional x402 witnessed attestation.51 npmApache 2.0
- AlicenseNot gradedqualityDmaintenanceLocal-first security check for AI coding agents — finds hardcoded secrets, exposed .env files, git-history leaks and vulnerable dependencies (OSV), entirely on your machine. Ask your agent "is this safe to ship?" and get a Launch Readiness score with a fix for every finding.MIT
- FlicenseAqualityDmaintenanceAudits PostgreSQL/Supabase schemas for security issues like missing RLS, permissive policies, and sensitive data exposure during AI conversations.3-