// docs / baas security / supabase service role exposure
Supabase service role ključ izložen u JavaScriptu: šta to znači i kako ga pronaći
Supabase service role ključ je glavni ključ vaše baze podataka. Svako ko ga drži zaobilazi Row-Level Security, može čitati svaku kolonu svake tabele te pisati ili brisati šta god želi. Dizajniran je da postoji isključivo u serverskom kodu — nikada u pregledniku. Kada ga AI alat za kodiranje isporuči u JavaScript bundle, vaša baza je, u suštini, javna. Ovaj članak objašnjava JWT oblik koji identificira procurjeli ključ, tri obrasca AI alata koji proizvode curenje, šta uraditi u prvom satu nakon otkrivanja i kako skenirati za time automatski prije nego što to učine korisnici.
Šta je service role ključ
Supabase izdaje dva različita ključa za svaki projekat: anon ključ (također zvan publishable key u novijim projektima) i service_role ključ. Oba su JSON Web Tokeni potpisani JWT secretom vašeg projekta. Razlika je u role claimu ugrađenom u payload JWT-a — anon za javni ključ, service_role za glavni ključ. PostgREST, Supabase Storage i Supabase Auth svi prelaze u režim zaobilaženja-svega kada vide claim service_role.
Dekodirajte bilo koji Supabase ključ na jwt.io i pogledajte payload. Oblik service-role JWT-a je nepogrešiv:
Dekodirani payload service-role JWT-a (prikazan kao blok s isticanjem sintakse ispod).
{
"iss": "supabase",
"ref": "[project-ref]",
"role": "service_role",
"iat": 1700000000,
"exp": 2000000000
}Noviji Supabase projekti izdaju tajne ključeve s prefiksom sb_secret_ umjesto JWT-a. Ponašanje je identično — sve što nosi sb_secret_ u javnom bundleu jednako je katastrofalno.
Kako AI alati za kodiranje izlijevaju service role ključ
Vidjeli smo ista tri obrasca u hiljadama vibe-coded aplikacija. Svaki počinje tako što developer traži pomoć od AI alata, a završava se ugrađivanjem service ključa u bundle.
Obrazac 1: Jedan .env fajl s prefiksom NEXT_PUBLIC_
Developer traži od AI alata da "postavi Supabase" i prihvata jedan .env s oba ključa. AI alat — treniran na korpusu u kojem se većina environment varijabli izlaže preko NEXT_PUBLIC_* — stavlja prefiks NEXT_PUBLIC_ na oba. Next.js u vrijeme buildanja ugrađuje sve što odgovara tom prefiksu u klijentski bundle. Isporučite na Vercel i service ključ je u main.[hash].js.
Obrazac 2: Pogrešan ključ u pozivu createClient
Developer lijepi oba ključa u fajl config.ts koji je AI generirao, a AI greškom popunjava klijentski createClient() poziv s process.env.SUPABASE_SERVICE_ROLE_KEY. Build povlači varijablu i JWT završi u bundleu.
Obrazac 3: Service-role ključ hardkodiran u seed skriptama
Developer traži od AI alata da napiše skriptu koja popunjava bazu. AI hardkodira service-role ključ direktno u fajl (umjesto čitanja iz environmenta), commita fajl u repozitorij i sada javni GitHub repo ili ruta /scripts/seed.js deploy-ane aplikacije poslužuje ključ.
Kako FixVibe bundle sken detektuje curenje
FixVibe-ova provjera bundle-secrets preuzima svaki JavaScript fajl koji deploy-ana aplikacija referencira — entry chunkove, lazy-loaded chunkove, web workere, service workere — i propušta ih kroz detektor koji dekodira sve što odgovara JWT obliku (eyJ[base64-header].eyJ[base64-payload].[signature]). Ako dekodirani payload sadrži "role": "service_role", sken to prijavljuje kao kritični nalaz s putanjom fajla i tačnom linijom gdje se ključ pojavljuje. Ista provjera također hvata noviji sb_secret_* obrazac po prefiksu.
Sken se nikada ne autentificira s otkrivenim ključem. Identificira oblik i prijavljuje curenje — koristiti ključ za dokazivanje iskoristivosti bilo bi neovlašteni pristup vašoj bazi. Dokaz je u samom JWT payloadu.
Otkriveno — šta uraditi u prvom satu
Procurjeli service role ključ je runtime hitnost. Pretpostavite da je ključ skrejpan — napadači u realnom vremenu prate javne bundleove. Tretirajte bazu kao kompromitovanu sve dok ne rotirate ključ i auditujete nedavnu aktivnost.
- Rotirajte ključ odmah. U Supabase Dashboardu, idite na Project Settings → API → Service role key → Reset. Stari ključ se poništava u roku od nekoliko sekundi. Svaki serverski kod koji koristi ključ mora biti ažuriran i ponovo deploy-an prije nego što rotacija stupi na snagu.
- Auditujte nedavnu aktivnost baze. Otvorite Database → Logs u dashboardu. Filtrirajte zadnjih 7 dana. Tražite neobične upite
SELECT *nad tabelama s PII-jem, velikeUPDATEiliDELETEizjave i zahtjeve s IP adresa izvan vaše poznate infrastrukture. Supabase loguje headerx-real-ipna svakom zahtjevu. - Provjerite storage objekte. Posjetite Storage → Logs i pregledajte nedavna preuzimanja fajlova. Procurjeli service-role ključ daje bypass-everything pristup i privatnim bucketima.
- Uklonite ključ iz source controla. Čak i nakon rotacije, ostavljanje JWT-a u vašoj git historiji znači da je otkriv u javnom repou. Koristite
git filter-repoili BFG Repo-Cleaner da ga uklonite iz historije, zatim force-push (prvo upozorite saradnike). - Ponovo skenirajte nakon popravka. Pokrenite svjež FixVibe sken prema redeploy-anoj aplikaciji. Nalaz bundle-secrets trebao bi nestati. Potvrdite da nijedan
service_roleJWT i nijedan stringsb_secret_*nije ostao ni u jednom chunku.
Sprečavanje curenja od samog početka
Strukturni popravak je disciplina imenovanja plus zaštita na nivou alata:
- Nikada ne stavljajte prefiks
NEXT_PUBLIC_*,VITE_*ili bilo koji drugi prefiks koji ugrađuje varijable u bundle na service ključ. Konvencija imenovanja je granica — svaki framework je poštuje. - Držite service ključ potpuno izvan
.envfajla na developerovoj mašini. Čitajte ga iz secret managera (Doppler, Infisical, Vercel enkriptovane env varijable) prilikom deploya, nikada ga ne commitajte lokalno. - <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.
- Dodajte CI gate koji skenira izlaz buildanja. Nakon
next build, grepujte izlaz.next/static/chunks/za stringservice_role. Neuspjeh buildanja ako se nešto poklopi.
# 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 1Često postavljana pitanja
Koliko brzo napadači zaista pronađu procurjele Supabase service-role ključeve?
Skeneri javnih bundleova pretražuju nove deployove u roku od nekoliko minuta. Istraživači su dokumentovali funkcionalne eksploite protiv novih Supabase projekata u manje od sat vremena od prvog deploya. Tretirajte svako izlaganje service-rolea kao 60-minutni prozor, ne 60-dnevni.
Je li rotacija ključa dovoljna, ili moram pretpostaviti eksfiltraciju podataka?
Rotacija poništava procurjeli ključ, ali ne poništava podatke koji su već povučeni. Ako vaše tabele sadrže PII, podatke o plaćanju ili bilo kakve regulirane podatke, možda imate obavezu obavještavanja prema GDPR-u (72 sata), CCPA-i ili HIPAA-i. Auditujte logove i konsultujte pravnu službu ako audit pokaže sumnjiv pristup.
Može li me RLS zaštititi ako service-role ključ procuri?
Ne. Row-Level Security se u potpunosti zaobilazi claimom service_role. To je po dizajnu — ključ postoji upravo zato da omogući backend kodu da preskoči RLS za admin operacije. Mjera ublažavanja je osigurati da ključ nikada ne dođe u kontekst u kojem napadač može da ga pročita.
Vrijedi li ovo za novi Supabase model publishable / secret ključeva (<code>sb_publishable_</code> / <code>sb_secret_</code>)?
Da — identična klasa rizika. Ključ sb_secret_* je novi format tajnog ključa koji za novije projekte zamjenjuje service-role JWT. Sve što nosi sb_secret_* u bundleu jednako je katastrofalno kao i procurjeli service-role JWT. FixVibe-ov detektor bundle-secrets prepoznaje oba oblika.
A šta s anon / publishable ključem — je li on siguran u bundleu?
Da, po dizajnu. Anon ključ je namijenjen da postoji u pregledniku i koristi ga svaki Supabase web klijent. Njegova sigurnost zavisi isključivo od ispravne konfiguracije RLS-a na svakoj javnoj tabeli. Pogledajte članak Supabase RLS skener za to šta treba provjeriti.
Sljedeći koraci
Pokrenite FixVibe sken prema svom produkcijskom URL-u — provjera bundle-secrets je besplatna, bez registracije, i prijavljuje izloženost service_role u manje od minute. Uparite ovo s člankom Supabase RLS skener da biste provjerili da li RLS sloj radi svoj posao, te s Sigurnosnom checklistom za Supabase storage da zaključate pristup fajlovima. Za pozadinu zašto AI alati tako pouzdano generiraju ovu klasu curenja, pročitajte Zašto AI alati za kodiranje ostavljaju sigurnosne propuste.
