FixVibe

// docs / baas security / supabase service role exposure

Supabase service role key terekspos di JavaScript: apa artinya dan cara menemukannya

Service role key Supabase adalah kunci master ke database Anda. Siapa saja yang memegangnya mem-bypass Row-Level Security, dapat membaca setiap kolom dari setiap tabel, dan dapat menulis atau menghapus apa pun yang mereka pilih. Ia dirancang untuk hidup secara eksklusif di kode sisi server β€” tidak pernah di browser. Ketika AI coding tool mengirimkannya ke bundle JavaScript, database Anda, secara efektif, bersifat publik. Artikel ini menjelaskan bentuk JWT yang mengidentifikasi key yang bocor, tiga pola AI tool yang menghasilkan kebocoran, apa yang harus dilakukan pada jam pertama setelah deteksi, dan cara men-scan secara otomatis sebelum pengguna melakukannya.

Apa itu service role key

Supabase menerbitkan dua key berbeda untuk setiap proyek: key anon (juga disebut publishable key di proyek yang lebih baru) dan key service_role. Keduanya adalah JSON Web Token yang ditandatangani oleh JWT secret proyek Anda. Perbedaannya adalah claim role yang dipanggang ke dalam payload JWT β€” anon untuk key publik, service_role untuk kunci master. PostgREST, Supabase Storage, dan Supabase Auth semuanya beralih ke mode bypass-segalanya ketika mereka melihat claim service_role.

Decode key Supabase apa pun di jwt.io dan lihat payload-nya. Bentuk JWT service-role tidak salah lagi:

Payload yang ter-decode dari JWT service-role (ditampilkan sebagai blok dengan syntax highlight di bawah).

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

Proyek Supabase yang lebih baru menerbitkan key bergaya rahasia dengan prefix sb_secret_ alih-alih JWT. Perilakunya identik β€” apa pun yang membawa sb_secret_ di bundle publik sama-sama katastrofis.

Bagaimana AI coding tools membocorkan service role key

The same three patterns account for most leaks. Each one starts with a developer asking an AI tool for help and ends with the service key inlined into a bundle.

Pola 1: File .env tunggal dengan prefix NEXT_PUBLIC_

Pengembang meminta AI tool untuk "menyiapkan Supabase" dan menerima satu .env dengan kedua key. AI tool β€” dilatih pada korpus di mana sebagian besar environment variable diekspos via NEXT_PUBLIC_* β€” memberi prefix NEXT_PUBLIC_ pada keduanya. Next.js meng-inline apa pun yang cocok dengan prefix itu ke dalam bundle klien pada build time. Kirim ke Vercel, dan service key ada di main.[hash].js.

Pola 2: Key salah dalam panggilan createClient

Pengembang menempelkan kedua key ke file config.ts yang dihasilkan AI, dan AI mengisi panggilan createClient() sisi browser dengan process.env.SUPABASE_SERVICE_ROLE_KEY karena keliru. Build menarik variabel itu, dan JWT mendarat di bundle.

Pola 3: Service role key di-hardcode di skrip seed

Pengembang meminta AI tool untuk menulis skrip yang men-seed database. AI meng-hardcode service role key langsung ke dalam file (alih-alih membaca dari environment), commit file ke repositori, dan repo GitHub publik atau route /scripts/seed.js aplikasi yang ter-deploy sekarang menyajikan key.

Cara scan bundle FixVibe mendeteksi kebocoran

FixVibe inspects every JavaScript file the deployed app ships β€” including lazy-loaded chunks and workers β€” and reports a Supabase service-role key or secret key (sb_secret_*) as a critical finding, with the file and line where it appears.

Scan tidak pernah berautentikasi dengan key yang ditemukan. Ia mengidentifikasi bentuk dan melaporkan kebocoran β€” menggunakan key untuk membuktikan eksploitabilitas akan menjadi akses tidak sah ke database Anda. Buktinya ada di payload JWT itu sendiri.

Terdeteksi β€” apa yang harus dilakukan di jam pertama

Service role key yang bocor adalah keadaan darurat runtime. Asumsikan key telah di-scrape β€” penyerang memantau bundle publik secara real time. Perlakukan database sebagai terkompromi sampai Anda telah merotasi key dan mengaudit aktivitas terkini.

  1. Rotasi key segera. Di Dashboard Supabase, masuk ke Project Settings β†’ API β†’ Service role key β†’ Reset. Key lama diinvalidasi dalam hitungan detik. Setiap kode sisi server yang menggunakan key harus diperbarui dan di-deploy ulang sebelum rotasi mendarat.
  2. Audit aktivitas database terkini. Buka Database β†’ Logs di dashboard. Filter pada 7 hari terakhir. Cari query SELECT * tidak biasa terhadap tabel dengan PII, statement UPDATE atau DELETE besar, dan request dari IP di luar infrastruktur yang Anda kenal. Supabase mencatat header x-real-ip pada setiap request.
  3. Periksa objek storage. Kunjungi Storage β†’ Logs dan tinjau unduhan file terkini. Service role key yang bocor memberikan akses bypass-segalanya ke bucket privat juga.
  4. Hapus key dari source control. Bahkan setelah rotasi, meninggalkan JWT di history git Anda berarti ia dapat ditemukan di repo publik. Gunakan git filter-repo atau BFG Repo-Cleaner untuk membersihkannya dari history, kemudian force-push (peringatkan kolaborator terlebih dahulu).
  5. Scan ulang setelah perbaikan. Jalankan scan FixVibe baru terhadap aplikasi yang di-deploy ulang. Temuan bundle-secrets seharusnya hilang. Konfirmasi tidak ada JWT service_role dan tidak ada string sb_secret_* yang tersisa di chunk mana pun.

