FixVibe

// docs / baas security / supabase storage

רשימת בדיקה לאבטחת דליי אחסון של Supabase: 22 פריטים

Supabase Storage הוא עטיפה דקה סביב דלי תואם-S3 פלוס אותו מודל Row-Level Security של מסד הנתונים. זה אומר שאותן מלכודות RLS שמשפיעות על טבלאות משפיעות על גישה לקבצים — ועוד כמה ספציפיות לאחסון שמופיעות כשכלי קוד מבוססי-AI מחברים העלאות. הרשימה הזו היא 22 פריטים על פני חמישה חלקים: תצורת דלי, מדיניויות RLS, אימות העלאה, URLs חתומים, והיגיינה תפעולית. כל אחד ניתן לאימות תוך פחות מ-15 דקות.

כל פריט להלן הוא חיוני. עבור מכניקות ה-RLS הבסיסיות, ראה סורק Supabase RLS. עבור מחלקת חשיפת המפתח הסמוכה לאחסון, ראה מפתח Supabase service role חשוף ב-JavaScript.

תצורת דלי

התחל עם ברירות המחדל הנכונות. דלי מוגדר שגוי דולף קבצים בין אם ה-RLS שלך נכון ובין אם לא.

  1. הגדר כל דלי כברירת מחדל לפרטי. ב-Dashboard של Supabase → Storage → Buckets, הגדר את מתג Public bucket ל-off אלא אם יש לך סיבה מפורשת (נכסי שיווק, אווטרים ציבוריים ללא PII). דליים ציבוריים עוקפים RLS עבור פעולות קריאה — כל מי שיודע את שם הדלי יכול לרשום ולהוריד.
  2. הגדר מגבלת גודל קובץ קשיחה על כל דלי. Dashboard → הגדרות דלי → מגבלת גודל קובץ. 50 MB הוא ברירת מחדל הגיונית להעלאות משתמש; העלה אותה במכוון עבור מקרי שימוש של וידאו / קבצים גדולים. ללא מגבלה, העלאה זדונית אחת יכולה למצות את מכסת האחסון שלך או את רוחב הפס החודשי שלך.
  3. הגבל סוגי MIME מותרים לכל דלי. רשימת סוגי MIME מותרים — רשימת היתר מפורשת, לא רשימת חסימה. image/jpeg, image/png, image/webp לדליים של תמונות בלבד. לעולם אל תתיר text/html, application/javascript, או image/svg+xml בדלי תוכן משתמש — הם מורצים בדפדפן כשהם משרתים דרך URL חתום.
  4. השתמש בדלי אחד לכל סוג תוכן, לא בדלי משותף אחד. הגדרות לכל דלי (גודל, סוגי MIME, מדיניויות RLS) הן הגרגריות שיש לך. דלי user-avatars, דלי document-uploads, ודלי public-assets קלים יותר לנעילה מדלי מעורב אחד.
  5. אמת תצורת CORS אם העלאות מצד הלקוח. אם משתמשים מעלים ישירות מהדפדפן ל-URL חתום, ה-CORS של הדלי חייב לרשום את מקור הייצור שלך. * מקובל רק לדליים ציבוריים — לעולם לא לדליים המכילים PII של משתמשים.

מדיניויות RLS על storage.objects

