TL;DR: RLS הוא פירצת האבטחה #1 בפרויקטי Vibe Coding - Lovable/Base44/Cursor יוצרים schemas בלי policies, וכל user יכול לקרוא נתונים של אחרים דרך ה-API. המדריך מראה איך להטמיע נכון: enable על כל טבלה, policy לכל פעולה, בדיקת auth.uid(), הגנה על multi-tenant.
למה RLS הוא הבעיה הקריטית בפרויקטי AI
ב-90% מפרויקטי Lovable/Base44 שאנחנו רואים, RLS לא מוטמע באופן מקיף. לא תיאוריה - ראינו incidents אמיתיים ב-2025: B2B SaaS עם payment data של 200 לקוחות שזלגו; פלטפורמת חינוך עם תשובות שלכל התלמידים; CRM עם leads של מתחרים.
הסיבה: AI agents לא חושבים על security by default. הם בונים schema, מחברים API, ומשאירים את הסיסמאות בידי המתכנת. אם המתכנת לא מודע ל-RLS - הפרצה פתוחה.
מה זה RLS
תשובה ישירה: RLS הוא מנגנון Postgres שמסנן rows לפי policy SQL. כל קריאה דרך API מועברת דרך ה-policy לפני שמחזירה תוצאות. בלי policy - אין אכיפה ברמת ה-row.
ב-Supabase ו-Base44 - RLS מופעל על טבלה חדשה אבל אין policies = deny all. AI agent שיוצר טבלה לעיתים שוכח policies וה-הכל "לא עובד". התגובה: לכבות RLS. וכך הפרויקט עולה לpod.
Setup בסיסי
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
כלל זהב: כל טבלה חדשה - RLS enable מיידית. עדיף error 401 מאשר להדליף נתונים.
Policy לכל פעולה
-- SELECT
CREATE POLICY "users see own orders"
ON orders FOR SELECT
USING (auth.uid() = user_id);
-- INSERT
CREATE POLICY "users create own orders"
ON orders FOR INSERT
WITH CHECK (auth.uid() = user_id);
-- UPDATE - חייב USING + WITH CHECK
CREATE POLICY "users update own orders"
ON orders FOR UPDATE
USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);
-- DELETE - לרוב admin only
CREATE POLICY "admins delete"
ON orders FOR DELETE
USING (EXISTS (
SELECT 1 FROM admin_users
WHERE admin_users.user_id = auth.uid()
));
USINGvsWITH CHECK: USING בודק אילו rows גלויים. WITH CHECK בודק אילו אפשר ליצור/לעדכן. ב-UPDATE צריך את שניהם.
Multi-tenant - הגנה על organizations
CREATE TABLE org_members (
user_id uuid REFERENCES auth.users(id),
org_id uuid NOT NULL,
role text DEFAULT 'member',
PRIMARY KEY (user_id, org_id)
);
ALTER TABLE org_members ENABLE ROW LEVEL SECURITY;
CREATE TABLE projects (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
org_id uuid NOT NULL,
name text NOT NULL
);
ALTER TABLE projects ENABLE ROW LEVEL SECURITY;
CREATE POLICY "members see org projects"
ON projects FOR SELECT
USING (
org_id IN (
SELECT org_id FROM org_members WHERE user_id = auth.uid()
)
);
CREATE POLICY "org admins create projects"
ON projects FOR INSERT
WITH CHECK (
EXISTS (
SELECT 1 FROM org_members
WHERE org_id = projects.org_id
AND user_id = auth.uid()
AND role IN ('admin', 'owner')
)
);
קראו עוד: Supabase RLS Policies
הגנה על foreign keys + JOINs
טעות נפוצה: policy על orders אבל לא על customers. ה-API קורא דרך JOIN ומדליף.
פתרון: Policy גם על customers:
CREATE POLICY "users see own customers"
ON customers FOR SELECT
USING (
id IN (SELECT customer_id FROM orders WHERE user_id = auth.uid())
);
service_role - רק בצד שרת
service_role עוקף RLS לחלוטין. לעולם לא ב-frontend. בדקו: grep -r "SERVICE_ROLE" src/ - צריך להופיע רק ב-api/ או server/.
חוק הגנת הפרטיות הישראלי
מ-2024 חובות מחמירות: דיווח breach תוך 72 שעות, הסכמה מפורשת ל-sensitive, right to be forgotten, audit logs. RLS לבדו לא מספיק - הוסיפו טריגרים שמתעדים גישה ל-PII.
קראו עוד: PII Data Handling | GDPR for AI
Checklist לפני Production
- RLS על כל טבלה (גם logs)
- Policy ל-SELECT/INSERT/UPDATE/DELETE
- USING + WITH CHECK ב-UPDATE
- service_role רק בצד שרת
- Multi-tenant: org_id בכל טבלה + policy על org membership
- Foreign keys מוגנים - אין JOIN שמדליף
- Test as anonymous + authenticated
- Audit log על PII access
- Penetration test לפני launch
כלים מ-VibeScale
- AI Readiness Checklist - בודק RLS
- Production Readiness Audit - 30 בדיקות
- Audit Framework - דוח RLS מפורט תוך 72 שעות
