FixVibe

// docs / baas security / supabase rls scanner

Scanner RLS Supabase: temukan tabel dengan row-level security yang hilang atau rusak

Row-level security (RLS) adalah satu-satunya hal yang berdiri antara data pelanggan Anda dan internet ketika Anda merilis aplikasi berbasis Supabase. AI coding tools menghasilkan kode berbentuk RLS yang ter-compile, terkirim, dan diam-diam membocorkan data β€” tabel dibuat tanpa RLS diaktifkan, policy yang membaca tetapi tidak pernah membatasi, predikat yang membandingkan kolom dengan dirinya sendiri. Artikel ini menunjukkan apa yang dapat dibuktikan scanner RLS Supabase dari luar, empat bentuk RLS rusak yang muncul di aplikasi vibe-coded, dan cara men-scan deployment Anda sendiri dalam kurang dari semenit.

Apa yang dapat dibuktikan scan RLS eksternal

A passive RLS scan looks at your Supabase project the way an anonymous visitor would. It uses only the publishable anon key β€” the same key your browser uses β€” and never authenticates as a user or touches service-role privileges. Anything it can see, an unauthenticated attacker on the internet can see.

Dari luar database, scanner dapat mengonfirmasi hal berikut dengan kepercayaan tinggi:

  • RLS dinonaktifkan pada sebuah tabel. PostgREST mengembalikan baris untuk SELECT anonim ketika RLS mati atau ketika sebuah policy mengizinkannya. Kedua kasus adalah temuan.
  • Role anonim dapat membuat daftar tabel. GET /rest/v1/ dengan anon key mengembalikan skema OpenAPI untuk setiap tabel yang role anon miliki privilege apa pun di dalamnya. Aplikasi yang dihasilkan AI sering memberikan USAGE pada skema dan SELECT pada setiap tabel, yang mengekspos seluruh peta skema bahkan ketika RLS menolak baca yang sebenarnya.
  • Read access does not establish write safety. A passive scan cannot prove that INSERT, UPDATE, or DELETE policies protect every user and tenant. Review write policies and test them with isolated fixtures under the intended roles.
  • Service-role key ada di bundle browser. Berdekatan dengan RLS: jika scanner menemukan SUPABASE_SERVICE_ROLE_KEY atau JWT apa pun dengan role: service_role di bundle JavaScript, RLS tidak relevan β€” pemegang key itu mem-bypass setiap policy.

Apa yang tidak dapat dibuktikan scan eksternal

Jujurlah tentang batasan scanner. Scan RLS eksternal tidak dapat membaca tabel pg_policies Anda, file migrasi Anda, atau predikat persis dari policy apa pun. Ia menyimpulkan dari perilaku black-box, yang berarti kadang-kadang ia akan melaporkan temuan yang ternyata data publik yang disengaja (tabel newsletter pemasaran, katalog produk publik). Laporan FixVibe menandai ini sebagai kepercayaan menengah ketika scanner tidak dapat membedakan niat β€” periksa nama tabel dan putuskan.

Empat bentuk RLS rusak yang dihasilkan AI tools

When you point Cursor, Claude Code, Lovable, or Bolt at Supabase, the same four broken-RLS patterns come up again and again. Each one passes type-check, compiles, and ships:

Bentuk 1: RLS tidak pernah diaktifkan

The most common failure mode. The migration creates the table but the developer (or the AI tool) forgets ALTER TABLE ... ENABLE ROW LEVEL SECURITY. PostgREST happily serves the entire table to anyone with the anon key. Fix: ALTER TABLE public.[name] ENABLE ROW LEVEL SECURITY;, then add a policy per command. Enabling RLS with no policies denies all access through the API; the policies decide who gets in.

sql
ALTER TABLE public.[name] ENABLE ROW LEVEL SECURITY;

Bentuk 2: RLS diaktifkan, tanpa policy

Kegagalan yang lebih halus. RLS diaktifkan tetapi tidak ada policy yang ditulis. Default di PostgreSQL adalah deny, jadi user terautentikasi tidak melihat apa-apa β€” dan pengembang menambahkan USING (true) agar aplikasi bekerja, yang mengizinkan semua orang membaca semuanya. Fix: tulis policy yang dibatasi oleh auth.uid(): CREATE POLICY "select_own" ON public.[name] FOR SELECT USING (auth.uid() = user_id); dan policy INSERT/UPDATE/DELETE yang sepadan.

sql
CREATE POLICY "select_own"
  ON public.[name]
  FOR SELECT
  USING (auth.uid() = user_id);

Bentuk 3: Policy membandingkan kolom dengan dirinya sendiri

Artefak salin-tempel. Pengembang menulis USING (user_id = user_id) β€” yang selalu benar β€” alih-alih USING (auth.uid() = user_id). Type-check lolos; policy mengizinkan setiap baris. Fix: selalu bandingkan kolom dengan pemanggilan fungsi (auth.uid(), auth.jwt()->>'org_id', dll.), tidak pernah dengan dirinya sendiri atau konstanta.

