Guide Cursor

How do I get Cursor to write safe Supabase RLS?

Short answer

Cursor writes whatever SQL you accept, so give it a standing rule and a way to prove the result. Add a project rule in .cursor/rules that every new table gets RLS on, minimal grants and one owner-scoped policy per operation in the same migration. If you connect the Supabase MCP server, scope it to one project with read_only=true and keep manual approval of tool calls on. Then test policies with supabase test db, signed-out requests and a second account. Keep service_role and sb_secret_ keys out of NEXT_PUBLIC_ and VITE_ variables.

1. Add a project rule

Create .cursor/rules/supabase-rls.mdc with something like:

When you create or change a table in the public schema, in the same migration:
- enable row level security
- revoke all from anon, authenticated, then grant only what each role needs
  (authenticated for private data; anon only for public read-only data)
- one policy per operation, comparing the owner column to (select auth.uid())
Don't disable RLS, don't use using (true) on private data, don't GRANT ALL to anon,
and don't put a service_role or sb_secret_ key in client code or a NEXT_PUBLIC_/VITE_ variable.

2. Lock down the Supabase MCP server

Supabase's MCP docs recommend scoping the server to one project and running read-only when you're inspecting data:

https://mcp.supabase.com/mcp?project_ref=YOUR_REF&read_only=true

Supabase also warns about prompt injection: text stored in your database can contain instructions an AI might follow. Keep manual approval of each tool call on, avoid pointing it at production data, and use a branch for schema changes.

3. Prove the policies with tests

Supabase's RLS guide says to create a test file under supabase/tests/ that asserts allow and deny for select, insert, update and delete as anon and authenticated, then run supabase test db. "Until the suite passes, you don't know whether the policies do what you intended." Ask Cursor to write the tests, then read them: a test that only checks success can pass when a write matched zero rows.

4. Keep secret keys on the server

Anything with a NEXT_PUBLIC_ or VITE_ prefix ships to the browser. Only the publishable or anon key belongs there. Use the secret key in server code, route handlers or Edge Functions, and keep .env files out of git.

Where we can help

Free instant check: paste your URL at patchandship.com/check.html to scan your homepage's JavaScript for secret keys and security headers (no signup, nothing stored). Paid, fixed price per app: Database Check, $49; Security Fix, $149 (every critical issue on our checklist fixed within 48 hours of working access); Fix & Deploy, $249. Otherwise a full refund if you ask within 14 days of purchase (Refund Policy). AI agents run the checks and a human engineer approves every change. Not a penetration test or a security guarantee.

FAQ

Does Cursor enable RLS automatically?

Not by itself. It follows your prompts and rules. Tables created in the Supabase dashboard have RLS on by default; tables created in SQL or migrations need it enabled explicitly.

Is it safe to give Cursor the Supabase MCP?

With care: scope it to one project, use read_only for inspection, keep manual approval on and avoid production data. Supabase lists prompt injection as the main risk.

Why did Cursor suggest GRANT ALL TO anon?

Usually to clear a 42501 error. It makes the table reachable by signed-out visitors. Grant authenticated the specific privileges instead and keep RLS on.

How do I check an existing Cursor project?

Run the Security Advisor, the read-only table query in our Oct 30 guide, and a signed-out curl request with the public key.

Sources