// docs / baas security / supabase rls scanner
ماسح Supabase RLS: ابحث عن الجداول التي تفتقر إلى أمان مستوى الصف أو يعاني من خلل
أمان مستوى الصف (RLS) هو الشيء الوحيد الذي يفصل بيانات عملائك عن الإنترنت عندما تُطلق تطبيقًا مبنيًا على Supabase. أدوات البرمجة بالذكاء الاصطناعي تُولِّد كودًا بشكل RLS يُترجَم ويُطلَق ويُسرِّب البيانات بصمت — جداول تُنشأ دون تفعيل RLS، وسياسات تقرأ ولكنها لا تُقيّد، ومسندات تقارن عمودًا بنفسه. يوضح هذا المقال ما يستطيع ماسح Supabase RLS إثباته من الخارج، والأشكال الأربعة لـ RLS المعطّل التي تظهر في تطبيقات الـ vibe-coding، وكيفية مسح نشرك الخاص في أقل من دقيقة.
ما يستطيع مسح RLS خارجي إثباته
يعمل مسح RLS سلبي على نقطة نهاية PostgREST التي يكشفها Supabase عند https://[project].supabase.co/rest/v1/. يستخدم فقط مفتاح anon القابل للنشر — نفس المفتاح الذي يستخدمه متصفحك — ويفحص بيانات وصف قائمة الجداول، والقراءات المجهولة، والكتابات المجهولة. لا يُصادق أبدًا كمستخدم ولا يلامس أبدًا صلاحيات service-role. أي شيء يستطيع فعله، يمكن لمهاجم غير مصادق على الإنترنت فعله.
من خارج قاعدة البيانات، يمكن للماسح أن يؤكد ما يلي بثقة عالية:
- RLS معطّل على جدول. يُرجع PostgREST صفوفًا لاستعلام
SELECTمجهول عند إيقاف تشغيل RLS أو عندما تسمح به سياسة. كلا الحالتين نتيجة. - يمكن للدور المجهول إدراج الجداول. يُرجع طلب
GET /rest/v1/باستخدام مفتاح anon مخطط OpenAPI لكل جدول يملك الدورanonأي امتياز عليه. كثيرًا ما تمنح التطبيقات المُولَّدة بالذكاء الاصطناعيUSAGEعلى المخطط وSELECTعلى كل جدول، مما يكشف خريطة المخطط الكاملة حتى عندما يرفض RLS القراءات الفعلية. - يمكن للدور المجهول الإدراج. سينجح
POSTاستكشافي يحتوي على تخمين لشكل العمود إذا لم يكن لـ RLS سياسةINSERTتمنعه — حتى لو كانSELECTمُقيّدًا. - مفتاح service-role موجود في حزمة المتصفح. بجوار RLS: إذا وجد الماسح
SUPABASE_SERVICE_ROLE_KEYأو أي JWT يحتوي علىrole: service_roleفي حزمة JavaScript، يصبح RLS بلا قيمة — حامل ذلك المفتاح يتجاوز كل سياسة.
ما لا يستطيع المسح الخارجي إثباته
كن صادقًا بشأن حدود الماسح. لا يستطيع مسح RLS خارجي قراءة جدول pg_policies أو ملفات الهجرة أو المسند الدقيق لأي سياسة. يستنتج من السلوك في الصندوق الأسود، مما يعني أنه سيُبلِّغ أحيانًا عن نتيجة تتضح أنها بيانات عامة مقصودة (جدول لنشرة تسويقية، كتالوج منتجات عام). يُؤشِّر تقرير FixVibe هذه الحالات بـ ثقة متوسطة عندما لا يستطيع الماسح التمييز في النوايا — راجع اسم الجدول واتخذ القرار.
الأشكال الأربعة لـ RLS المعطّل التي تُنتجها أدوات الذكاء الاصطناعي
عندما توجِّه Cursor أو Claude Code أو Lovable أو Bolt إلى Supabase، تظهر الأنماط الأربعة نفسها لـ RLS المعطّل عبر آلاف التطبيقات. كل واحد منها يجتاز فحص النوع ويُترجَم ويُطلَق:
الشكل 1: لم يتم تفعيل RLS أصلًا
أكثر أنماط الفشل شيوعًا. تُنشئ الهجرة الجدول ولكن المطور (أو أداة الذكاء الاصطناعي) ينسى ALTER TABLE ... ENABLE ROW LEVEL SECURITY. يخدم PostgREST الجدول بكامله بسعادة لأي شخص يحمل مفتاح anon. الإصلاح: ALTER TABLE public.[name] ENABLE ROW LEVEL SECURITY; ALTER TABLE public.[name] FORCE ROW LEVEL SECURITY;. FORCE ليس اختياريًا — بدونه يتجاوز مالك الجدول (وأي دور يملك ملكية الجدول) RLS.
ALTER TABLE public.[name] ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.[name] FORCE ROW LEVEL SECURITY;الشكل 2: RLS مُفعَّل ولكن بدون سياسات
فشل أكثر دقة. يكون RLS مُفعَّلًا ولكن لا تُكتب أي سياسات. الافتراضي في PostgreSQL هو الرفض، لذا لا يرى المستخدمون المُصادقون شيئًا — فيضيف المطور USING (true) لجعل التطبيق يعمل، مما يسمح للجميع بقراءة كل شيء. الإصلاح: اكتب سياسة محصورة بـ auth.uid(): CREATE POLICY "select_own" ON public.[name] FOR SELECT USING (auth.uid() = user_id); وسياسة INSERT/UPDATE/DELETE مطابقة.
CREATE POLICY "select_own"
ON public.[name]
FOR SELECT
USING (auth.uid() = user_id);الشكل 3: تقارن السياسة عمودًا بنفسه
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: سياسة على SELECT دون INSERT/UPDATE
يُحكم المطور القراءات ولكنه ينسى الكتابات. سياسات RLS لكل أمر. FOR SELECT يحمي القراءات فقط؛ لا يزال بإمكان عميل مجهول INSERT إذا لم تمنعه سياسة. الإصلاح: أنشِئ سياسة لكل أمر، أو استخدم FOR ALL مع جملتي USING وWITH CHECK صريحتين.
كيف يعمل ماسح Supabase RLS من FixVibe
يعمل فحص baas.supabase-rls في ثلاث مراحل، لكل منها مستويات ثقة صريحة:
- المرحلة 1 — البصمة. يزحف الماسح إلى التطبيق المنشور، ويُحلِّل حزمة JavaScript الخاصة به، ويستخرج عنوان URL لمشروع Supabase ومفتاح anon من تكوين وقت التشغيل. لا تخمين DNS، ولا قوة غاشمة — يقرأ ما يقرأه المتصفح.
- المرحلة 2 — اكتشاف المخطط. يُعيد طلب
GET /rest/v1/واحد مع مفتاح anon مخطط OpenAPI لكل جدول يمكن لدور anon رؤيته. يُسجِّل الماسح أسماء الجداول ولكنه لا يقرأ بيانات الصفوف في هذه المرحلة. - المرحلة 3 — فحوصات القراءة والكتابة. لكل جدول مُكتشف، يُصدر الماسح استعلام
SELECTمجهول واحد معlimit=1. إذا أعادت صفوفًا، يكون RLS متساهلًا. يتوقف الماسح هناك — لا يُعدِّد الصفوف، ولا يُقسِّمها على صفحات، ولا يُعدِّل البيانات. فحوصات INSERT مشروطة بالتحقق من ملكية النطاق والاشتراك الصريح؛ ولا تُطلَق أبدًا على أهداف غير مُتحقَّق منها.
تُرفَق كل نتيجة بعنوان URL الطلب الدقيق، وحالة الاستجابة، وشكل الاستجابة (الترويسة فقط)، واسم الجدول. مطالبة الإصلاح بالذكاء الاصطناعي في أسفل النتيجة عبارة عن كتلة SQL جاهزة للنسخ واللصق تُشغِّلها في محرر Supabase SQL.
ماذا تفعل عندما يجد الماسح شيئًا
كل نتيجة RLS طارئة في وقت التشغيل. تتعرض نقاط نهاية PostgREST العامة لمسح المهاجمين خلال دقائق. تسلسل المعالجة آلي:
- راجع كل جدول. شغِّل
SELECT schemaname, tablename, rowsecurity FROM pg_tables WHERE schemaname = 'public';في محرر Supabase SQL. أي صف يحتوي علىrowsecurity = falseهو مشكلة. - فعِّل RLS على كل جدول عام. اجعل
ENABLE ROW LEVEL SECURITYوFORCE ROW LEVEL SECURITYالافتراضيين على كل جدول يُنشأ — اجعل ذلك قالب هجرة. - اكتب السياسات أمرًا بأمر. لا تستخدم
FOR ALL USING (true). اكتب سياسات صريحة لـ SELECT وINSERT وUPDATE وDELETE — كل واحدة محصورة بـauth.uid()أو عمود org-id منauth.jwt(). - تحقق بحساب ثانٍ. سجِّل بحساب مستخدم آخر، وحاول قراءة سجلات مستخدم آخر عبر REST API مباشرة. إذا كانت الاستجابة
200، فالسياسة معطّلة. - أعد المسح. بعد تطبيق الإصلاح، أعد تشغيل مسح FixVibe على نفس عنوان URL. يجب أن تختفي نتيجة
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;كيف تُقارَن هذه الأداة بالماسحات الأخرى
معظم أدوات DAST العامة (Burp Suite وOWASP ZAP وNessus) لا تعرف ما هو PostgREST. ستزحف إلى تطبيقك، وتتجاهل المسار /rest/v1/، وتُبلِّغ عن صفحات HTML التي تفهمها. Snyk وSemgrep أدوات تحليل ساكن — تجد ملفات الهجرة في مستودعك حيث استدعاءات RLS مفقودة، ولكنها لا تستطيع إثبات أن قاعدة البيانات المنشورة مُهيَّأة بشكل خاطئ. يقع FixVibe في الفجوة: سلبي، مدرك لـ BaaS، يُركِّز على ما يستطيع مهاجم غير مصادق إثباته من عنوان URL العام.
الأسئلة الشائعة
هل سيقرأ الماسح بياناتي أو يُعدِّلها؟
لا. تُصدر عمليات المسح السلبية ما لا يزيد عن استعلام SELECT ... limit=1 واحد لكل جدول مُكتشف لتأكيد ما إذا كان RLS يسمح بالقراءات المجهولة. يُسجِّل الماسح شكل الاستجابة، لا محتوى الصفوف. فحوصات INSERT وUPDATE وDELETE مشروطة بالتحقق من ملكية النطاق ولا تُشغَّل أبدًا على أهداف غير مُتحقَّق منها.
هل يعمل هذا إذا كان مشروع Supabase الخاص بي متوقفًا أو على نطاق مخصص؟
تُرجع المشاريع المتوقفة 503 على كل طلب — يُبلِّغ الماسح عن المشروع بأنه غير قابل للوصول. تعمل النطاقات المخصصة طالما أن التطبيق المنشور لا يزال يُحمِّل SDK عميل Supabase في المتصفح؛ يستخرج الماسح عنوان URL المشروع من الحزمة بأي حال.
ماذا لو تم تدوير مفتاح anon أو تغيّر مفتاحي القابل للنشر؟
أعد تشغيل المسح. يُعيد الماسح استخراج المفتاح من الحزمة الحالية في كل تشغيل. التدوير يُبطل التقرير السابق فقط، لا حالة سياسات قاعدة البيانات.
هل يفحص الماسح نموذج مفتاح Supabase القابل للنشر الجديد (<code>sb_publishable_*</code>)؟
نعم. يتعرف الكاشف على كل من رموز anon JWT القديمة ومفاتيح sb_publishable_* الأحدث ويتعامل معها بشكل متطابق — كلاهما مُصمَّم ليكون عامًا وكلاهما يجعل RLS خط الدفاع الوحيد.
الخطوات التالية
شغِّل مسح FixVibe مجاني على عنوان URL الإنتاج — فحص baas.supabase-rls مُفعَّل على كل خطة بما فيها الباقة المجانية. لقراءة أعمق حول ما يمكن أن يتسرب من مشروع Supabase، راجع مفتاح Supabase service role المكشوف في JavaScript وقائمة التحقق لأمان دلاء Supabase Storage. للحصول على رؤية شاملة عبر جميع موفِّري BaaS، اقرأ ماسح التهيئة الخاطئة لـ BaaS.
