תשובה קצרה: לפני שמשיקים אפליקציה שנבנתה ב-Lovable צריך לעבור על עשר בדיקות: RLS מופעל על כל טבלה, המדיניות עומדת בבדיקה של שני משתמשים, אין מפתח סודי בקוד שמגיע לדפדפן, הגדרות ההתחברות סגורות, אין Edge Function שעונה לבקשה בלי משתמש מחובר, ה-webhook של התשלומים מאומת ומעבד כל אירוע פעם אחת, יש גיבוי שבדקתם שאפשר לשחזר ממנו, יש סביבת staging, יש הגבלת קצב על פעולות שעולות כסף, ואתם יודעים מה יקרה לעלות ולעומס בפי 10 משתמשים. את רובן אפשר לבדוק לבד בשעתיים, מהדפדפן ומהלוח של Supabase. הסריקה המובנית של Lovable מכסה חלק מהרשימה, ולמטה מפורט מה נשאר לכם.
מה הסריקה של Lovable כבר בודקת, ומה נשאר לכם?
Lovable מריצה סריקת אבטחה בסיסית כשפותחים את חלון הפרסום. לפי התיעוד שלה, הסריקה המהירה מחפשת טבלאות בלי RLS, כללי גישה שמתירים לכולם, הגנה מסיסמאות שדלפו שכבויה, תלויות npm עם חולשות ידועות ושרת MCP שחשוף בלי אימות. יש גם סריקה עמוקה שעוברת על קוד האפליקציה, והיא לא רצה אוטומטית.
שני משפטים מאותו תיעוד שכדאי לקחת ברצינות. הראשון: הכלים האלה מזהים בעיות נפוצות ולא יכולים להבטיח אבטחה מלאה. השני: האחריות לכך שהאפליקציה עומדת בדרישות האבטחה שמתאימות לה היא שלכם. סריקה ירוקה אומרת שלא נמצאו הדפוסים שהיא מחפשת. היא לא יודעת אם המדיניות שכתבתם עושה את מה שהתכוונתם, אם התשלום נרשם פעמיים, או אם יש גיבוי.
הרקע: במאי 2025 פורסמה CVE-2025-48757, שתיארה פרויקטים שנבנו ב-Lovable עם מדיניות RLS חסרה או חלשה, כך שאפשר היה לגשת לטבלאות שלהם בלי להתחבר. הפרסום חל על פרויקטים שנוצרו עד 15 באפריל 2025. הדפוס עצמו לא נעלם: כל טבלה חדשה שמתווספת לפרויקט צריכה את אותה בדיקה.
איך בודקים ש-RLS באמת מגן על הנתונים?
1. RLS מופעל על כל טבלה
RLS (Row Level Security) הוא המנגנון ב-Postgres שקובע איזה משתמש רואה איזו שורה. באפליקציית Lovable טיפוסית הדפדפן פונה ישירות למסד הנתונים עם המפתח הציבורי, ולכן RLS הוא מה שעומד בין משתמש לנתונים של משתמש אחר.
איך בודקים: בעורך ה-SQL הריצו:
select tablename, rowsecurity
from pg_tables
where schemaname = 'public';
איך נראה רע: כל שורה עם false, כולל טבלאות שנראות שוליות כמו לוגים או טבלאות קישור. באחד הפרויקטים שטיפלנו בהם RLS לא היה מוטמע על 60% מהטבלאות, ונציגי מכירות של חברה אחת ראו לידים של חברות אחרות.
2. המדיניות עצמה נכונה: בדיקת שני המשתמשים
RLS מופעל עם מדיניות using (true) מתנהג כמו RLS כבוי. לכן קריאת ההגדרות לא מספיקה, צריך לנסות.
איך בודקים: פתחו שני חשבונות בדיקה, A ו-B, וצרו בכל אחד כמה רשומות. התחברו כ-A, פתחו את לשונית Network בכלי הפיתוח, ומצאו בקשה לנתיב שמתחיל ב-/rest/v1/. העתיקו אותה (Copy as fetch), החליפו בכתובת את המזהה של A במזהה של B או מחקו את הסינון, והריצו בקונסול. אחר כך הריצו אותה שוב בלי הכותרת Authorization, רק עם המפתח הציבורי.
איך נראה רע: חזרו רשומות של B, או חזרו רשומות כלשהן בבקשה האנונימית. בדקו גם כתיבה: בקשת PATCH לשורה של B צריכה לעדכן אפס שורות. ואם בטבלת הפרופילים יש עמודה כמו role, plan או credits, נסו לעדכן אותה לעצמכם. אם זה עבר, כל משתמש יכול להפוך את עצמו למנהל או לתת לעצמו מנוי.
הטעויות הנפוצות במדיניות ואיך מתקנים אותן מפורטות במדריך ל-RLS שלא עובד ב-Supabase. הסבר על המונח עצמו נמצא במילון: RLS.
איך יודעים אם מפתח סודי דלף לדפדפן?
3. אין מפתח סודי בקוד שמגיע לדפדפן
המפתח הציבורי של Supabase נועד להיות בדפדפן. מפתח service_role עוקף את כל ה-RLS, ומפתחות של Stripe, OpenAI או שירות מיילים מאפשרים לחייב ולשלוח בשמכם.
איך בודקים: פתחו את האתר החי, בכלי הפיתוח לחצו Ctrl+Shift+F (חיפוש בכל הקבצים) וחפשו service_role, sk_live, sk- ו-secret. דרך מהירה יותר היא בדיקת האבטחה לאתר, שקוראת את הקוד שהאתר מגיש ומדווחת על מפתחות שדלפו, על קוד מקור שזמין להורדה ועל כותרות הגנה חסרות.
איך נראה רע: כל מפתח סודי בקוד צד-לקוח. מפתח שנמצא צריך להחליף אצל הספק. אם הפרויקט מחובר ל-GitHub, המפתח נשאר גם בהיסטוריה. המקום לסודות הוא ה-Secrets של ה-Edge Functions.
מה צריך לבדוק בהתחברות ובסשן?
4. הגדרות ההתחברות והסשן
איך בודקים: בהגדרות Auth ודאו שאימות אימייל בהרשמה מופעל, שהגנה מסיסמאות שדלפו מופעלת, ושברשימת כתובות ההפניה (Redirect URLs) מופיעים רק הדומיינים שלכם. ספריית הלקוח של Supabase שומרת כברירת מחדל את הסשן ב-localStorage, ולכן כל פרצת XSS היא גם גניבת חשבון. חפשו בקוד dangerouslySetInnerHTML וכל מקום שמציג HTML או Markdown שמשתמש כתב.
איך נראה רע: הרשמה בלי אימות אימייל באפליקציה שנותנת משהו לחשבון חדש (קרדיטים, תקופת ניסיון), localhost או כוכבית ברשימת ההפניה, ותוכן משתמשים שמוצג כ-HTML בלי סינון. באחד הפרויקטים שטיפלנו בהם הסשנים ב-localStorage היו חשופים ל-XSS.
5. אין Edge Function שעונה לבקשה בלי משתמש
Edge Functions הן הקוד שרץ בשרת: שליחת מיילים, קריאה ל-OpenAI, יצירת תשלום. הרבה פעמים הן רצות עם הרשאות מלאות, ולכן כל אחת צריכה לבדוק בעצמה מי שלח את הבקשה ומה מותר לו.
איך בודקים: מצאו את כתובת הפונקציה בלשונית Network ושלחו אליה את אותה בקשה בלי הכותרת Authorization. אחר כך שלחו אותה עם הטוקן של B על משאב של A.
איך נראה רע: הפונקציה מבצעת את הפעולה. זה אחד התחומים שהסריקה העמוקה של Lovable מכסה, ולכן כדאי להריץ אותה לפני ההשקה.
איך בודקים שה-webhook של התשלומים לא יחייב פעמיים?
6. אימות חתימה ועיבוד חד-פעמי
לפי התיעוד של Stripe, נקודת קצה עלולה לקבל את אותו אירוע יותר מפעם אחת, והדרך להתגונן היא לשמור את מזהי האירועים שכבר עובדו ולדלג עליהם. Stripe ממליצה גם לאמת את החתימה של כל אירוע, כי בלי אימות כל אחד יכול לשלוח אירוע מזויף שמאשר הזמנה. העיקרון זהה בכל ספק סליקה.
איך בודקים:
- בקוד ה-webhook חפשו אימות חתימה (
constructEventאוconstructEventAsync) עם סוד שמתחיל ב-whsec_. - חפשו טבלה שבה נשמר מזהה האירוע, עם אילוץ ייחודיות.
- בסביבת בדיקה שלחו את אותו אירוע פעמיים, עם כפתור Resend בלוח של Stripe.
- בדקו באיזה רגע המשתמש מקבל את מה ששילם עליו.
איך נראה רע: אחרי שליחה כפולה יש שתי הזמנות, שני מיילים או קרדיט כפול. או שהמנוי מופעל כשהדפדפן טוען את דף "התשלום הצליח": מי שסוגר את הלשונית לא מקבל את מה ששילם עליו, ומי שמכיר את הכתובת מקבל בלי לשלם. באחד הפרויקטים שטיפלנו בהם ה-webhooks של התשלומים נפלו על timeout בעומס, ושיעור התשלומים המוצלחים עמד על 88% עד שתוקן. תקלות נפוצות מפורטות במדריך ל-webhooks של Stripe שלא עובדים.
מה קורה אם הנתונים נמחקים מחר בבוקר?
7. גיבוי שבדקתם שאפשר לשחזר ממנו
לפי התיעוד של Supabase, בתוכנית החינמית אין גיבויים יומיים, ו-Supabase ממליצה לפרויקטים כאלה לייצא את הנתונים בעצמם ולשמור עותק מחוץ לפלטפורמה. בתוכנית Pro יש גישה לגיבויים של 7 הימים האחרונים, ושחזור לנקודת זמן (PITR) הוא תוסף. אם הפרויקט רץ על Lovable Cloud, בדקו מה התוכנית שלכם כוללת.
איך בודקים: ודאו שיש גיבוי, ושחזרו אותו פעם אחת לפרויקט נפרד כדי לראות שהאפליקציה עולה מולו.
איך נראה רע: "נראה לי שיש גיבוי", או גיבוי שאף פעם לא שוחזר. מיגרציה שמוחקת עמודה בפרודקשן בלי גיבוי היא אובדן נתונים קבוע.
8. סביבת staging
איך בודקים: שאלו את עצמכם: כשאני מבקש מ-Lovable לשנות את מבנה הטבלאות, על איזה מסד נתונים השינוי רץ?
איך נראה רע: יש מסד נתונים אחד, ושינויי מבנה רצים ישר על הנתונים של הלקוחות. באחד הפרויקטים שטיפלנו בהם לא הייתה סביבת dev או staging, וכל פיצ'ר חדש שבר שניים או שלושה ישנים.
מה יקרה כשיגיעו פי 10 משתמשים?
9. הגבלת קצב על פעולות שעולות כסף
איך בודקים: רשמו כל פעולה שעולה כסף או שולחת משהו החוצה: קריאה למודל AI, SMS, מייל, העלאת קובץ. לכל אחת שאלו מה מונע ממשתמש אחד, או מסקריפט, להפעיל אותה אלף פעמים בשעה. ואז נסו: לחצו על הכפתור עשרים פעם ברצף.
איך נראה רע: אין מגבלה לכל משתמש, ואין תקרת הוצאה אצל ספק ה-AI. חשבון אחד יכול לייצר חשבונית של חודש בלילה אחד.
10. עלות ועומס בפי 10
איך בודקים: פתחו את דף השימוש (Usage) בלוח של Supabase או של Lovable Cloud, ובכל שירות בתשלום שהאפליקציה משתמשת בו. קחו את הצריכה של החודש האחרון, הכפילו בעשר, והשוו למגבלות התוכנית: גודל מסד הנתונים, תעבורה, הפעלות של Edge Functions, חיבורים בו-זמניים, קרדיטים של AI. חפשו גם שאילתות שמושכות טבלה שלמה בלי עימוד ובלי אינדקס.
איך נראה רע: חשבון שעובר את התוכנית, או צוואר בקבוק שלא קשור לכסף. באחד הפרויקטים שטיפלנו בהם ה-connection pool הוגבל ל-15 חיבורים והמערכת לא עמדה ביום עומס. בפרויקט אחר טבלת לידים של מיליון שורות רצה בלי אינדקסים.
הצ'קליסט המלא בטבלה אחת
| # | בדיקה | איך בודקים | איך נראה רע |
|---|---|---|---|
| 1 | RLS על כל טבלה | שאילתה על pg_tables | טבלה עם rowsecurity = false |
| 2 | המדיניות נכונה | שני משתמשים, בקשה חוזרת מ-Network | רואים או משנים נתונים של משתמש אחר |
| 3 | מפתחות סודיים | חיפוש בקוד האתר החי | service_role או sk_live בדפדפן |
| 4 | התחברות וסשן | הגדרות Auth וחיפוש HTML לא מסונן | אין אימות אימייל, Redirect פתוח, XSS |
| 5 | Edge Functions | קריאה בלי Authorization | הפעולה מתבצעת |
| 6 | webhook תשלומים | Resend של אותו אירוע | הזמנה או קרדיט כפול |
| 7 | גיבוי | שחזור לפרויקט נפרד | אין גיבוי, או שלא נבדק |
| 8 | staging | איפה רצים שינויי מבנה | ישר על פרודקשן |
| 9 | הגבלת קצב | עשרים לחיצות ברצף | אין מגבלה ואין תקרת הוצאה |
| 10 | עלות בפי 10 | Usage כפול עשר מול התוכנית | חריגה, חיבורים, שאילתות בלי אינדקס |
מתי בדיקה עצמית לא מספיקה?
הרשימה מכסה את מה שאפשר לראות מהדפדפן ומהלוח. היא לא תגיד לכם אם מבנה הנתונים יחזיק את הפיצ'ר הבא, איזה ממצא דחוף ואיזה יכול לחכות, וכמה עולה לתקן כל אחד. שלושה מצבים שבהם כדאי שמהנדס יעבור על הכול: האפליקציה מחזיקה מידע אישי או תשלומים, משקיע או לקוח עסקי שאל על אבטחה, או שמצאתם ברשימה הזו שלושה ממצאים "רעים" ומעלה.
לזה נועדה בדיקה לפני השקה: מהנדס עובר על האבטחה וההרשאות, מבנה הנתונים והעומס, התשלומים ועלות האירוח, לפי ארבעת השלבים של ה-Audit Framework, ומוסר דוח בעברית עם תיקונים מדורגים לפי עדיפות וטווח עלות לכל תיקון, ושיחת מעבר של 45 דקות. איך נראה דוח כזה אפשר לראות בדוח לדוגמה. אם אתם באמצע המעבר מ-POC לפרודקשן, המדריך ההנדסי ל-Lovable בפרודקשן מפרט את העבודה שבאה אחרי הבדיקה.
מקורות
- Lovable Documentation - Security: מה הסריקה המהירה והעמוקה בודקות, והצהרת האחריות
- Matt Palmer - CVE-2025-48757: הגילוי על מדיניות RLS חסרה בפרויקטי Lovable, כולל הציר הזמן
- Stripe Docs - Receive Stripe events in your webhook endpoint: אירועים כפולים ואימות חתימה
- Supabase Docs - Database Backups: גיבויים לפי תוכנית ו-PITR
לא בטוחים מאיפה להתחיל? בעמוד הבדיקה לפני השקה אפשר לקבוע שיחת וואטסאפ חינמית של 20 דקות. מספרים מה בניתם ומתי אתם רוצים לעלות לאוויר, ונגיד לכם אם צריך בדיקה מלאה או שהרשימה הזו מספיקה.
