Skip to content
BuildThenTestedSee packages

Service-role key shipped in the browser bundle

Anyone who opens the app can copy the key from the downloaded JavaScript and read, change or delete every row in every table. API keys and passwords the app uses to talk to other services. Check it yourself with the steps below; our test adds what a script and a second account can find.

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
)
A Supabase client created in front-end code with the service_role key instead of the anon or publishable key.

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.

  1. Open your live app in Chrome, right-click anywhere and choose Inspect, then open the Sources tab.
  2. Press Ctrl+Shift+F (Cmd+Option+F on a Mac) to search every loaded file. Search for service_role and then for sb_secret_.
  3. Open the Network tab, reload the page, click any request whose address contains supabase.co, and read the apikey header under Request Headers.
  4. In the Supabase dashboard, open Project Settings, then API Keys, and compare that header value with your keys.
  5. 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.

Compare packages

Related patterns

  • Third-party API key in the JavaScript bundleSecrets and keys

    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.

    High
  • NEXT_PUBLIC_ prefix on a secretSecrets and keys

    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.

    Critical
  • Row Level Security disabled on a tableData access

    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.

    Critical
  • LLM API key exposed to the clientAI features

    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.

    Critical

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.