Shape 4: Overly permissive write policies

With RLS enabled, a role with no applicable policy is denied by default. A SELECT policy does not itself allow INSERT. Write exposure can arise from a permissive applicable INSERT or ALL policy, disabled RLS, or a role that bypasses RLS. Fix: inspect table privileges and every applicable policy, use ownership-scoped WITH CHECK conditions, and test writes with separate user identities.

Cara kerja scanner RLS Supabase FixVibe

FixVibe's Supabase check works from the deployed app, in three steps:

  1. Find the project. FixVibe loads the deployed app and reads the Supabase project URL and public key from the same configuration your browser receives. No guessing, no brute force.
  2. See what is exposed. FixVibe checks which tables the anonymous role can see, without reading row data at this step.
  3. Stage 3 β€” inspect anonymous read access. The passive check reports observable access to discovered resources. It does not create, update, or delete database rows, and it cannot establish that all write policies or cross-user boundaries are correct.

Each finding ships with the exact request URL, response status, response shape (header-only), and the table name. FixVibe now labels whether the fix belongs in code/config, a provider console, DNS, secret rotation, or manual review so the next step matches who can actually apply it.

Apa yang harus dilakukan ketika scanner menemukan sesuatu

Setiap temuan RLS adalah keadaan darurat runtime. Endpoint PostgREST publik di-scan oleh penyerang dalam hitungan menit. Urutan remediasi bersifat mekanis:

  1. Audit setiap tabel. Jalankan SELECT schemaname, tablename, rowsecurity FROM pg_tables WHERE schemaname = 'public'; di editor SQL Supabase. Setiap baris dengan rowsecurity = false adalah masalah.
  2. Enable RLS on every public table. Default to ENABLE ROW LEVEL SECURITY on every table created β€” make it a migration template.
  3. Tulis policy command-per-command. Jangan gunakan FOR ALL USING (true). Tulis policy eksplisit untuk SELECT, INSERT, UPDATE, DELETE β€” masing-masing dibatasi pada auth.uid() atau kolom org-id dari auth.jwt().
  4. Verifikasi dengan akun kedua. Daftar sebagai user yang berbeda, coba baca catatan user lain melalui REST API secara langsung. Jika response adalah 200, policy rusak.
  5. Re-scan. After applying the fix, re-run a FixVibe scan against the same URL. The Supabase RLS finding should clear.
sql
-- Audit every table for missing RLS. Run in the Supabase SQL editor.
SELECT schemaname, tablename, rowsecurity
FROM   pg_tables
WHERE  schemaname = 'public'
ORDER  BY rowsecurity, tablename;

Bagaimana ini dibandingkan dengan scanner lain

Sebagian besar tool DAST generik (Burp Suite, OWASP ZAP, Nessus) tidak tahu apa itu PostgREST. Mereka akan meng-crawl aplikasi Anda, mengabaikan path /rest/v1/, dan melaporkan halaman HTML yang mereka pahami. Snyk dan Semgrep adalah tool analisis statis β€” mereka menemukan file migrasi di repo Anda dengan panggilan RLS yang hilang, tetapi tidak dapat membuktikan database yang ter-deploy salah konfigurasi. FixVibe duduk di celah itu: pasif, sadar-BaaS, fokus pada apa yang dapat dibuktikan penyerang tidak terautentikasi dari URL publik.

Pertanyaan yang sering diajukan

Apakah scanner membaca atau memodifikasi data saya?

The passive RLS check is read-only. It examines observable anonymous read access and reports limited evidence. It does not perform database write operations or prove that every user and tenant is correctly isolated.

Apakah ini bekerja jika proyek Supabase saya dijeda atau berada di domain kustom?

Proyek yang dijeda mengembalikan 503 pada setiap request β€” scanner melaporkan proyek sebagai tidak terjangkau. Domain kustom bekerja selama aplikasi yang ter-deploy masih memuat SDK klien Supabase di browser; scanner mengekstrak URL proyek dari bundle bagaimanapun juga.

Bagaimana jika anon key saya dirotasi atau publishable key saya berubah?

Jalankan kembali scan. Scanner mengekstrak ulang key dari bundle saat ini pada setiap run. Rotasi hanya menginvalidasi laporan sebelumnya, bukan keadaan policy database.

Apakah scanner memeriksa model publishable-key Supabase yang baru (sb_publishable_*)?

Ya. Detektor mengenali JWT anon lama dan key sb_publishable_* yang lebih baru, serta memperlakukannya secara identik β€” keduanya dimaksudkan untuk publik dan keduanya menyisakan RLS sebagai satu-satunya garis pertahanan.

Langkah berikutnya

Run a free FixVibe scan against your production URL β€” the Supabase RLS check runs on every plan including the free tier. For a deeper read on what else can leak from a Supabase project, see Supabase service role key exposed in JavaScript and Supabase storage bucket security checklist. For the umbrella view across all BaaS providers, read BaaS misconfiguration scanner.

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

Scanner RLS Supabase: temukan tabel dengan row-level security yang hilang atau rusak Β· FixVibe