FixVibe

// docs / baas security / supabase service role exposure

Cheia service role Supabase expusă în JavaScript: ce înseamnă și cum să o găsești

Cheia service role Supabase este cheia master a bazei tale de date. Oricine o deține ocolește Row-Level Security, poate citi fiecare coloană a fiecărei tabele și poate scrie sau șterge orice. Este concepută să trăiască exclusiv în codul server — niciodată în browser. Când un instrument de codare AI o livrează în bundle-ul JavaScript, baza ta de date este, practic, publică. Acest articol explică forma JWT care identifică o cheie scursă, cele trei tipare de instrumente AI care produc scurgerea, ce să faci în prima oră după detectare și cum să scanezi automat pentru ea înainte ca utilizatorii să o facă.

Ce este cheia service role

Supabase emite două chei distincte pentru fiecare proiect: cheia anon (numită și cheie publicabilă în proiectele mai noi) și cheia service_role. Ambele sunt JSON Web Token-uri semnate cu secretul JWT al proiectului tău. Diferența este claim-ul role încorporat în payload-ul JWT — anon pentru cheia publică, service_role pentru cheia master. PostgREST, Supabase Storage și Supabase Auth comută toate în modul bypass-everything când văd claim-ul service_role.

Decodează orice cheie Supabase la jwt.io și uită-te la payload. Forma unui JWT service-role este inconfundabilă:

Payload-ul decodat al unui JWT service-role (afișat ca un bloc cu evidențiere sintaxă mai jos).

json
{
  "iss": "supabase",
  "ref": "[project-ref]",
  "role": "service_role",
  "iat": 1700000000,
  "exp": 2000000000
}

Proiectele Supabase mai noi emit chei de tip secret cu prefixul sb_secret_ în locul unui JWT. Comportamentul este identic — orice conține sb_secret_ într-un bundle public este la fel de catastrofal.

Cum scurg instrumentele de codare AI cheia service role

Am văzut aceleași trei tipare în mii de aplicații vibe-coded. Fiecare începe cu un dezvoltator care cere ajutor unui instrument AI și se termină cu cheia de serviciu inserată într-un bundle.

Tipar 1: un singur fișier .env cu prefixul NEXT_PUBLIC_

Dezvoltatorul cere instrumentului AI să „configureze Supabase" și acceptă un singur .env cu ambele chei. Instrumentul AI — antrenat pe un corpus în care majoritatea variabilelor de mediu sunt expuse prin NEXT_PUBLIC_* — le prefixează pe ambele cu NEXT_PUBLIC_. Next.js încorporează orice se potrivește cu acel prefix în bundle-ul clientului la build time. Livrează pe Vercel, iar cheia service este în main.[hash].js.

Tipar 2: cheia greșită în apelul createClient

Dezvoltatorul lipește ambele chei într-un fișier config.ts generat de AI, iar AI-ul populează apelul createClient() de pe browser cu process.env.SUPABASE_SERVICE_ROLE_KEY din greșeală. Build-ul preia variabila, iar JWT-ul aterizează în bundle.

Tipar 3: cheia service-role hardcodată în scripturi de seed

Dezvoltatorul cere instrumentului AI să scrie un script care populează baza de date. AI-ul hardcodează cheia service-role direct în fișier (în loc să citească din mediu), face commit fișierului în repository, iar repo-ul GitHub public sau ruta /scripts/seed.js a aplicației deployate servește acum cheia.

Cum detectează scanarea bundle-ului FixVibe scurgerea

Verificarea bundle-secrets a FixVibe descarcă fiecare fișier JavaScript referențiat de aplicația deployată — chunk-uri de intrare, chunk-uri încărcate leneș, web workers, service workers — și le trece printr-un detector care decodează orice se potrivește formei JWT (eyJ[base64-header].eyJ[base64-payload].[signature]). Dacă payload-ul decodat conține "role": "service_role", scanarea o raportează ca un rezultat critic cu calea fișierului și linia exactă unde apare cheia. Aceeași verificare se potrivește și cu noul tipar sb_secret_* după prefix.

Scanarea nu se autentifică niciodată cu cheia descoperită. Identifică forma și raportează scurgerea — utilizarea cheii pentru a dovedi exploatabilitatea ar fi acces neautorizat la baza ta de date. Dovada este în însuși payload-ul JWT.

Detectat — ce să faci în prima oră