Mencegah kebocoran sejak awal

Perbaikan struktural adalah disiplin penamaan ditambah pengaman di tingkat tool:

  • Jangan pernah memberi prefix service key dengan NEXT_PUBLIC_*, VITE_*, atau prefix bundle-inlining lainnya. Konvensi penamaan adalah batasnya β€” setiap framework menghormatinya.
  • Jauhkan service key sepenuhnya dari .env di mesin pengembang. Baca dari secret manager (Doppler, Infisical, env vars terenkripsi Vercel) saat deploy, jangan pernah commit secara lokal.
  • Tandai setiap konstruksi klien Supabase dengan konteks eksplisit. File bernama supabase/browser.ts menggunakan anon key; file bernama supabase/server.ts menggunakan service-role key dengan import 'server-only' di bagian atas. Import server-only menyebabkan error build jika komponen klien mencoba memakai modul tersebut.
  • Tambahkan pre-commit hook yang melakukan grep untuk string berbentuk JWT. git diff --staged | grep -E 'eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+' menangkap baik token anon maupun service sebelum mereka meninggalkan mesin Anda.
  • Tambahkan gate CI yang men-scan output build. Setelah next build, grep output .next/static/chunks/ untuk string service_role. Gagalkan build jika ada yang cocok.
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

Pertanyaan yang sering diajukan

Seberapa cepat penyerang benar-benar menemukan service-role key Supabase yang bocor?

Scanner bundle publik menjelajahi deployment baru dalam hitungan menit. Peneliti telah mendokumentasikan eksploit yang berfungsi terhadap proyek Supabase baru dalam waktu kurang dari satu jam sejak deploy pertama. Perlakukan setiap eksposur service-role sebagai jendela 60 menit, bukan 60 hari.

Apakah merotasi key cukup, atau saya harus mengasumsikan eksfiltrasi data?

Rotasi menginvalidasi key yang bocor tetapi tidak membatalkan data yang sudah ditarik. Jika tabel Anda berisi PII, data pembayaran, atau data yang diatur, Anda mungkin memiliki kewajiban pemberitahuan di bawah GDPR (72 jam), CCPA, atau HIPAA. Audit log dan konsultasikan dengan penasihat hukum jika audit menunjukkan akses mencurigakan.

Dapatkah RLS melindungi saya jika service-role key bocor?

Tidak. Row-Level Security sepenuhnya di-bypass oleh claim service_role. Itu disengaja β€” key ada justru untuk membiarkan kode backend melewati RLS untuk operasi admin. Mitigasinya adalah memastikan key tidak pernah mencapai konteks di mana penyerang dapat membacanya.

Apakah ini berlaku untuk model publishable / secret key Supabase yang baru (sb_publishable_ / sb_secret_)?

Ya β€” kelas risiko yang identik. Key sb_secret_* adalah format secret-key baru yang menggantikan JWT service-role untuk proyek yang lebih baru. Apa pun yang membawa sb_secret_* di bundle sama katastrofisnya dengan JWT service-role yang bocor. Detektor bundle-secrets FixVibe mencocokkan kedua bentuk.

Bagaimana dengan key anon / publishable β€” apakah aman di bundle?

Ya, secara desain. Anon key dimaksudkan untuk hidup di browser dan adalah yang digunakan setiap klien web Supabase. Keamanannya sepenuhnya bergantung pada RLS yang dikonfigurasi dengan benar pada setiap tabel publik. Lihat artikel Scanner RLS Supabase untuk apa yang harus diperiksa.

Langkah berikutnya

Jalankan scan FixVibe terhadap URL produksi Anda β€” check bundle-secrets gratis, tanpa pendaftaran, dan melaporkan eksposur service_role dalam waktu kurang dari semenit. Pasangkan ini dengan artikel Scanner RLS Supabase untuk memverifikasi lapisan RLS bekerja dengan baik, dan Checklist keamanan bucket storage Supabase untuk mengunci akses file. Untuk latar belakang mengapa AI tools menghasilkan kelas kebocoran ini dengan begitu andal, baca Mengapa AI coding tools meninggalkan celah keamanan.

// scan permukaan baas anda

Temukan tabel terbuka itu sebelum orang lain menemukannya.

Masukkan URL produksi. FixVibe mengenumerasi penyedia BaaS yang berkomunikasi dengan aplikasi Anda, mengidentifikasi endpoint publiknya, dan melaporkan apa yang dapat dibaca atau ditulis oleh klien yang tidak terautentikasi. Gratis, tanpa instalasi, tanpa kartu.

  • Tier gratis β€” 3 scan / bulan, tanpa kartu untuk pendaftaran.
  • Fingerprinting BaaS pasif β€” tidak perlu verifikasi domain.
  • Supabase, Firebase, Clerk, Auth0, Appwrite, dan lainnya.
  • Coding-agent prompts where code/config applies, plus provider-console steps for hosted BaaS fixes.
Jalankan scan BaaS gratis β†’

tidak perlu pendaftaran

Supabase service role key terekspos di JavaScript: apa artinya dan cara menemukannya Β· FixVibe