Supabase Storage מאחסן מטא-נתוני קבצים בטבלת storage.objects. RLS על אותה טבלה שולט במי יכול לקרוא, להעלות, לעדכן או למחוק קבצים. ללא RLS, דגל הציבורי/פרטי של הדלי הוא ההגנה היחידה שלך.

  1. אשר ש-RLS מופעל על storage.objects. SELECT rowsecurity FROM pg_tables WHERE schemaname = 'storage' AND tablename = 'objects'; חייב להחזיר true. Supabase מפעיל זאת כברירת מחדל בפרויקטים חדשים; אמת שלא הושבת.
  2. כתוב מדיניות SELECT מצומצמת ל-auth.uid() עבור דליים פרטיים. CREATE POLICY "users_read_own_files" ON storage.objects FOR SELECT USING (auth.uid()::text = (storage.foldername(name))[1]);. המוסכמה היא לאחסן קבצים תחת [user-id]/[filename] ולהשתמש ב-storage.foldername() כדי לחלץ את הבעלים מהנתיב.
  3. כתוב מדיניות INSERT שאוכפת את אותה מוסכמת נתיב. CREATE POLICY "users_upload_own" ON storage.objects FOR INSERT WITH CHECK (auth.uid()::text = (storage.foldername(name))[1]);. ללא WITH CHECK, משתמש מאומת יכול להעלות לתיקייה של משתמש אחר.
  4. הוסף מדיניויות UPDATE ו-DELETE אם האפליקציה שלך תומכת בעריכת או מחיקת קבצים. כל פקודה צריכה את המדיניות שלה. דילוג על DELETE אומר שמשתמשים מאומתים לא יכולים להסיר את הקבצים שלהם; דילוג על UPDATE אומר שדריסת קבצים נכשלת בשקט.
  5. בדוק גישה בין-משתמשים בשני session דפדפן. היכנס כמשתמש A, העלה קובץ, העתק את הנתיב. היכנס כמשתמש B בדפדפן אחר, נסה למשוך את הקובץ דרך ה-REST API. התגובה חייבת להיות 403 או 404, לעולם לא 200.
sql
-- Confirm RLS on storage.objects
SELECT rowsecurity
FROM   pg_tables
WHERE  schemaname = 'storage' AND tablename = 'objects';

-- SELECT policy: scope reads to the owning user's folder.
CREATE POLICY "users_read_own_files"
  ON storage.objects
  FOR SELECT
  USING (auth.uid()::text = (storage.foldername(name))[1]);

-- INSERT policy: enforce the [user-id]/[filename] path convention.
CREATE POLICY "users_upload_own"
  ON storage.objects
  FOR INSERT
  WITH CHECK (auth.uid()::text = (storage.foldername(name))[1]);

אימות העלאה

אמת כל העלאה בצד-שרת, אפילו כשלדלי יש אילוצי MIME וגודל. כלי קוד מבוססי-AI מייצרים אימות של צד-לקוח בלבד כברירת מחדל; זה לא מגן על כלום.

  1. בדוק מחדש סוג MIME בצד-שרת מהבייטים בפועל של הקובץ, לא מ-header ה-Content-Type. השתמש בספרייה כמו file-type (Node) או רחרוח byte קסום. תוקף יכול לטעון Content-Type: image/jpeg על קובץ שהוא בעצם payload פוליגלוט של HTML / JavaScript.
  2. הסר מטא-נתוני EXIF מתמונות מועלות. EXIF יכול להכיל קואורדינטות GPS, מספרים סידוריים של מכשירים, וחותמות זמן. השתמש ב-sharp עם .withMetadata(false) או exif-parser כדי להסיר לפני האחסון.
  3. דחה SVGs שמכילים תגי script או handlers של onload. SVG הוא XML — והרבה אפליקציות שנוצרו על-ידי AI מתירות העלאות SVG כ"סתם תמונה". השתמש ב-DOMPurify בצד-שרת או סרב להעלאות SVG לחלוטין.
  4. השתמש בשמות קבצים דטרמיניסטיים ובלתי-ניתנים-לניחוש. אל תשמר את שם הקובץ המקורי. השתמש ב-UUID או hash של תוכן הקובץ. שמות קבצים מקוריים מדליפים ("passport_scan_2024_01_15.jpg") ושמות צפויים מאפשרים מנייה.

URLs חתומים

