FixVibe

// docs / baas security / supabase storage

چک‌لیست امنیت سطل ذخیره‌سازی Supabase: ۲۲ مورد

Supabase Storage یک پوشش نازک روی یک سطل سازگار با S3 به‌علاوه همان مدل امنیت در سطح ردیف مانند پایگاه‌داده است. این یعنی همان دام‌های RLS که جدول‌ها را تحت تأثیر قرار می‌دهند، دسترسی فایل را نیز تحت تأثیر قرار می‌دهند — و چند مورد خاص ذخیره‌سازی که وقتی ابزارهای کدنویسی هوش مصنوعی آپلودها را پیکربندی می‌کنند ظاهر می‌شوند. این چک‌لیست ۲۲ مورد در پنج بخش است: پیکربندی سطل، سیاست‌های RLS، اعتبارسنجی آپلود، signed URLها و بهداشت عملیاتی. هر مورد در کمتر از ۱۵ دقیقه قابل تأیید است.

هر مورد زیر ضروری است. برای مکانیک‌های زیربنایی RLS، اسکنر Supabase RLS را ببینید. برای کلاس افشای کلید مجاور به ذخیره‌سازی، افشای کلید service role Supabase در جاوااسکریپت را ببینید.

پیکربندی سطل

با پیش‌فرض‌های درست شروع کنید. یک سطل با پیکربندی نادرست فایل‌ها را افشا می‌کند چه RLS شما درست باشد چه نباشد.

  1. پیش‌فرض هر سطل را روی خصوصی قرار دهید. در داشبورد Supabase → Storage → Buckets، دکمه Public bucket را خاموش کنید مگر این‌که دلیل صریحی داشته باشید (دارایی‌های بازاریابی، آواتارهای عمومی بدون PII). سطل‌های عمومی RLS را برای عملیات خواندن دور می‌زنند — هر کسی با نام سطل می‌تواند فهرست و دانلود کند.
  2. روی هر سطل یک حد سخت اندازه فایل تنظیم کنید. Dashboard → Bucket settings → File size limit. ۵۰ MB یک پیش‌فرض معقول برای آپلودهای کاربر است؛ آن را عمداً برای موارد کاربرد ویدئو / فایل‌های بزرگ بالا ببرید. بدون حد، یک آپلود مخرب می‌تواند سهمیه ذخیره‌سازی یا پهنای باند ماهانه شما را تخلیه کند.
  3. MIME typeهای مجاز را به‌ازای هر سطل محدود کنید. فهرست MIME typeهای مجاز — لیست سفید صریح، نه لیست سیاه. image/jpeg، image/png، image/webp برای سطل‌های فقط-تصویر. هرگز text/html، application/javascript یا image/svg+xml را در یک سطل محتوای کاربر اجازه ندهید — آن‌ها وقتی از طریق signed URL ارائه می‌شوند در مرورگر اجرا می‌گردند.
  4. یک سطل برای هر نوع محتوا استفاده کنید، نه یک سطل مشترک. تنظیمات per-bucket (اندازه، MIME typeها، سیاست‌های RLS) دانه‌بندی‌ای است که در اختیار دارید. یک سطل user-avatars، یک سطل document-uploads و یک سطل public-assets راحت‌تر از یک سطل مخلوط قفل می‌شوند.
  5. اگر فرانت‌اند آپلود می‌کند، پیکربندی CORS را تأیید کنید. اگر کاربران مستقیماً از مرورگر به یک signed URL آپلود می‌کنند، CORS سطل باید origin تولیدی شما را فهرست کند. * فقط برای سطل‌های عمومی قابل قبول است — هرگز برای سطل‌های حاوی 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. دسترسی متقابل کاربران را در دو نشست مرورگر آزمایش کنید. به‌عنوان کاربر 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 و اندازه دارد. ابزارهای کدنویسی هوش مصنوعی به‌طور پیش‌فرض اعتبارسنجی فقط-کلاینتی تولید می‌کنند؛ این از چیزی محافظت نمی‌کند.

  1. MIME type را در سمت سرور از بایت‌های واقعی فایل دوباره بررسی کنید، نه از هدر Content-Type. از کتابخانه‌ای مانند file-type (Node) یا magic-byte sniffing استفاده کنید. یک مهاجم می‌تواند Content-Type: image/jpeg را روی فایلی که در واقع یک payload چندزبانه HTML / JavaScript است ادعا کند.
  2. متادیتای EXIF را از تصاویر آپلودی پاک کنید. EXIF می‌تواند شامل مختصات GPS، شماره‌های سریال دستگاه و timestampها باشد. از sharp با .withMetadata(false) یا exif-parser برای پاک کردن پیش از ذخیره‌سازی استفاده کنید.
  3. SVGهایی که حاوی تگ script یا هندلر onload هستند را رد کنید. SVG یک XML است — و بسیاری از اپلیکیشن‌های تولیدشده توسط هوش مصنوعی آپلود SVG را به‌عنوان "فقط یک تصویر" اجازه می‌دهند. از DOMPurify در سمت سرور استفاده کنید یا آپلود SVG را کاملاً رد کنید.
  4. از نام‌فایل‌های قطعی و غیرقابل‌حدس استفاده کنید. نام‌فایل اصلی را حفظ نکنید. از UUID یا هش محتوای فایل استفاده کنید. نام‌های اصلی نشت می‌کنند ("passport_scan_2024_01_15.jpg") و نام‌های قابل پیش‌بینی شمارش را امکان‌پذیر می‌کنند.

