// docs / baas security / supabase service role exposure
Supabase service-role-nøkkel eksponert i JavaScript: hva det betyr og hvordan du finner den
Supabase service-role-nøkkelen er hovednøkkelen til databasen din. Enhver som har den, omgår Row-Level Security, kan lese hver kolonne i hver tabell, og kan skrive eller slette hva de vil. Den er designet for å leve utelukkende i serverside-kode — aldri i nettleseren. Når et AI-kodeverktøy sender den til JavaScript-bundlen, er databasen din i praksis offentlig. Denne artikkelen forklarer JWT-formen som identifiserer en lekket nøkkel, de tre AI-verktøy-mønstrene som produserer lekkasjen, hva du skal gjøre den første timen etter deteksjon, og hvordan du skanner etter den automatisk før brukerne gjør det.
Hva service-role-nøkkelen er
Supabase utsteder to distinkte nøkler for hvert prosjekt: anon-nøkkelen (også kalt den publiserbare nøkkelen i nyere prosjekter) og service_role-nøkkelen. Begge er JSON Web Tokens signert av prosjektets JWT-hemmelighet. Forskjellen er role-claimet bakt inn i JWT-payloaden — anon for den offentlige nøkkelen, service_role for hovednøkkelen. PostgREST, Supabase Storage og Supabase Auth bytter alle til bypass-everything-modus når de ser service_role-claimet.
Dekod en hvilken som helst Supabase-nøkkel på jwt.io og se på payloaden. Formen til en service-role-JWT er umiskjennelig:
Dekodet payload av en service-role-JWT (vist som en syntaks-uthevet blokk nedenfor).
{
"iss": "supabase",
"ref": "[project-ref]",
"role": "service_role",
"iat": 1700000000,
"exp": 2000000000
}Nyere Supabase-prosjekter utsteder secret-style-nøkler med prefikset sb_secret_ i stedet for en JWT. Atferden er identisk — alt som bærer sb_secret_ i en offentlig bundle er like katastrofalt.
Hvordan AI-kodeverktøy lekker service-role-nøkkelen
Vi har sett de samme tre mønstrene på tvers av tusenvis av vibe-kodede apper. Hvert av dem starter med at en utvikler ber et AI-verktøy om hjelp og ender med at service-nøkkelen er inlinet i en bundle.
Mønster 1: Enkel .env-fil med NEXT_PUBLIC_-prefiks
Utvikleren ber AI-verktøyet om å "sette opp Supabase" og aksepterer en enkelt .env med begge nøklene. AI-verktøyet — trent på et korpus der de fleste miljøvariabler eksponeres via NEXT_PUBLIC_* — prefikser begge med NEXT_PUBLIC_. Next.js inlinerer alt som matcher det prefikset i klientbundlen ved byggetidspunkt. Lever til Vercel, og service-nøkkelen ligger i main.[hash].js.
Mønster 2: Feil nøkkel i createClient-kall
Utvikleren limer inn begge nøklene i en config.ts-fil AI-en genererte, og AI-en fyller ut det nettleserside createClient()-kallet med process.env.SUPABASE_SERVICE_ROLE_KEY ved en feil. Byggingen henter inn variabelen, og JWT-en lander i bundlen.
Mønster 3: Service-role-nøkkel hardkodet i seed-skript
Utvikleren ber AI-verktøyet om å skrive et skript som seeder databasen. AI-en hardkoder service-role-nøkkelen direkte i filen (i stedet for å lese fra miljøet), committer filen til repoet, og det offentlige GitHub-repoet eller den deployede appens /scripts/seed.js-rute serverer nå nøkkelen.
Slik oppdager FixVibes bundle-skanning lekkasjen
FixVibes bundle-secrets-sjekk laster ned hver JavaScript-fil referert av den deployede appen — entry-chunks, lazy-lastede chunks, web workers, service workers — og kjører dem gjennom en detektor som dekoder alt som matcher JWT-formen (eyJ[base64-header].eyJ[base64-payload].[signature]). Hvis den dekodede payloaden inneholder "role": "service_role", rapporterer skanningen det som et kritisk funn med filstien og den eksakte linjen der nøkkelen vises. Samme sjekk matcher også det nyere sb_secret_*-mønsteret etter prefiks.
Skanningen autentiserer seg aldri med den oppdagede nøkkelen. Den identifiserer formen og rapporterer lekkasjen — å bruke nøkkelen for å bevise utnyttbarhet ville vært uautorisert tilgang til databasen din. Beviset ligger i selve JWT-payloaden.
Oppdaget — hva du skal gjøre den første timen
En lekket service-role-nøkkel er en runtime-nødssituasjon. Anta at nøkkelen har blitt skrapet — angripere overvåker offentlige bundles i sanntid. Behandle databasen som kompromittert til du har rotert nøkkelen og granska nylig aktivitet.
- Roter nøkkelen umiddelbart. I Supabase Dashboard, gå til Project Settings → API → Service role key → Reset. Den gamle nøkkelen invalideres innen sekunder. All serverside-kode som bruker nøkkelen må oppdateres og redeployes før rotasjonen lander.
- Granske nylig databaseaktivitet. Åpne Database → Logs i dashboardet. Filtrer på siste 7 dager. Se etter uvanlige
SELECT *-spørringer mot tabeller med PII, storeUPDATE- ellerDELETE-utsagn, og requests fra IP-er utenfor din kjente infrastruktur. Supabase loggerx-real-ip-headeren på hver request. - Sjekke storage-objekter. Besøk Storage → Logs og gjennomgå nylige filnedlastinger. En lekket service-role-nøkkel gir bypass-everything-tilgang til private buckets også.
- Fjerne nøkkelen fra source control. Selv etter rotasjon betyr det at JWT-en ligger i git-historikken din at den er oppdagelig i det offentlige repoet. Bruk
git filter-repoeller BFG Repo-Cleaner for å skrubbe den fra historikken, og deretter force-push (advar samarbeidspartnere først). - Skanne på nytt etter fiks. Kjør en fersk FixVibe-skanning mot den redeployede appen. Bundle-secrets-funnet skal forsvinne. Bekreft at ingen
service_role-JWT og ingensb_secret_*-streng gjenstår i noen chunk.
Forebygging av lekkasjen i utgangspunktet
Den strukturelle fiksen er navnedisiplin pluss verktøynivå-rekkverk:
- Aldri prefiks service-nøkkelen med
NEXT_PUBLIC_*,VITE_*eller noe annet bundle-inlinende prefiks. Navnekonvensjonen er grensen — alle rammeverk respekterer den. - Hold service-nøkkelen helt utenfor
.envpå utviklermaskinen. Les den fra en hemmelighetsbehandler (Doppler, Infisical, Vercel krypterte env-vars) ved deploy, aldri commit den lokalt. - <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.
- Legg til en CI-port som skanner byggeutgangen. Etter
next build, grep.next/static/chunks/-utgangen etterservice_role-strengen. La byggingen feile hvis noe matcher.
# 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 1Ofte stilte spørsmål
Hvor raskt finner angripere faktisk lekkede Supabase service-role-nøkler?
Skannere av offentlige bundles tråler nye deployments innen minutter. Forskere har dokumentert fungerende utnyttelser mot nye Supabase-prosjekter på under en time fra første deploy. Behandle enhver service-role-eksponering som et 60-minutters vindu, ikke et 60-dagers.
Er det nok å rotere nøkkelen, eller må jeg anta dataeksfiltrering?
Rotasjon invaliderer den lekkede nøkkelen, men opphever ikke data som allerede er hentet ut. Hvis tabellene dine inneholder PII, betalingsdata eller andre regulerte data, kan du ha en meldeplikt under GDPR (72 timer), CCPA eller HIPAA. Granske loggene og rådfør deg med juridisk rådgiver hvis granskingen viser mistenkelig tilgang.
Kan RLS beskytte meg hvis service-role-nøkkelen lekker?
Nei. Row-Level Security omgås fullstendig av service_role-claimet. Det er ved design — nøkkelen finnes nettopp for å la backend-kode hoppe over RLS for admin-operasjoner. Avbøtningen er å sørge for at nøkkelen aldri når en kontekst der en angriper kan lese den.
Gjelder dette for den nye Supabase publiserbare/secret-nøkkel-modellen (<code>sb_publishable_</code> / <code>sb_secret_</code>)?
Ja — identisk risikoklasse. sb_secret_*-nøkkelen er det nye secret-nøkkel-formatet som erstatter service-role-JWT-en for nyere prosjekter. Alt som bærer sb_secret_* i en bundle er like katastrofalt som en lekket service-role-JWT. FixVibes bundle-secrets-detektor matcher begge formene.
Hva med anon-/publiserbar nøkkel — er den trygg i bundlen?
Ja, ved design. Anon-nøkkelen er ment å leve i nettleseren og er det enhver Supabase-webklient bruker. Sikkerheten avhenger helt og holdent av at RLS er riktig konfigurert på hver offentlige tabell. Se artikkelen Supabase RLS-skanner for hva du skal sjekke.
Neste steg
Kjør en FixVibe-skanning mot produksjons-URL-en din — bundle-secrets-sjekken er gratis, ingen registrering, og rapporterer service_role-eksponering på under et minutt. Par dette med artikkelen Supabase RLS-skanner for å verifisere at RLS-laget gjør jobben sin, og Sjekkliste for Supabase storage-bucket-sikkerhet for å låse ned filtilgang. For bakgrunn til hvorfor AI-verktøy genererer denne lekkasjeklassen så pålitelig, les Hvorfor AI-kodeverktøy etterlater sikkerhetshull.