URLs חתומים הם איך שלקוחות ניגשים לדליים פרטיים. תוקף הפקיעה, היקף הדלי, ומה שמתועד חשובים.

  1. הגדר תוקף URL חתום כברירת מחדל לשעה או פחות. createSignedUrl(path, expiresIn) של JS SDK של Supabase לוקח שניות. לעולם אל תשתמש בערכים כמו 31536000 (שנה אחת) — ה-URL הופך לקישור חצי-ציבורי קבוע.
  2. לעולם אל תאחסן URLs חתומים במסד הנתונים שלך. צור חדשים בצד-שרת בכל בקשה. URL חתום מאוחסן עם תוקף של שנה שדולף דרך dump של מסד נתונים מעניק גישה ארוכת-טווח.
  3. תעד יצירת URL חתום, לא רק העלאות קבצים. אם אתה חושד בפריצה מאוחר יותר, אתה צריך לדעת מי יצר איזה URL ומתי. תעד auth.uid() + דלי + נתיב אובייקט + חותמת זמן.
  4. השתמש באפשרות downloadAs כשמשרתים קבצים מועלים-על-ידי-משתמש. createSignedUrl(path, expiresIn, { download: '.jpg' }) אוכף header Content-Disposition: attachment כך שהקובץ מורד במקום להיות מוצג — מובס את מחלקת הביצוע של HTML / SVG / HTML-בתוך-PDF.

היגיינה תפעולית

תצורת אחסון נסחפת עם הזמן. ארבעת הפריטים התפעוליים האלה שומרים את המשטח הדוק.

  1. בצע audit לדליים רבעוני. Dashboard → Storage → Buckets. אשר שמצב ציבורי/פרטי ורשימות סוגי MIME תואמים למה שהאפליקציה מצפה. דליים שנוצרו "זמנית" הופכים לקבועים אם אף אחד לא מסיר אותם.
  2. נטר פעולות רישום אנונימיות. יומני אחסון (Dashboard → Logs → Storage) רושמים בקשות LIST. עלייה חדה בבקשות רישום אנונימיות מול דלי פרטי אומרת שמישהו בוחן אותו מבחוץ.
  3. הגדר מדיניות שמירה להעלאות זמניות. דליי טמפ (תצוגה מקדימה של תמונה, העלאות טיוטה) צריכים להימחק אוטומטית אחרי 24-72 שעות דרך פונקציה מתוזמנת. שמירה ללא הגבלת זמן היא התחייבות תחת חובות מינימיזציית-נתונים של GDPR / CCPA.
  4. הרץ סריקת FixVibe חודשית. בדיקת baas.supabase-storage-public בוחנת אחר דליים שמגיבים ל-GET + LIST אנונימיים. דליים חדשים נוספים; ישנים משנים נראות — רק סריקה רציפה לוכדת את הסחיפה.

צעדים הבאים

הרץ סריקת FixVibe מול URL הייצור שלך — רישומי אחסון אנונימיים מופיעים תחת baas.supabase-storage-public. צמד את הרשימה הזו עם סורק Supabase RLS עבור שכבת הטבלה ו-מפתח Supabase service role חשוף ב-JavaScript עבור הסמיכות של חשיפת מפתחות. עבור תצורות שגויות של אחסון בספקי BaaS אחרים, ראה סורק תצורות שגויות של BaaS.

// סרוק את משטח ה-baas שלך

מצא את הטבלה הפתוחה לפני שמישהו אחר עושה זאת.

הכנס URL ייצור. FixVibe מזהה את ספקי ה-BaaS שהאפליקציה שלך מתקשרת איתם, מבצע fingerprint לנקודות הקצה הציבוריות שלהם, ומדווח מה לקוח לא-מאומת יכול לקרוא או לכתוב. חינם, ללא התקנה, ללא כרטיס.

  • שכבת חינם — 3 סריקות בחודש, ללא כרטיס בהרשמה.
  • Fingerprinting פסיבי של BaaS — אין צורך באימות דומיין.
  • Supabase, Firebase, Clerk, Auth0, Appwrite ועוד.
  • פרומפטים של תיקון AI על כל ממצא — הדבק חזרה לתוך Cursor / Claude Code.
הרץ סריקת BaaS חינמית

אין צורך בהרשמה

רשימת בדיקה לאבטחת דליי אחסון של Supabase: 22 פריטים — Docs · FixVibe