Signed URLها

Signed URLها روشی هستند که کلاینت‌ها به سطل‌های خصوصی دسترسی پیدا می‌کنند. انقضا، دامنه سطل و آنچه ثبت می‌شود مهم است.

  1. انقضای پیش‌فرض signed URL را روی ۱ ساعت یا کمتر تنظیم کنید. createSignedUrl(path, expiresIn) در Supabase JS SDK ثانیه می‌گیرد. هرگز از مقادیری مانند 31536000 (یک سال) استفاده نکنید — URL تبدیل به یک لینک نیمه‌عمومی دائمی می‌شود.
  2. هرگز signed URLها را در پایگاه‌داده خود ذخیره نکنید. در هر درخواست در سمت سرور تازه تولید کنید. یک signed URL ذخیره‌شده با انقضای ۱ ساله که از طریق یک dump پایگاه‌داده نشت می‌کند، دسترسی بلندمدت می‌دهد.
  3. تولید signed URL را ثبت کنید، نه فقط آپلودهای فایل. اگر بعداً به یک compromise مشکوک شدید، باید بدانید چه کسی چه URLی را چه زمانی تولید کرده. auth.uid() + سطل + مسیر شیء + timestamp را ثبت کنید.
  4. هنگام ارائه فایل‌های آپلودشده توسط کاربر از گزینه downloadAs استفاده کنید. createSignedUrl(path, expiresIn, { download: '.jpg' }) یک هدر Content-Disposition: attachment را اجبار می‌کند تا فایل به‌جای رندر شدن دانلود شود — کلاس اجرای HTML / SVG / HTML-in-PDF را شکست می‌دهد.

بهداشت عملیاتی

پیکربندی ذخیره‌سازی در طول زمان از مسیر منحرف می‌شود. این چهار مورد عملیاتی سطح را محکم نگه می‌دارند.

  1. سطل‌ها را به‌صورت فصلی بررسی کنید. Dashboard → Storage → Buckets. تأیید کنید وضعیت عمومی/خصوصی و فهرست‌های MIME-type با آنچه اپلیکیشن انتظار دارد مطابقت دارد. سطل‌هایی که "موقتاً" ایجاد شده‌اند اگر کسی آن‌ها را حذف نکند دائمی می‌شوند.
  2. عملیات لیست ناشناس را پایش کنید. لاگ‌های ذخیره‌سازی (Dashboard → Logs → Storage) درخواست‌های LIST را ثبت می‌کنند. جهش درخواست‌های لیست ناشناس علیه یک سطل خصوصی یعنی کسی آن را از بیرون می‌کاود.
  3. برای آپلودهای موقت یک سیاست نگه‌داری تنظیم کنید. سطل‌های موقت (پیش‌نمایش تصویر، آپلودهای پیش‌نویس) باید پس از ۲۴-۷۲ ساعت از طریق یک تابع زمان‌بندی‌شده به‌صورت خودکار حذف شوند. نگه‌داری نامحدود طبق تعهدات کاهش داده GDPR / CCPA یک مسئولیت است.
  4. یک اسکن FixVibe ماهانه اجرا کنید. فحص baas.supabase-storage-public سطل‌هایی را که به GET + LIST ناشناس پاسخ می‌دهند می‌کاود. سطل‌های جدید اضافه می‌شوند؛ سطل‌های قدیمی قابلیت رؤیت تغییر می‌دهند — فقط اسکن مداوم این انحراف را می‌گیرد.

گام‌های بعدی

یک اسکن FixVibe را روی URL تولیدی خود اجرا کنید — فهرست‌های ذخیره‌سازی ناشناس زیر baas.supabase-storage-public ظاهر می‌شوند. این چک‌لیست را با اسکنر Supabase RLS برای لایه جدول و افشای کلید service role Supabase در جاوااسکریپت برای مجاورت افشای کلید ترکیب کنید. برای پیکربندی‌های نادرست ذخیره‌سازی در سایر ارائه‌دهندگان BaaS، اسکنر پیکربندی نادرست BaaS را ببینید.

// سطح baas خود را اسکن کنید

جدول باز را پیش از دیگران پیدا کنید.

یک آدرس URL از محیط تولید وارد کنید. FixVibe ارائه‌دهندگان BaaS که اپلیکیشن شما با آن‌ها صحبت می‌کند را شناسایی می‌کند، نقاط پایانی عمومی آن‌ها را اثرانگشت‌برداری می‌کند و گزارش می‌دهد که یک کلاینت بدون احراز هویت چه چیزی می‌تواند بخواند یا بنویسد. رایگان، بدون نصب، بدون کارت اعتباری.

  • پلن رایگان — ۳ اسکن در ماه، بدون نیاز به کارت اعتباری برای ثبت‌نام.
  • اثرانگشت‌برداری غیرفعال BaaS — نیازی به تأیید دامنه نیست.
  • Supabase، Firebase، Clerk، Auth0، Appwrite و بیشتر.
  • پرامپت‌های اصلاحی هوش مصنوعی روی هر یافته — کافی است در Cursor / Claude Code جای‌گذاری کنید.
یک اسکن رایگان BaaS اجرا کنید

نیازی به ثبت‌نام نیست

چک‌لیست امنیت سطل ذخیره‌سازی Supabase: ۲۲ مورد — Docs · FixVibe