// docs / baas security / supabase rls scanner
Supabase RLS scanner៖ រកតារាងដែលខ្វះ ឬមាន row-level security ខូច
Row-level security (RLS) គឺជារបាំងតែមួយគត់ដែលឈរនៅចន្លោះទិន្នន័យអតិថិជនរបស់អ្នក និងអ៊ីនធឺណិតនៅពេលអ្នកដាក់ឱ្យដំណើរការកម្មវិធីដែលគាំទ្រដោយ Supabase។ ឧបករណ៍សរសេរកូដ AI បង្កើតកូដរូបរាង RLS ដែល compile បាន, ដាក់ឱ្យដំណើរការ និងធ្វើឱ្យទិន្នន័យលេចធ្លាយដោយស្ងៀមស្ងាត់ — តារាងបង្កើតដោយមិនបានបើក RLS, policy ដែលអាន តែមិនដែលរឹតបន្តឹង, predicate ដែលប្រៀបធៀបជួរឈរនឹងខ្លួនវាផ្ទាល់។ អត្ថបទនេះបង្ហាញពីអ្វីដែល Supabase RLS scanner អាចបញ្ជាក់បានពីខាងក្រៅ, ទម្រង់ RLS ខូចបួនបែបដែលលេចឡើងនៅក្នុងកម្មវិធី vibe-coded និងរបៀប scan deployment ផ្ទាល់ខ្លួនរបស់អ្នកក្នុងរយៈពេលក្រោម 1 នាទី។
អ្វីដែលការ scan RLS ខាងក្រៅអាចបញ្ជាក់បាន
ការ scan RLS បែប passive ដំណើរការប្រឆាំងនឹង PostgREST endpoint ដែល Supabase ផ្ដល់នៅ https://[project].supabase.co/rest/v1/។ វាប្រើតែ anon key ដែលអាចបោះពុម្ពផ្សាយបាន — key ដូចគ្នាដែល browser របស់អ្នកប្រើ — និងត្រួតពិនិត្យ metadata រាយតារាង, ការអានបែប anonymous និងការសរសេរបែប anonymous។ វាមិនដែល authenticate ជាអ្នកប្រើ និងមិនដែលប៉ះសិទ្ធិ service-role។ អ្វីដែលវាអាចធ្វើបាន អ្នកវាយប្រហារដែលមិនបាន authenticate នៅលើអ៊ីនធឺណិតក៏អាចធ្វើបានដែរ។
ពីខាងក្រៅ database, scanner អាចបញ្ជាក់ដូចខាងក្រោមដោយមានទំនុកចិត្តខ្ពស់៖
- RLS ត្រូវបានបិទនៅលើតារាង។ PostgREST ត្រឡប់ rows សម្រាប់
SELECTបែប anonymous នៅពេល RLS បិទ ឬនៅពេល policy អនុញ្ញាត។ ករណីណាមួយក៏ជា finding ដែរ។ - role anonymous អាចរាយតារាងបាន។
GET /rest/v1/ជាមួយ anon key ត្រឡប់ OpenAPI schema សម្រាប់រាល់តារាងដែល roleanonមានសិទ្ធិណាមួយលើ។ កម្មវិធីបង្កើតដោយ AI ច្រើនតែផ្ដល់USAGEលើ schema និងSELECTលើគ្រប់តារាង ដែលលាតត្រដាងផែនទី schema ពេញលេញ ទោះបី RLS បដិសេធការអានពិតប្រាកដក៏ដោយ។ - role anonymous អាច insert បាន។
POSTប្រៀបធៀបជាមួយការទាយរូបរាងជួរឈរនឹងជោគជ័យបើ RLS គ្មានINSERTpolicy បដិសេធវា — សូម្បីតែSELECTត្រូវបានចាក់សោក៏ដោយ។ - service-role key ស្ថិតក្នុង bundle browser។ ជាប់នឹង RLS៖ បើ scanner រកឃើញ
SUPABASE_SERVICE_ROLE_KEYឬ JWT ណាមួយដែលមានrole: service_roleនៅក្នុង JavaScript bundle, RLS គ្មានន័យអ្វីទេ — អ្នកកាន់ key នោះរំលង policy ទាំងអស់។
អ្វីដែលការ scan ខាងក្រៅមិនអាចបញ្ជាក់បាន
ត្រូវនិយាយត្រង់អំពីព្រំដែនរបស់ scanner។ ការ scan RLS ខាងក្រៅមិនអាចអានតារាង pg_policies របស់អ្នក, ឯកសារ migration របស់អ្នក ឬ predicate ពិតប្រាកដនៃ policy ណាមួយឡើយ។ វាសន្និដ្ឋានពីឥរិយាបថ black-box ដែលមានន័យថា ពេលខ្លះវានឹងរាយការណ៍ finding ដែលប្រែជាទិន្នន័យសាធារណៈដែលមានចេតនា (តារាង marketing newsletter, កាតាឡុកផលិតផលសាធារណៈ)។ របាយការណ៍ FixVibe សម្គាល់ទាំងនេះថាជា medium confidence នៅពេល scanner មិនអាចបែងចែកចេតនា — ពិនិត្យឈ្មោះតារាង និងសម្រេចចិត្ត។
ទម្រង់ RLS ខូចបួនបែបដែលឧបករណ៍ AI បង្កើត
នៅពេលអ្នកដាក់ Cursor, Claude Code, Lovable ឬ Bolt ទៅលើ Supabase, លំនាំ RLS ខូចបួនបែបដូចគ្នាលេចឡើងនៅទូទាំងកម្មវិធីរាប់ពាន់។ មួយៗឆ្លងកាត់ type-check, compile និង ship៖
ទម្រង់ទី 1៖ RLS មិនដែលត្រូវបានបើក
របៀបបរាជ័យសាមញ្ញបំផុត។ migration បង្កើតតារាង តែអ្នកអភិវឌ្ឍន៍ (ឬឧបករណ៍ AI) ភ្លេច ALTER TABLE ... ENABLE ROW LEVEL SECURITY។ PostgREST យ៉ាងរីករាយបម្រើតារាងទាំងមូលដល់នរណាក៏ដោយដែលមាន anon key។ ដំណោះស្រាយ៖ ALTER TABLE public.[name] ENABLE ROW LEVEL SECURITY; ALTER TABLE public.[name] FORCE ROW LEVEL SECURITY;។ FORCE មិនមែនជាជម្រើស — ដោយគ្មានវា ម្ចាស់តារាង (និង role ណាមួយដែលមានភាពជាម្ចាស់តារាង) រំលង RLS។
ALTER TABLE public.[name] ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.[name] FORCE ROW LEVEL SECURITY;ទម្រង់ទី 2៖ RLS បានបើក, គ្មាន policy
ការបរាជ័យដែលស្រាលជាង។ RLS ត្រូវបានបើក តែគ្មាន policy ត្រូវបានសរសេរ។ លំនាំដើមនៅក្នុង PostgreSQL គឺ deny, ដូច្នេះអ្នកប្រើ authenticated មើលឃើញគ្មានអ្វី — ហើយអ្នកអភិវឌ្ឍន៍បន្ថែម USING (true) ដើម្បីធ្វើឱ្យកម្មវិធីដំណើរការ ដែលអនុញ្ញាតឱ្យគ្រប់គ្នាអានគ្រប់យ៉ាង។ ដំណោះស្រាយ៖ សរសេរ policy ដែលកំណត់ scope តាម auth.uid()៖ CREATE POLICY "select_own" ON public.[name] FOR SELECT USING (auth.uid() = user_id); និង policy INSERT/UPDATE/DELETE ដែលត្រូវគ្នា។
CREATE POLICY "select_own"
ON public.[name]
FOR SELECT
USING (auth.uid() = user_id);ទម្រង់ទី 3៖ Policy ប្រៀបធៀបជួរឈរនឹងខ្លួនវាផ្ទាល់
A copy-paste artefact. The developer writes <code>USING (user_id = user_id)</code> — which is always true — instead of <code>USING (auth.uid() = user_id)</code>. Type-checks pass; the policy permits every row. <strong>Fix:</strong> always compare a column to a function call (<code>auth.uid()</code>, <code>auth.jwt()->>'org_id'</code>, etc.), never to itself or to a constant.
ទម្រង់ទី 4៖ Policy នៅ SELECT តែមិននៅ INSERT/UPDATE
អ្នកអភិវឌ្ឍន៍ចាក់សោការអាន តែភ្លេចការសរសេរ។ RLS policy គឺផ្អែកលើ command។ FOR SELECT ការពារតែការអាន; client anonymous នៅតែអាច INSERT បានបើគ្មាន policy បដិសេធវា។ ដំណោះស្រាយ៖ សរសេរ policy តាម command មួយៗ ឬប្រើ FOR ALL ជាមួយ USING និង WITH CHECK ច្បាស់លាស់។
របៀបដែល FixVibe Supabase RLS scanner ដំណើរការ
ការត្រួតពិនិត្យ baas.supabase-rls ដំណើរការក្នុងបីដំណាក់កាល ដោយមានកម្រិតទំនុកចិត្តច្បាស់លាស់៖
- ដំណាក់កាលទី 1 — fingerprint។ Scanner crawl កម្មវិធីដែលបាន deploy, ញែក JavaScript bundle របស់វា និងស្រង់ Supabase project URL និង anon key ពីការកំណត់រចនាសម្ព័ន្ធ runtime។ គ្មាន DNS guessing, គ្មាន brute force — វាអានអ្វីដែល browser អាន។
- ដំណាក់កាលទី 2 — រកឃើញ schema។
GET /rest/v1/តែមួយជាមួយ anon key ត្រឡប់ OpenAPI schema សម្រាប់រាល់តារាងដែល anon role អាចមើលឃើញ។ Scanner កត់ត្រាឈ្មោះតារាង តែមិនអានទិន្នន័យ row នៅដំណាក់កាលនេះ។ - ដំណាក់កាលទី 3 — អាន និងសរសេរ probe។ សម្រាប់រាល់តារាងដែលរកឃើញ, scanner ផ្ញើ
SELECTanonymous មួយជាមួយlimit=1។ បើ rows ត្រឡប់, RLS អនុញ្ញាត។ Scanner ឈប់នៅទីនោះ — វាមិនរាប់ rows, មិន paginate, មិនកែប្រែទិន្នន័យ។ INSERT probe ត្រូវបានរារាំងនៅពីក្រោយការផ្ទៀងផ្ទាត់ភាពជាម្ចាស់ domain និង opt-in ច្បាស់លាស់; ពួកវាមិនដែលដំណើរការប្រឆាំងនឹង target ដែលមិនបានផ្ទៀងផ្ទាត់។
Finding នីមួយៗមកជាមួយ URL request ពិតប្រាកដ, status response, រូបរាង response (header តែប៉ុណ្ណោះ) និងឈ្មោះតារាង។ AI fix prompt នៅខាងក្រោម finding គឺជា SQL block copy-paste ដែលអ្នកដំណើរការនៅក្នុង Supabase SQL editor។
អ្វីដែលត្រូវធ្វើនៅពេល scanner រកឃើញអ្វីមួយ
រាល់ RLS finding គឺជាគ្រោះមហន្តរាយ runtime។ PostgREST endpoint សាធារណៈត្រូវបាន scan ដោយអ្នកវាយប្រហារក្នុងរយៈពេលប៉ុន្មាននាទី។ លំដាប់ដោះស្រាយគឺមេកានិច៖
- ត្រួតពិនិត្យរាល់តារាង។ ដំណើរការ
SELECT schemaname, tablename, rowsecurity FROM pg_tables WHERE schemaname = 'public';នៅក្នុង Supabase SQL editor។ Row ណាមួយដែលមានrowsecurity = falseគឺជាបញ្ហា។ - បើក RLS លើគ្រប់តារាងសាធារណៈ។ លំនាំដើមទៅ
ENABLE ROW LEVEL SECURITYនិងFORCE ROW LEVEL SECURITYលើគ្រប់តារាងដែលបង្កើត — ធ្វើឱ្យវាជាគំរូ migration។ - សរសេរ policy តាម command មួយៗ។ កុំប្រើ
FOR ALL USING (true)។ សរសេរ policy ច្បាស់លាស់សម្រាប់ SELECT, INSERT, UPDATE, DELETE — នីមួយៗ scoped ទៅauth.uid()ឬ org-id column ពីauth.jwt()។ - ផ្ទៀងផ្ទាត់ជាមួយគណនីទីពីរ។ ចុះឈ្មោះជាអ្នកប្រើផ្សេង, ព្យាយាមអានកំណត់ត្រារបស់អ្នកប្រើផ្សេងតាមរយៈ REST API ដោយផ្ទាល់។ បើ response គឺ
200, policy ខូច។ - Scan ឡើងវិញ។ បន្ទាប់ពីអនុវត្តដំណោះស្រាយ, ដំណើរការ FixVibe scan ឡើងវិញប្រឆាំងនឹង URL ដូចគ្នា។ Finding
baas.supabase-rlsគួរត្រូវលុបបំបាត់។
-- 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;របៀបនេះប្រៀបធៀបជាមួយ scanner ផ្សេងទៀត
ឧបករណ៍ DAST ទូទៅ (Burp Suite, OWASP ZAP, Nessus) មិនដឹងថា PostgREST គឺជាអ្វី។ ពួកវានឹង crawl កម្មវិធីរបស់អ្នក, មិនអើពើផ្លូវ /rest/v1/ និងរាយការណ៍លើទំព័រ HTML ដែលពួកវាយល់។ Snyk និង Semgrep គឺជាឧបករណ៍ static-analysis — ពួកវារកឃើញឯកសារ migration នៅក្នុង repo របស់អ្នកដែលខ្វះការហៅ RLS តែមិនអាចបញ្ជាក់ថា database ដែលបាន deploy កំណត់រចនាសម្ព័ន្ធខុសឡើយ។ FixVibe នៅក្នុងគម្លាត៖ passive, BaaS-aware, ផ្ដោតលើអ្វីដែលអ្នកវាយប្រហារដែលមិនបាន authenticate អាចបញ្ជាក់ពី URL សាធារណៈ។
សំណួរសួរញឹកញាប់
តើ scanner នឹងអាន ឬកែប្រែទិន្នន័យរបស់ខ្ញុំទេ?
ទេ។ Passive scan ផ្ញើច្រើនបំផុតមួយ SELECT ... limit=1 ក្នុងតារាងដែលរកឃើញនីមួយៗ ដើម្បីបញ្ជាក់ថា RLS អនុញ្ញាតឱ្យអាន anonymous ឬអត់។ Scanner កត់ត្រារូបរាង response មិនមែនមាតិកា row។ INSERT, UPDATE, និង DELETE probe ត្រូវបានរារាំងនៅពីក្រោយការផ្ទៀងផ្ទាត់ភាពជាម្ចាស់ domain និងមិនដែលដំណើរការប្រឆាំងនឹង target ដែលមិនបានផ្ទៀងផ្ទាត់ឡើយ។
តើនេះដំណើរការទេបើ Supabase project របស់ខ្ញុំត្រូវបានផ្អាក ឬនៅលើ domain custom?
Project ដែលត្រូវបានផ្អាកត្រឡប់ 503 លើ request នីមួយៗ — scanner រាយការណ៍ project ថាមិនអាចទាក់ទងបាន។ Domain custom ដំណើរការដរាបណាកម្មវិធីដែល deploy នៅតែផ្ទុក Supabase client SDK នៅក្នុង browser; scanner ស្រង់ project URL ពី bundle ដែរក្នុងករណីណាក៏ដោយ។
ចុះបើ anon key របស់ខ្ញុំត្រូវបាន rotate ឬ publishable key ផ្លាស់ប្ដូរ?
ដំណើរការ scan ឡើងវិញ។ Scanner ស្រង់ key ឡើងវិញពី bundle បច្ចុប្បន្ននៅរាល់ដំណើរការ។ ការ rotate បដិសេធតែរបាយការណ៍មុនប៉ុណ្ណោះ មិនមែនស្ថានភាព policy នៃ database ឡើយ។
តើ scanner ត្រួតពិនិត្យ model publishable-key ថ្មីរបស់ Supabase (<code>sb_publishable_*</code>) ដែរទេ?
បាទ/ចាស។ Detector ស្គាល់ទាំង JWT anon ចាស់ និង key sb_publishable_* ថ្មី ហើយចាត់ទុកពួកវាដូចគ្នា — ទាំងពីរមានចេតនាដើម្បីសាធារណៈ និងទាំងពីរទុក RLS ជាខ្សែការពារតែមួយ។
ជំហានបន្ទាប់
ដំណើរការ FixVibe scan ឥតគិតថ្លៃប្រឆាំងនឹង URL ផលិតកម្មរបស់អ្នក — ការត្រួតពិនិត្យ baas.supabase-rls ត្រូវបានបើកនៅគ្រប់ plan រួមទាំងកម្រិតឥតគិតថ្លៃ។ សម្រាប់ការអានស៊ីជម្រៅអំពីអ្វីផ្សេងទៀតដែលអាចលេចធ្លាយពី Supabase project, សូមមើល Supabase service role key ត្រូវបានបង្ហាញនៅក្នុង JavaScript និង បញ្ជីត្រួតពិនិត្យសុវត្ថិភាព Supabase storage bucket។ សម្រាប់ទិដ្ឋភាពទូទៅនៅគ្រប់ BaaS provider, សូមអាន BaaS misconfiguration scanner។