O cheie service role scursă este o urgență în producție. Presupune că cheia a fost scrapată — atacatorii monitorizează bundle-urile publice în timp real. Tratează baza de date ca fiind compromisă până când ai rotit cheia și ai auditat activitatea recentă.

  1. Rotește cheia imediat. În Supabase Dashboard, mergi la Project Settings → API → Service role key → Reset. Cheia veche este invalidată în câteva secunde. Orice cod server care folosește cheia trebuie actualizat și redeployat înainte de finalizarea rotației.
  2. Auditează activitatea recentă a bazei de date. Deschide Database → Logs în dashboard. Filtrează ultimele 7 zile. Caută interogări SELECT * neobișnuite împotriva tabelelor cu PII, declarații mari UPDATE sau DELETE și cereri de la IP-uri din afara infrastructurii tale cunoscute. Supabase loghează antetul x-real-ip la fiecare cerere.
  3. Verifică obiectele de stocare. Vizitează Storage → Logs și revizuiește descărcările recente de fișiere. O cheie service-role scursă oferă acces bypass-everything și la bucket-urile private.
  4. Elimină cheia din controlul sursei. Chiar și după rotație, lăsarea JWT-ului în istoricul git înseamnă că este descoperibilă în repo-ul public. Folosește git filter-repo sau BFG Repo-Cleaner pentru a o curăța din istoric, apoi force-push (avertizează colaboratorii mai întâi).
  5. Re-scanează după remediere. Rulează o scanare FixVibe nouă împotriva aplicației redeployate. Rezultatul bundle-secrets ar trebui să dispară. Confirmă că niciun JWT service_role și niciun șir sb_secret_* nu rămâne în vreun chunk.

Prevenirea scurgerii de la bun început

Remedierea structurală este disciplina de numire plus garduri la nivel de instrument:

  • Niciodată să nu prefixezi cheia service cu NEXT_PUBLIC_*, VITE_* sau orice alt prefix de inlining în bundle. Convenția de numire este limita — fiecare framework o respectă.
  • Păstrează cheia service complet în afara .env pe mașina dezvoltatorului. Citește-o dintr-un manager de secrete (Doppler, Infisical, variabile env criptate Vercel) la deploy, niciodată să nu o comiți local.
  • <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.
  • Adaugă un gate CI care scanează output-ul build-ului. După next build, caută în output-ul .next/static/chunks/ șirul service_role. Eșuează build-ul dacă se potrivește ceva.
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

Întrebări frecvente

Cât de repede găsesc atacatorii efectiv cheile service-role Supabase scurse?

Scanerele de bundle-uri publice trag deployment-urile noi în câteva minute. Cercetătorii au documentat exploit-uri funcționale împotriva proiectelor Supabase noi în mai puțin de o oră de la primul deploy. Tratează orice expunere a service-role ca pe o fereastră de 60 de minute, nu de 60 de zile.

Este rotirea cheii suficientă sau trebuie să presupun exfiltrarea datelor?

Rotația invalidează cheia scursă, dar nu anulează datele deja extrase. Dacă tabelele tale conțin PII, date de plată sau orice date reglementate, este posibil să ai o obligație de notificare conform GDPR (72 de ore), CCPA sau HIPAA. Auditează log-urile și consultă consilieri juridici dacă auditul arată acces suspect.

Mă poate proteja RLS dacă scurge cheia service-role?

Nu. Row-Level Security este complet ocolit de claim-ul service_role. Este prin design — cheia există tocmai pentru a permite codului de backend să sară peste RLS pentru operațiuni de admin. Mitigarea este să te asiguri că cheia nu ajunge niciodată într-un context unde un atacator o poate citi.

Se aplică asta noului model de chei publicabile / secret Supabase (<code>sb_publishable_</code> / <code>sb_secret_</code>)?

Da — clasă de risc identică. Cheia sb_secret_* este noul format de cheie secretă care înlocuiește JWT-ul service-role pentru proiectele mai noi. Orice conține sb_secret_* într-un bundle este la fel de catastrofal ca un JWT service-role scurs. Detectorul de bundle-secrets al FixVibe se potrivește cu ambele forme.

Cum rămâne cu cheia anon / publicabilă — este în siguranță în bundle?

Da, prin design. Cheia anon este destinată să trăiască în browser și este ceea ce folosește fiecare client web Supabase. Siguranța ei depinde în totalitate de configurarea corectă a RLS pe fiecare tabelă publică. Vezi articolul Scaner RLS Supabase pentru ce să verifici.

Pași următori

Rulează o scanare FixVibe împotriva URL-ului tău de producție — verificarea bundle-secrets este gratuită, fără înregistrare, și raportează expunerea service_role în mai puțin de un minut. Combină asta cu articolul Scaner RLS Supabase pentru a verifica dacă stratul RLS își face treaba și Lista de verificare pentru securitatea bucket-urilor de stocare Supabase pentru a bloca accesul la fișiere. Pentru context despre de ce instrumentele AI generează această clasă de scurgeri atât de des, citește De ce instrumentele de codare AI lasă lacune de securitate.

// scanează suprafața ta baas

Găsește tabela deschisă înainte să o facă altcineva.

Introdu un URL de producție. FixVibe enumeră furnizorii BaaS cu care comunică aplicația ta, identifică amprenta endpoint-urilor lor publice și raportează ce poate citi sau scrie un client neautentificat. Gratuit, fără instalare, fără card.

  • Plan gratuit — 3 scanări/lună, fără card la înregistrare.
  • Amprentare BaaS pasivă — nu e necesară verificarea domeniului.
  • Supabase, Firebase, Clerk, Auth0, Appwrite și altele.
  • Prompt-uri de remediere AI pe fiecare rezultat — lipește-le înapoi în Cursor / Claude Code.
Rulează o scanare BaaS gratuită

nu necesită înregistrare

Cheia service role Supabase expusă în JavaScript: ce înseamnă și cum să o găsești — Docs · FixVibe