// docs / baas security / supabase service role exposure
Supabase service-role-avain paljastunut JavaScriptissä: mitä se tarkoittaa ja kuinka se löydetään
Supabasen service-role-avain on tietokantasi pääavain. Sen haltija ohittaa row-level securityn, voi lukea jokaisen sarakkeen jokaisesta taulusta ja voi kirjoittaa tai poistaa mitä tahansa. Se on suunniteltu elämään ainoastaan palvelinpuolen koodissa — ei koskaan selaimessa. Kun AI-koodaustyökalu toimittaa sen JavaScript-pakettiin, tietokantasi on käytännössä julkinen. Tämä artikkeli selittää JWT-muodon, joka tunnistaa vuotaneen avaimen, kolme AI-työkalukuviota, jotka tuottavat vuodon, mitä tehdä ensimmäisen tunnin aikana havaitsemisen jälkeen, ja kuinka sitä skannataan automaattisesti ennen kuin käyttäjät tekevät sen.
Mikä service-role-avain on
Supabase myöntää kaksi erillistä avainta jokaiselle projektille: anon-avaimen (jota uudemmissa projekteissa kutsutaan myös julkaistavaksi avaimeksi) ja service_role-avaimen. Molemmat ovat JSON Web Tokeneita, jotka on allekirjoitettu projektisi JWT-salaisuudella. Ero on role-claimissa, joka on leivottu JWT-payloadiin — anon julkiselle avaimelle, service_role pääavaimelle. PostgREST, Supabase Storage ja Supabase Auth siirtyvät kaikki ohita-kaikki-tilaan, kun ne näkevät service_role-claimin.
Dekoodaa mikä tahansa Supabase-avain osoitteessa jwt.io ja katso payloadia. Service-role-JWT:n muoto on erehtymätön:
Dekoodattu service-role-JWT:n payload (näytetään syntaksikorostuneena lohkona alla).
{
"iss": "supabase",
"ref": "[project-ref]",
"role": "service_role",
"iat": 1700000000,
"exp": 2000000000
}Uudemmat Supabase-projektit myöntävät secret-tyyppisiä avaimia, joiden etuliite on sb_secret_ JWT:n sijasta. Käyttäytyminen on identtistä — mikä tahansa, jossa on sb_secret_ julkisessa paketissa, on yhtä katastrofaalista.
Miten AI-koodaustyökalut vuotavat service-role-avaimen
Olemme nähneet samat kolme kuviota tuhansissa vibe-koodatuissa sovelluksissa. Jokainen alkaa siitä, että kehittäjä pyytää AI-työkalulta apua, ja päättyy siihen, että service-avain on inlinattu pakettiin.
Kuvio 1: Yksi .env-tiedosto NEXT_PUBLIC_-etuliitteellä
Kehittäjä pyytää AI-työkalua "asentamaan Supabasen" ja hyväksyy yhden .env:n molemmilla avaimilla. AI-työkalu — koulutettu korpuksella, jossa useimmat ympäristömuuttujat paljastuvat NEXT_PUBLIC_*:n kautta — etuliittää molemmat NEXT_PUBLIC_:lla. Next.js inlinaa kaiken, mikä vastaa tuota etuliitettä, klienttipakettiin käännösaikana. Julkaise Verceliin, ja service-avain on main.[hash].js:ssä.
Kuvio 2: Väärä avain createClient-kutsussa
Kehittäjä liittää molemmat avaimet AI:n generoimaan config.ts-tiedostoon, ja AI täyttää vahingossa selainpuolen createClient()-kutsun arvolla process.env.SUPABASE_SERVICE_ROLE_KEY. Käännös vetää muuttujan sisään, ja JWT päätyy pakettiin.
Kuvio 3: Service-role-avain kovakoodattu seed-skripteihin
Kehittäjä pyytää AI-työkalua kirjoittamaan skriptin, joka seedaa tietokannan. AI kovakoodaa service-role-avaimen suoraan tiedostoon (sen sijaan että lukisi ympäristöstä), committaa tiedoston repoon, ja julkinen GitHub-repo tai julkaistun sovelluksen /scripts/seed.js-reitti tarjoilee nyt avaimen.
Kuinka FixVibe-pakettiskannaus havaitsee vuodon
FixVibe-bundle-secrets-tarkistus lataa jokaisen JavaScript-tiedoston, johon julkaistu sovellus viittaa — entry-chunkit, lazy-ladatut chunkit, web workerit, service workerit — ja ajaa ne tunnistimen läpi, joka dekoodaa kaiken, mikä vastaa JWT-muotoa (eyJ[base64-header].eyJ[base64-payload].[signature]). Jos dekoodattu payload sisältää "role": "service_role":n, skannaus raportoi sen kriittisenä löydöksenä tiedostopolun ja tarkan rivin kanssa, jolla avain ilmestyy. Sama tarkistus täsmää myös uudemman sb_secret_*-kuvion etuliitteen perusteella.
Skannaus ei koskaan autentikoidu löydetyllä avaimella. Se tunnistaa muodon ja raportoi vuodon — avaimen käyttäminen hyödynnettävyyden todistamiseen olisi luvatonta pääsyä tietokantaasi. Todiste on JWT-payloadissa itsessään.
Havaittu — mitä tehdä ensimmäisen tunnin aikana
Vuotanut service-role-avain on ajonaikainen hätätilanne. Oleta, että avain on jo kerätty — hyökkääjät tarkkailevat julkisia paketteja reaaliajassa. Käsittele tietokantaa kompromettoituneena, kunnes olet rotatoinut avaimen ja tarkastanut viimeaikaisen toiminnan.
- Rotatoi avain välittömästi. Supabase-dashboardissa mene kohtaan Project Settings → API → Service role key → Reset. Vanha avain mitätöidään sekunneissa. Kaikki palvelinpuolen koodi, joka käyttää avainta, on päivitettävä ja julkaistava uudelleen ennen kuin rotaatio astuu voimaan.
- Tarkasta viimeaikainen tietokantatoiminta. Avaa Database → Logs dashboardissa. Suodata viimeisten 7 päivän mukaan. Etsi epätavallisia
SELECT *-kyselyitä PII:tä sisältäviä tauluja vastaan, suuriaUPDATE- taiDELETE-lauseita ja pyyntöjä IP-osoitteista, jotka eivät kuulu tunnettuun infrastruktuuriisi. Supabase kirjaax-real-ip-headerin jokaiseen pyyntöön. - Tarkista storage-objektit. Käy Storage → Logs ja tarkastele viimeaikaisia tiedostojen latauksia. Vuotanut service-role-avain antaa ohita-kaikki-pääsyn myös yksityisiin bucketteihin.
- Poista avain versionhallinnasta. Jopa rotaation jälkeen JWT:n jättäminen git-historiaan tarkoittaa, että se on löydettävissä julkisesta reposta. Käytä
git filter-repo:a tai BFG Repo-Cleaneria pyyhkimään se historiasta, sitten force-push (varoita yhteistyökumppaneita ensin). - Skannaa uudelleen korjauksen jälkeen. Aja uusi FixVibe-skannaus uudelleenjulkaistua sovellusta vastaan. Bundle-secrets-löydöksen pitäisi kadota. Vahvista, että mitään
service_role-JWT:tä eikäsb_secret_*-merkkijonoa ei jää mihinkään chunkkiin.
Vuodon estäminen ennakolta
Rakenteellinen ratkaisu on nimeämisdisipliini sekä työkalutason suojakaiteet:
- Älä koskaan etuliitä service-avainta
NEXT_PUBLIC_*:lla,VITE_*:lla tai millään muulla bundle-inlinaavalla etuliitteellä. Nimeämiskonventio on raja — jokainen kehys kunnioittaa sitä. - Pidä service-avain kokonaan poissa
.env:stä kehittäjäkoneella. Lue se salaisuudenhallintajärjestelmästä (Doppler, Infisical, Vercelin salatut env-muuttujat) julkaisussa, älä koskaan committaa sitä paikallisesti. - <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.
- Lisää CI-gate, joka skannaa käännös-outputin. Komennon
next buildjälkeen grepaa.next/static/chunks/-output etsienservice_role-merkkijonoa. Anna käännöksen epäonnistua, jos jokin täsmää.
# 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 1Usein kysytyt kysymykset
Kuinka nopeasti hyökkääjät tosiasiassa löytävät vuotaneet Supabase service-role-avaimet?
Julkisten pakettien skannerit haravoivat uudet julkaisut minuuteissa. Tutkijat ovat dokumentoineet toimivia exploitteja uusia Supabase-projekteja vastaan alle tunnissa ensimmäisestä julkaisusta. Käsittele jokaista service-role-paljastumista 60-minuutin ikkunana, ei 60-päivän.
Riittääkö avaimen rotatointi, vai täytyykö olettaa datan eksfiltraatio?
Rotaatio mitätöi vuotaneen avaimen mutta ei peruuta jo vedettyä dataa. Jos taulusi sisältävät PII:tä, maksudataa tai mitä tahansa säänneltyä dataa, sinulla saattaa olla ilmoitusvelvollisuus GDPR:n (72 tuntia), CCPA:n tai HIPAA:n alaisuudessa. Tarkasta lokit ja konsultoi juridista neuvonantajaa, jos tarkastus näyttää epäilyttävää käyttöä.
Voiko RLS suojata minua, jos service-role-avain vuotaa?
Ei. Row-level security ohitetaan kokonaan service_role-claimilla. Se on by design — avain on olemassa juuri sitä varten, että backend-koodi voi ohittaa RLS:n hallintaoperaatioissa. Lieventäminen tapahtuu varmistamalla, että avain ei koskaan päädy kontekstiin, jossa hyökkääjä voi lukea sen.
Päteekö tämä uuteen Supabase julkaistava-/secret-avain-malliin (<code>sb_publishable_</code> / <code>sb_secret_</code>)?
Kyllä — identtinen riskiluokka. sb_secret_*-avain on uusi secret-avain-muoto, joka korvaa service-role-JWT:n uudemmissa projekteissa. Mikä tahansa, joka kantaa sb_secret_*:ta paketissa, on yhtä katastrofaalista kuin vuotanut service-role-JWT. FixVibe-bundle-secrets-tunnistin täsmää molempia muotoja.
Entä anon-/julkaistava-avain — onko se turvallinen paketissa?
Kyllä, by design. Anon-avain on tarkoitettu elämään selaimessa, ja sitä jokainen Supabase-webklientti käyttää. Sen turvallisuus riippuu kokonaan siitä, että RLS on oikein konfiguroitu jokaiseen julkiseen tauluun. Katso artikkeli Supabase RLS -skanneri siitä, mitä tarkistaa.
Seuraavat askeleet
Aja FixVibe-skannaus tuotanto-URL:ääsi vastaan — bundle-secrets-tarkistus on ilmainen, ei rekisteröitymistä, ja raportoi service_role-paljastumisen alle minuutissa. Yhdistä tämä artikkeliin Supabase RLS -skanneri varmistaaksesi, että RLS-kerros tekee tehtävänsä, ja artikkeliin Supabasen storage-bucketin tietoturvatarkistuslista lukitaksesi tiedostojen pääsyn. Taustaksi siitä, miksi AI-työkalut tuottavat tämän vuotoluokan niin luotettavasti, lue Miksi AI-koodaustyökalut jättävät tietoturva-aukkoja.
