// docs / baas security / supabase service role exposure
Supabase-diens-rol-sleutel blootgestel in JavaScript: wat dit beteken en hoe om dit te vind
Die Supabase-diens-rol-sleutel is die meestersleutel tot jou databasis. Enigiemand wat dit besit, omseil ry-vlak-sekuriteit, kan elke kolom van elke tabel lees, en kan enigiets skryf of skrap wat hulle wil. Dit is ontwerp om uitsluitlik in bedienerkant-kode te leef — nooit in die blaaier nie. Wanneer 'n KI-koderingsgereedskap dit na die JavaScript-bundel stuur, is jou databasis eintlik publiek. Hierdie artikel verduidelik die JWT-vorm wat 'n gelekde sleutel identifiseer, die drie KI-gereedskap-patrone wat die lek voortbring, wat om te doen in die eerste uur na deteksie, en hoe om dit outomaties te skandeer voordat gebruikers dit doen.
Wat die diens-rol-sleutel is
Supabase reik twee duidelike sleutels uit vir elke projek: die anon-sleutel (ook die publiseerbare sleutel genoem in nuwer projekte) en die service_role-sleutel. Albei is JSON-Web-Tokens geteken deur jou projek se JWT-geheim. Die verskil is die role-aanspraak ingebak in die JWT-payload — anon vir die publieke sleutel, service_role vir die meestersleutel. PostgREST, Supabase-Stoorplek, en Supabase-Auth skakel almal in omseil-alles-modus wanneer hulle die service_role-aanspraak sien.
Dekodeer enige Supabase-sleutel by jwt.io en kyk na die payload. Die vorm van 'n diens-rol-JWT is onmisbaar:
Gedekodeerde payload van 'n diens-rol-JWT (hieronder as 'n sintaks-uitgelig blok getoon).
{
"iss": "supabase",
"ref": "[project-ref]",
"role": "service_role",
"iat": 1700000000,
"exp": 2000000000
}Nuwer Supabase-projekte reik geheim-styl-sleutels uit met die voorvoegsel sb_secret_ in plaas van 'n JWT. Die gedrag is identies — enigiets wat sb_secret_ in 'n openbare bundel dra, is net so katastrofies.
Hoe KI-koderingsgereedskap die diens-rol-sleutel lek
Ons het dieselfde drie patrone in duisende vibe-gekodeerde toepassings gesien. Elkeen begin met 'n ontwikkelaar wat 'n KI-gereedskap om hulp vra en eindig met die diens-sleutel binne-in 'n bundel ingebed.
Patroon 1: Enkele .env-lêer met NEXT_PUBLIC_-voorvoegsel
Die ontwikkelaar vra die KI-gereedskap om "Supabase op te stel" en aanvaar 'n enkele .env met albei sleutels. Die KI-gereedskap — opgelei op 'n korpus waar die meeste omgewingsveranderlikes via NEXT_PUBLIC_* blootgestel word — voeg NEXT_PUBLIC_ by albei. Next.js bed enigiets wat by daardie voorvoegsel pas tydens boutyd in die kliëntbundel in. Stuur na Vercel, en die diens-sleutel is in main.[hash].js.
Patroon 2: Verkeerde sleutel in createClient-oproep
Die ontwikkelaar plak albei sleutels in 'n config.ts-lêer wat die KI gegenereer het, en die KI vul die blaaierkant-createClient()-oproep per ongeluk met process.env.SUPABASE_SERVICE_ROLE_KEY in. Die bou trek die veranderlike in, en die JWT land in die bundel.
Patroon 3: Diens-rol-sleutel hardgekodeer in saadskripte
Die ontwikkelaar vra die KI-gereedskap om 'n skrip te skryf wat die databasis saad. Die KI hardkodeer die diens-rol-sleutel direk in die lêer (eerder as om uit die omgewing te lees), commit die lêer na die bewaarplek, en die openbare GitHub-bewaarplek of die ontplooide toepassing se /scripts/seed.js-roete bedien nou die sleutel.
Hoe die FixVibe-bundel-skandering die lek opspoor
FixVibe se bundel-geheime-toets laai elke JavaScript-lêer af waarna die ontplooide toepassing verwys — invoer-stukke, lui-gelaaide stukke, webwerkers, dienswerkers — en stuur dit deur 'n detektor wat enigiets dekodeer wat by die JWT-vorm pas (eyJ[base64-kopstuk].eyJ[base64-payload].[handtekening]). As die gedekodeerde payload "role": "service_role" bevat, rapporteer die skandering dit as 'n kritieke bevinding met die lêerpad en die presiese reël waar die sleutel verskyn. Dieselfde toets pas ook by die nuwer sb_secret_*-patroon volgens voorvoegsel.
Die skandering autentiseer nooit met die ontdekte sleutel nie. Dit identifiseer die vorm en rapporteer die lek — om die sleutel te gebruik om uitbuitbaarheid te bewys, sou ongemagtigde toegang tot jou databasis wees. Die bewys is in die JWT-payload self.
Opgespoor — wat om in die eerste uur te doen
'n Gelekde diens-rol-sleutel is 'n looptyd-noodgeval. Aanvaar dat die sleutel afgeskraap is — aanvallers monitor openbare bundels in werklike tyd. Behandel die databasis as gekompromitteerd totdat jy die sleutel geroteer en onlangse aktiwiteit geoudit het.
- Roteer die sleutel onmiddellik. In die Supabase-Dashboard, gaan na Projek-Instellings → API → Diens-rol-sleutel → Herstel. Die ou sleutel is binne sekondes ongeldig. Enige dienskant-kode wat die sleutel gebruik, moet bygewerk en herontplooi word voordat die rotasie land.
- Oudit onlangse databasis-aktiwiteit. Maak Databasis → Logs in die dashboard oop. Filtreer op die laaste 7 dae. Soek na ongewone
SELECT *-navrae teen tabelle met PII, grootUPDATE- ofDELETE-stellings, en versoeke van IP's buite jou bekende infrastruktuur. Supabase teken diex-real-ip-kopstuk op elke versoek aan. - Kyk na stoorobjekte. Besoek Stoorplek → Logs en hersien onlangse lêerafladings. 'n Gelekde diens-rol-sleutel gee omseil-alles-toegang tot privaat emmers ook.
- Verwyder die sleutel uit bronbeheer. Selfs na rotasie, beteken om die JWT in jou git-geskiedenis te los dat dit ontdekbaar is in die openbare bewaarplek. Gebruik
git filter-repoof BFG Repo-Cleaner om dit uit die geskiedenis te skrop, en doen dan 'n force-push (waarsku medewerkers eers). - Herskandeer na regstelling. Voer 'n vars FixVibe-skandering teen die herontplooide toepassing uit. Die bundel-geheime-bevinding behoort verwyder te wees. Bevestig dat geen
service_role-JWT en geensb_secret_*-string in enige stuk oorbly nie.
Voorkom die lek in die eerste plek
Die strukturele oplossing is benaming-dissipline plus gereedskap-vlak-beskermings:
- Plaas nooit die voorvoegsel
NEXT_PUBLIC_*,VITE_*of enige ander bundel-inbed-voorvoegsel voor die diens-sleutel nie. Die benamingskonvensie is die grens — elke raamwerk respekteer dit. - Hou die diens-sleutel heeltemal uit
.envop die ontwikkelaarmasjien. Lees dit uit 'n geheim-bestuurder (Doppler, Infisical, Vercel-geënkripteerde omgewingsveranderlikes) by ontplooiing, commit dit nooit plaaslik nie. - <strong>Mark every Supabase client construction with explicit context.</strong> Files named <code>supabase/browser.ts</code> use the anon key; files named <code>supabase/server.ts</code> use the service-role key with <code>import 'server-only'</code> at the top. The <code>server-only</code> import causes a build error if a client component tries to consume the module.
- <strong>Add a pre-commit hook that greps for JWT-shaped strings.</strong> <code>git diff --staged | grep -E 'eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+'</code> catches both anon and service tokens before they leave your machine.
- Voeg 'n CI-hek by wat die bou-uitvoer skandeer. Na
next build, grep die.next/static/chunks/-uitvoer vir dieservice_role-string. Laat die bou misluk as enigiets pas.
# Pre-commit hook: refuse any staged JWT-shaped string.
git diff --staged \
| grep -E 'eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+' \
&& echo "JWT detected in staged changes — refusing commit" \
&& exit 1
# CI gate: fail the build if "service_role" shipped to the static bundle.
grep -RE 'service_role|sb_secret_' .next/static/chunks/ \
&& echo "Service-role credential leaked into bundle" \
&& exit 1Algemene vrae
Hoe vinnig vind aanvallers werklik gelekde Supabase-diens-rol-sleutels?
Openbare-bundel-skandeerders skraap nuwe ontplooiings binne minute. Navorsers het werkende uitbuitings teen nuwe Supabase-projekte gedokumenteer in minder as 'n uur vanaf eerste ontplooiing. Behandel enige diens-rol-blootstelling as 'n 60-minute-venster, nie 'n 60-dag-een nie.
Is die roteer van die sleutel genoeg, of moet ek data-onttrekking aanvaar?
Rotasie ongeldig die gelekde sleutel maar herroep nie data wat reeds onttrek is nie. As jou tabelle PII, betalingsdata of enige gereguleerde data bevat, het jy moontlik 'n kennisgewingsverpligting onder GDPR (72 uur), CCPA of HIPAA. Oudit die logs en raadpleeg regsadviseurs as die oudit verdagte toegang toon.
Kan RLS my beskerm as die diens-rol-sleutel lek?
Nee. Ry-vlak-sekuriteit word geheel en al deur die service_role-aanspraak omseil. Dit is per ontwerp — die sleutel bestaan presies om backend-kode toe te laat om RLS oor te slaan vir admin-operasies. Die versagting is om seker te maak die sleutel bereik nooit 'n konteks waar 'n aanvaller dit kan lees nie.
Geld dit vir die nuwe Supabase publiseerbare / geheim-sleutel-model (<code>sb_publishable_</code> / <code>sb_secret_</code>)?
Ja — identiese risikoklas. Die sb_secret_*-sleutel is die nuwe geheime-sleutel-formaat wat die diens-rol-JWT vir nuwer projekte vervang. Enigiets wat sb_secret_* in 'n bundel dra, is net so katastrofies as 'n gelekde diens-rol-JWT. FixVibe se bundel-geheime-detektor pas by albei vorms.
Wat van die anon-/publiseerbare sleutel — is dit veilig in die bundel?
Ja, per ontwerp. Die anon-sleutel is bedoel om in die blaaier te leef en is wat elke Supabase-webkliënt gebruik. Sy veiligheid hang heeltemal af van RLS wat korrek op elke openbare tabel gekonfigureer is. Sien die Supabase RLS-skandeerder-artikel vir wat om te kontroleer.
Volgende stappe
Voer 'n FixVibe-skandering teen jou produksie-URL uit — die bundel-geheime-toets is gratis, geen aansluiting, en rapporteer service_role-blootstelling in minder as 'n minuut. Kombineer dit met die Supabase RLS-skandeerder-artikel om te verifieer dat die RLS-laag sy werk doen, en die Supabase-stoorbak-sekuriteitskontrolelys om lêertoegang toe te sluit. Vir agtergrond oor waarom KI-gereedskap hierdie lekklas so betroubaar genereer, lees Waarom KI-koderingsgereedskap sekuriteitsgapings laat.
