Service-role key shipped in the browser bundle
What it looks like
// src/lib/supabase.ts (imported by React components)
import { createClient } from '@supabase/supabase-js'
export const supabase = createClient(
'https://abcd1234.supabase.co',
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' // role: service_role
)What happens
Anyone who opens the app can copy the key from the downloaded JavaScript and read, change or delete every row in every table.
Where it shows up
Descriptive, not a verdict: builders and stacks whose defaults make this reachable, or that a public incident names. Each hub states the tool's own security features.
Seen in public
Escape analysed more than 5,600 publicly deployed apps built with AI app builders and found more than 2,000 vulnerabilities, over 400 exposed secrets and 175 instances of exposed personal data.
- more than 5,600 Apps analysed
- more than 2,000 Vulnerabilities found
- 400+ Exposed secrets
- 175 Exposed PII instances
Oct 2025 · Escape · all sources
Check it yourself
Uses your builder's dashboard and your browser. No tools to install.
- Open your live app in Chrome, right-click anywhere and choose Inspect, then open the Sources tab.
- Press Ctrl+Shift+F (Cmd+Option+F on a Mac) to search every loaded file. Search for
service_roleand then forsb_secret_. - Open the Network tab, reload the page, click any request whose address contains
supabase.co, and read theapikeyheader under Request Headers. - In the Supabase dashboard, open Project Settings, then API Keys, and compare that header value with your keys.
- A bad result is any search hit, or a header value that matches the service_role or secret key rather than the anon or publishable key.
What we check
We extract every credential-shaped string from the deployed bundle (the JavaScript files the browser downloads), decode each one and call the project's API with it to confirm which role it carries. The report lists the file, the role and the tables it could reach.
Fix direction
Move the service_role key out of front-end code into a server-only place such as an Edge Function or API route, and use the anon or publishable key in the browser. Rotate the exposed key in the Supabase dashboard, since anyone who loaded the old build may hold a copy.
Mechanism documented in: API keys (verified 2026-09-21); Secrets Management Cheat Sheet (verified 2026-09-21).
Covered by
Pre-launch check ($490, 48 hours) and Security sweep ($290, 24 hours)
Both include a re-check after your fixes.
Related patterns
- Third-party API key in the JavaScript bundleSecrets and keysHigh
Anyone who views the page source can take the key and run up charges, send messages or pull data on your account until the key is revoked.
- NEXT_PUBLIC_ prefix on a secretSecrets and keysCritical
The build writes the secret's value into public JavaScript, so anyone who loads the site can read it, and a redeploy with the same variable name republishes it.
- Row Level Security disabled on a tableData accessCritical
Anyone with the project URL and the public anon key, both of which sit in the app's JavaScript, can read, edit or delete every row in the table.
- LLM API key exposed to the clientAI featuresCritical
Anyone who views the page source can copy the key and run their own workloads on your account until the bill or the provider stops them.
Questions
is it safe to use the supabase service role key in the frontend
No. Supabase documents the service_role key (now called the secret key) as a server-only credential that skips every Row Level Security policy, the per-row access rules on your tables. Anything sent to the browser can be read by any visitor, so a service_role key in front-end code gives every visitor full database access. The browser should only ever hold the anon or publishable key.
how do i find out which supabase key my app is using
Open the app in Chrome, right-click, choose Inspect, open the Network tab and reload. Click a request to your project's supabase.co address and read the apikey request header. Compare it with the keys listed under Project Settings, API Keys in the Supabase dashboard. If it matches the service_role or secret key, treat that key as exposed and rotate it.
what happens if my supabase service key leaked
Treat the key as public. Rotate it in the Supabase dashboard so the old value stops working, move the new one to server-side code only, and review your tables for rows that changed unexpectedly. Rotation matters more than deleting the old build, because copies of the JavaScript may already exist in caches and browser histories.
Back to the catalogue, or run the self-check for your stack.