Demo, all content is generated
Question

Cursor fixed my RLS errors by adding NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEY, is that ok?

Solved · 5602 views · asked by juanpa · edited

I kept getting new row violates row-level security policy for table "orders". After a long session Cursor said the fix is to use the service role key in the client and added this:

export const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEY!
)

And everything works now! But the word 'service role' makes me nervous. The app is live with around 60 customers.

What I’ve tried

Read the Supabase docs page about keys but didn't really understand the difference. Everything works so I haven't changed it back yet.

Comment
Oh no. Going to check my own app right now. tomvibes · edited
Same thing happened to me with Claude Code. This thread is the reason I went back and looked. dental_dave · edited
Checked my app after reading this. Mine was fine, but I didn't know how to check before today. ahmed_elsayed · edited

3 answers

Marked as helpful by the asker
lena_ops · edited

Please treat this as an incident, today.

  • Anything prefixed NEXT_PUBLIC_ is copied into the JavaScript every visitor downloads. Open your site, DevTools → Sources, search for service_role or the start of the key. It's there.
  • The service role key skips RLS completely. Anyone who has it can read, change and delete every row in every table, including your customers' orders.

Steps:

  1. Rename back to the anon/publishable key in the client.
  2. Rotate the service role key in Supabase (API settings). Assume it's been copied.
  3. Fix the actual RLS problem. For an insert error it's usually a missing INSERT policy, e.g.
create policy "users insert own orders" on orders
for insert to authenticated
with check (user_id = auth.uid());
  1. If you really need admin powers, use the service key only in server code (Route Handler / Server Action / Edge Function), in an env var without NEXT_PUBLIC_.

Then check the Supabase logs for unusual requests since the day this was deployed.

Comment
Found it in the bundle in 20 seconds. Rotating now. Thank you for being direct. juanpa · edited
Done: rotated, insert policy added, client back on anon key. Orders still work. I feel sick but ok. juanpa · edited
Good work turning it around the same day. Most people find out months later. mira_dev · edited
mira_dev · edited

One more habit that prevents this: ask Cursor to explain why an RLS error happens before it fixes it. 'Violates row-level security' almost always means a policy is missing or checks the wrong column. The fix is in SQL, never in which key you use.

Comment
Putting this in my Cursor rules file: never use the service role key in client code. priya_ships · edited
old_school_raj · edited

Maybe learn what an environment variable is before putting 60 people's data online. This is exactly why nobody takes vibe coders seriously.

Comment
Fair that I should have known. I'm here to learn it now. juanpa · edited
He asked before anything went wrong and fixed it within hours. That's the behavior we want. sergio_ruiz · edited