← All advisories
Advisory VV-003critical2026-08

Supabase service_role / secret key shipped to the browser

The service_role (or new sb_secret_) key bypasses every RLS policy. If it is in your JavaScript bundle, your whole database is public.

01.

What it is

Supabase: secret and service role keys "are never safe to expose because they bypass RLS." The service_role Postgres role has the BYPASSRLS attribute.

The 30,998-app scan found 52 apps with a key that can spend money or read a whole database in their JavaScript, including a Supabase service_role.

02.

How to check

  1. Open your live site, DevTools → Sources, and search the bundle for "service_role" or "sb_secret_".
  2. Decode any JWT you find (jwt.io or the snippet below): a role claim of service_role is critical; anon/authenticated is expected.
03.

How to fix

  1. Rotate immediately: create a new secret key in Settings → API Keys, replace it everywhere, then retire or deactivate the old one.
  2. Move code that needs elevated access into an Edge Function or server route. Keep only the publishable/anon key in the browser.
// Decode a JWT payload found in your bundle (no verification needed to see the role)
const payload = JSON.parse(atob(token.split('.')[1]));
console.log(payload.role); // "service_role" => leaked admin key

// Server-only usage (Next.js route handler) — no NEXT_PUBLIC_ prefix
export async function POST(req) {
  const admin = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_SERVICE_ROLE_KEY);
  // ...check the caller is allowed first!
}
04.

Sources

The weekly email

One email a week. Only what changed.

New advisories, CVEs and fixes for Lovable, Bolt, v0, Replit, Base44 and Cursor apps. No roundups of things you already read.