// docs / baas security / supabase service role exposure
Supabase service role ključ izložen u JavaScriptu: što to znači i kako ga pronaći
Supabase service role ključ je glavni ključ vaše baze podataka. Svatko tko ga drži zaobilazi Row-Level Security, može čitati svaki stupac svake tablice te pisati ili brisati što 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 biti, javna. Ovaj članak objašnjava JWT oblik koji identificira procurio ključ, tri obrasca AI alata koji proizvode curenje, što učiniti u prvom satu nakon otkrivanja i kako automatski skenirati za time prije nego što to učine korisnici.
Što je service role ključ
Supabase izdaje dva različita ključa za svaki projekt: 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 propuštaju service role ključ
Vidjeli smo ista tri obrasca u tisućama vibe-coded aplikacija. Svaki počinje time što developer traži pomoć od AI alata, a završava ugrađivanjem service ključa u bundle.
Obrazac 1: Jedna .env datoteka s prefiksom NEXT_PUBLIC_
Developer traži od AI alata da "postavi Supabase" i prihvaća jednu .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 datoteku config.ts koju 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č izravno u datoteku (umjesto čitanja iz environmenta), commitira datoteku u repozitorij i sada javni GitHub repo ili ruta /scripts/seed.js deploy-ane aplikacije poslužuje ključ.
Kako FixVibe bundle sken detektira curenje
FixVibe-ova provjera bundle-secrets preuzima svaku JavaScript datoteku na koju deploy-ana aplikacija referira — 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čan nalaz s putanjom datoteke i toč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 — što učiniti u prvom satu
Procurio service role ključ je runtime hitnost. Pretpostavite da je ključ skrejpan — napadači u stvarnom vremenu prate javne bundleove. Tretirajte bazu kao kompromitiranu sve dok ne rotirate ključ i auditirate nedavnu aktivnost.
- Rotirajte ključ odmah. U Supabase Dashboardu idite na Project Settings → API → Service role key → Reset. Stari ključ poništava se u roku od nekoliko sekundi. Svaki serverski kod koji koristi ključ mora biti ažuriran i ponovno deploy-an prije nego što rotacija stupi na snagu.
- Auditirajte nedavnu aktivnost baze. Otvorite Database → Logs u dashboardu. Filtrirajte zadnjih 7 dana. Tražite neobične upite
SELECT *nad tablicama s PII-jem, velikeUPDATEiliDELETEizjave i zahtjeve s IP adresa izvan vaše poznate infrastrukture. Supabase logira headerx-real-ipna svakom zahtjevu. - Provjerite storage objekte. Posjetite Storage → Logs i pregledajte nedavna preuzimanja datoteka. Procurio 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 povijesti znači da je otkriv u javnom repou. Koristite
git filter-repoili BFG Repo-Cleaner da ga očistite iz povijesti, zatim force-push (prvo upozorite suradnike). - 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.
Sprječavanje curenja od samog početka
Strukturni popravak je disciplina imenovanja plus zaštita na razini 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
.envdatoteke na developerovom stroju. Čitajte ga iz secret managera (Doppler, Infisical, Vercel enkriptirane env varijable) prilikom deploya, nikada ga ne commitirajte 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, grepajte 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 procurene Supabase service-role ključeve?
Skeneri javnih bundleova pretražuju nove deployove u roku od nekoliko minuta. Istraživači su dokumentirali funkcionalne eksploite protiv novih Supabase projekata u manje od sata od prvog deploya. Tretirajte svako izlaganje service-rolea kao 60-minutni prozor, a ne 60-dnevni.
Je li rotacija ključa dovoljna ili moram pretpostaviti eksfiltraciju podataka?
Rotacija poništava procurio ključ, ali ne poništava podatke koji su već povučeni. Ako vaše tablice sadrže PII, podatke o plaćanju ili bilo kakve regulirane podatke, možda imate obvezu obavještavanja prema GDPR-u (72 sata), CCPA-i ili HIPAA-i. Auditirajte logove i konzultirajte 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 u potpunosti se 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 ga napadač može pročitati.
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 procurio service-role JWT. FixVibe-ov detektor bundle-secrets prepoznaje oba oblika.
A što s anon / publishable ključem — je li on siguran u bundleu?
Da, po dizajnu. Anon ključ namijenjen je da postoji u pregledniku i koristi ga svaki Supabase web klijent. Njegova sigurnost ovisi isključivo o ispravnoj konfiguraciji RLS-a na svakoj javnoj tablici. Pogledajte članak Supabase RLS skener za to što treba provjeriti.
Sljedeći koraci
Pokrenite FixVibe sken prema svom produkcijskom URL-u — provjera bundle-secrets besplatna je, bez registracije, i prijavljuje izloženost service_role u manje od minute. Uparite ovo s člankom Supabase RLS skener da provjerite radi li RLS sloj svoj posao, te s Sigurnosnom checklistom za Supabase storage da zaključate pristup datotekama. Za pozadinu zašto AI alati tako pouzdano generiraju ovu klasu curenja, pročitajte Zašto AI alati za kodiranje ostavljaju sigurnosne propuste.
