Lovable and the Supabase service_role key: how it leaks
The fastest way to make an RLS error disappear is to use the key that ignores RLS. Sometimes that is what your builder does.
Lovable wires your app to Supabase and writes the queries for you. Most of the time it uses the key that belongs in a browser. The failure mode worth checking for is what happens when a query is refused: Row Level Security says no, the build is blocked, and there is a key sitting in the same settings page that makes every refusal go away.
Check your published app
Two minutes in DevTools
- 1Open your live Lovable app and press F12.
- 2Sources tab, search all files with Ctrl+Shift+F for: service_role
- 3Search again for: SUPABASE_SERVICE — a mis-prefixed environment variable is the usual route in.
- 4Decode any long token starting eyJ using the command below and read its role claim.
- 5A role of service_role means the key is public and has been for as long as that build has been live.
Read the role out of a key you found
echo "THE_KEY" | cut -d. -f2 | base64 -d 2>/dev/null | grep -o '"role":"[^"]*"' # "role":"anon" → expected, this one belongs in the browser # "role":"service_role" → rotate it now
If you find it
- 01Rotate first: Supabase dashboard → Settings → API → reset the service_role key. Do this before touching the code, because the old key keeps working until you do.
- 02Update the places that legitimately used it — Edge Functions, server environment variables — then redeploy and confirm they still work.
- 03Fix the code path that leaked it, using the prompt below.
- 04Check Logs → API for bulk SELECT queries against user tables from an IP that is not yours, over the period the key was public.
- 05Check Auth → Users for accounts you did not create, and your tables for rows or deletions you cannot account for.
Stopping it happening again
The underlying cause is almost never malice or a bug in the builder — it is that an RLS error is an obstacle and the service_role key is the shortest way past it. The durable fix is to make the legitimate path work: write policies that permit what your app actually does, and move any operation that genuinely needs elevated access into an Edge Function where the key never reaches a browser.
Audit how this project uses Supabase keys. 1. Find every Supabase key in the project and decode each long eyJ token, reporting its role claim. Include environment variables and any sb_secret_ / sb_publishable_ keys. 2. For each, tell me whether the code holding it runs in the browser or on the server. 3. If any service_role or sb_secret_ key is reachable from client code, say so first, then rewrite those calls to use the anon key and work through Row Level Security instead. 4. If an operation genuinely needs to bypass RLS, move that operation into a Supabase Edge Function and keep the key server-side — do not move the key toward the client. 5. Confirm no client-exposed variable name (VITE_, NEXT_PUBLIC_, REACT_APP_) holds a secret key. Do NOT fix a row-level security error by switching to the service_role key, and do not disable RLS. If a query cannot work without one of those, tell me which query and why.
Common questions
- Does Lovable put the service_role key in my frontend?
- Not as a rule. It happens situationally: a query fails under Row Level Security, the fastest way to make the failure stop is the key that ignores RLS, and that key gets wired into client code. Whether yours is affected is a two-minute check rather than a yes or no.
- How do I check?
- Open your published app, press F12, and search all files for service_role and SUPABASE_SERVICE. Any hit means the key is in the bundle every visitor downloads. Decode any long eyJ token you find and read its role claim.
- What do I do first if I find it?
- Rotate the key in the Supabase dashboard before touching any code — the old key keeps working until you do. Then update your legitimate server-side uses, redeploy, and only then fix the code path that leaked it.
- Is the anon key in my Lovable app also a problem?
- No. The anon key is meant to be there and is constrained by Row Level Security. It is only dangerous if your policies are missing or unconditional, which is the separate check on the open database page.
This is one check out of 40+
Paste your site address and we run the whole list from the outside — leaked keys, open databases, unprotected pages — then hand you one prompt that fixes what we find. Free, about 30 seconds, no signup.
Check my site — free