FixVibe

// 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).

json
{
  "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.

  1. 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.
  2. Auditirajte nedavnu aktivnost baze. Otvorite Database → Logs u dashboardu. Filtrirajte zadnjih 7 dana. Tražite neobične upite SELECT * nad tablicama s PII-jem, velike UPDATE ili DELETE izjave i zahtjeve s IP adresa izvan vaše poznate infrastrukture. Supabase logira header x-real-ip na svakom zahtjevu.
  3. Provjerite storage objekte. Posjetite Storage → Logs i pregledajte nedavna preuzimanja datoteka. Procurio service-role ključ daje bypass-everything pristup i privatnim bucketima.
  4. 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-repo ili BFG Repo-Cleaner da ga očistite iz povijesti, zatim force-push (prvo upozorite suradnike).
  5. Ponovo skenirajte nakon popravka. Pokrenite svjež FixVibe sken prema redeploy-anoj aplikaciji. Nalaz bundle-secrets trebao bi nestati. Potvrdite da nijedan service_role JWT i nijedan string sb_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 .env datoteke 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 string service_role. Neuspjeh buildanja ako se nešto poklopi.
bash
# 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.

// skenirajte svoju baas površinu

Pronađite otvorenu tablicu prije nego što to učini netko drugi.

Ubacite produkcijski URL. FixVibe nabraja BaaS providere s kojima vaša aplikacija razgovara, fingerprintira njihove javne endpointe i prijavljuje što neautenticirani klijent može čitati ili pisati. Besplatno, bez instalacije, bez kartice.

  • Besplatni paket — 3 skena mjesečno, bez kartice pri registraciji.
  • Pasivno BaaS fingerprintiranje — bez potrebe za verifikacijom domene.
  • Supabase, Firebase, Clerk, Auth0, Appwrite i još mnogo toga.
  • AI prompti za popravak na svakom nalazu — zalijepite natrag u Cursor / Claude Code.
Pokrenite besplatni BaaS sken

registracija nije potrebna

Supabase service role ključ izložen u JavaScriptu: što to znači i kako ga pronaći — Docs · FixVibe