FixVibe

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

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

  1. 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.
  2. Auditujte nedavnu aktivnost baze. Otvorite Database → Logs u dashboardu. Filtrirajte zadnjih 7 dana. Tražite neobične upite SELECT * nad tabelama s PII-jem, velike UPDATE ili DELETE izjave i zahtjeve s IP adresa izvan vaše poznate infrastrukture. Supabase loguje header x-real-ip na svakom zahtjevu.
  3. Provjerite storage objekte. Posjetite Storage → Logs i pregledajte nedavna preuzimanja fajlova. Procurjeli 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 historiji znači da je otkriv u javnom repou. Koristite git filter-repo ili BFG Repo-Cleaner da ga uklonite iz historije, zatim force-push (prvo upozorite saradnike).
  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.

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 .env fajla 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 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 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.

// skenirajte svoju baas površinu

Pronađite otvorenu tabelu prije nego što to neko drugi učini.

Ubacite produkcijski URL. FixVibe nabraja BaaS providere s kojima vaša aplikacija razgovara, fingerprintira njihove javne endpointe i prijavljuje šta 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 nazad u Cursor / Claude Code.
Pokrenite besplatni BaaS sken

registracija nije potrebna

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