FixVibe

// docs / baas security / supabase storage

Supabase storage bucket güvenlik kontrol listesi: 22 madde

Supabase Storage, S3 uyumlu bir bucket'ın etrafındaki ince bir sarmalayıcıdır ve veritabanıyla aynı Row-Level Security modeline sahiptir. Bu, tabloları etkileyen aynı RLS tuzaklarının dosya erişimini de etkilediği anlamına gelir — ve yapay zeka kodlama araçları yüklemeleri bağladığında ortaya çıkan birkaç storage'a özgü tuzak. Bu kontrol listesi beş bölümde 22 madde içerir: bucket yapılandırması, RLS policy'leri, yükleme doğrulama, imzalı URL'ler ve operasyonel hijyen. Her biri 15 dakikadan kısa sürede doğrulanabilir.

Aşağıdaki her madde temeldir. Temel RLS mekanikleri için Supabase RLS tarayıcısı'na bakın. Storage'a komşu anahtar ifşa sınıfı için JavaScript'te ifşa olan Supabase service role anahtarı'na bakın.

Bucket yapılandırması

Doğru varsayılanlarla başlayın. Yanlış yapılandırılmış bir bucket, RLS'iniz doğru olsa da olmasa da dosya sızdırır.

  1. Her bucket'ı varsayılan olarak private yapın. Supabase Dashboard → Storage → Buckets'ta, açık bir nedeniniz yoksa (pazarlama varlıkları, PII içermeyen public avatarlar) Public bucket geçişini kapatın. Public bucket'lar okuma işlemleri için RLS'i atlar — bucket adına sahip herkes listeleyebilir ve indirebilir.
  2. Her bucket'ta sert bir dosya boyutu sınırı belirleyin. Dashboard → Bucket settings → File size limit. 50 MB kullanıcı yüklemeleri için makul bir varsayılandır; video / büyük dosya kullanım senaryoları için kasıtlı olarak yükseltin. Sınır olmadan, tek bir kötü niyetli yükleme storage kotanızı veya aylık bant genişliğinizi tüketebilir.
  3. Her bucket için izin verilen MIME türlerini kısıtlayın. İzin verilen MIME türleri listesi — açık allowlist, blocklist değil. Yalnızca resim içeren bucket'lar için image/jpeg, image/png, image/webp. Kullanıcı içeriği bucket'ında asla text/html, application/javascript veya image/svg+xml'a izin vermeyin — imzalı URL üzerinden sunulduklarında tarayıcıda yürütülürler.
  4. Bir paylaşımlı bucket değil, içerik türü başına bir bucket kullanın. Bucket başına ayarlar (boyut, MIME türleri, RLS policy'leri) sahip olduğunuz ayrıntı düzeyidir. Bir user-avatars bucket'ı, bir document-uploads bucket'ı ve bir public-assets bucket'ı, karışık bir bucket'tan kilitlemesi daha kolaydır.
  5. Frontend yüklerse CORS yapılandırmasını doğrulayın. Kullanıcılar doğrudan tarayıcıdan imzalı bir URL'ye yüklüyorsa, bucket CORS üretim origin'inizi listelemelidir. * yalnızca public bucket'lar için kabul edilebilir — asla kullanıcı PII içeren bucket'lar için değil.

storage.objects üzerinde RLS policy'leri

Supabase Storage dosya meta verilerini storage.objects tablosunda saklar. Bu tablodaki RLS, kimin dosya okuyabileceğini, yükleyebileceğini, güncelleyebileceğini veya silebileceğini kontrol eder. RLS olmadan, bucket'ın public/private bayrağı tek korumanızdır.

  1. storage.objects üzerinde RLS'in etkin olduğunu teyit edin. SELECT rowsecurity FROM pg_tables WHERE schemaname = 'storage' AND tablename = 'objects'; true döndürmelidir. Supabase yeni projelerde varsayılan olarak etkinleştirir; devre dışı bırakılmadığını doğrulayın.
  2. Private bucket'lar için auth.uid()'ye kapsamlanmış bir SELECT policy'si yazın. CREATE POLICY "users_read_own_files" ON storage.objects FOR SELECT USING (auth.uid()::text = (storage.foldername(name))[1]);. Konvansiyon, dosyaları [user-id]/[filename] altında saklamak ve sahibi yoldan çıkarmak için storage.foldername() kullanmaktır.
  3. Aynı yol konvansiyonunu zorlayan bir INSERT policy'si yazın. CREATE POLICY "users_upload_own" ON storage.objects FOR INSERT WITH CHECK (auth.uid()::text = (storage.foldername(name))[1]);. WITH CHECK olmadan, kimliği doğrulanmış bir kullanıcı başka bir kullanıcının klasörüne yükleyebilir.
  4. Uygulamanız dosya düzenlemelerini veya silmelerini destekliyorsa UPDATE ve DELETE policy'leri ekleyin. Her komutun kendi policy'sine ihtiyacı vardır. DELETE'i atlamak, kimliği doğrulanmış kullanıcıların kendi dosyalarını kaldıramaması demektir; UPDATE'i atlamak dosya üzerine yazmaların sessizce başarısız olması demektir.
  5. İki tarayıcı oturumunda kullanıcılar arası erişimi test edin. Kullanıcı A olarak oturum açın, bir dosya yükleyin, yolu kopyalayın. Başka bir tarayıcıda Kullanıcı B olarak oturum açın, dosyayı REST API üzerinden almayı deneyin. Yanıt 403 veya 404 olmalı, asla 200 olmamalıdır.
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]);

Yükleme doğrulama

Bucket'ta MIME ve boyut kısıtlamaları olsa bile her yüklemeyi sunucu tarafında doğrulayın. Yapay zeka kodlama araçları varsayılan olarak yalnızca istemci doğrulaması üretir; bu hiçbir şeyi korumaz.

  1. MIME türünü Content-Type başlığından değil, dosyanın gerçek baytlarından sunucu tarafında yeniden kontrol edin. file-type (Node) gibi bir kütüphane veya magic-byte sniffing kullanın. Bir saldırgan, aslında poliglot HTML / JavaScript yükü olan bir dosyada Content-Type: image/jpeg iddia edebilir.
  2. Yüklenen resimlerden EXIF meta verisini soyun. EXIF GPS koordinatları, cihaz seri numaraları ve zaman damgaları içerebilir. Storage'dan önce soymak için .withMetadata(false) ile sharp veya exif-parser kullanın.
  3. script etiketleri veya onload işleyicileri içeren SVG'leri reddedin. SVG XML'dir — ve birçok yapay zeka tarafından üretilmiş uygulama SVG yüklemelerine "sadece bir resim" olarak izin verir. Sunucu tarafında DOMPurify kullanın veya SVG yüklemelerini tamamen reddedin.
  4. Belirlenebilir ama tahmin edilemez dosya adları kullanın. Orijinal dosya adını korumayın. Bir UUID veya dosya içeriğinin bir hash'ini kullanın. Orijinal dosya adları sızıntı yapar ("passport_scan_2024_01_15.jpg") ve tahmin edilebilir adlar sıralamayı mümkün kılar.

İmzalı URL'ler

İmzalı URL'ler, istemcilerin private bucket'lara nasıl eriştiğidir. Sona erme süresi, bucket kapsamı ve neyin loglandığı önemlidir.

  1. İmzalı URL son kullanma tarihini varsayılan olarak 1 saat veya daha az yapın. Supabase JS SDK'sının createSignedUrl(path, expiresIn) saniye alır. 31536000 (bir yıl) gibi değerleri asla kullanmayın — URL kalıcı yarı-public bir bağlantı olur.
  2. İmzalı URL'leri asla veritabanınızda saklamayın. Her istekte sunucu tarafında taze olanlar oluşturun. Veritabanı dökümü yoluyla sızan 1 yıllık son kullanma tarihine sahip saklanmış bir imzalı URL, uzun vadeli erişim verir.
  3. Sadece dosya yüklemelerini değil, imzalı URL oluşturmayı da loglayın. Daha sonra bir tehlikeden şüphelenirseniz, hangi URL'yi kimin ne zaman oluşturduğunu bilmeniz gerekir. auth.uid() + bucket + nesne yolu + zaman damgasını loglayın.
  4. Kullanıcı tarafından yüklenen dosyaları sunarken downloadAs seçeneğini kullanın. createSignedUrl(path, expiresIn, { download: '.jpg' }), render etmek yerine dosyanın indirilmesi için Content-Disposition: attachment başlığını zorlar — HTML / SVG / PDF içinde HTML yürütme sınıfını yener.

Operasyonel hijyen

Storage yapılandırması zamanla kayar. Bu dört operasyonel madde yüzeyi sıkı tutar.

  1. Bucket'ları üç ayda bir denetleyin. Dashboard → Storage → Buckets. Public/private durumu ve MIME türü listelerinin uygulamanın beklediği şekilde olduğunu teyit edin. "Geçici olarak" oluşturulan bucket'lar, kimse kaldırmazsa kalıcı hale gelir.
  2. Anonim list işlemlerini izleyin. Storage logları (Dashboard → Logs → Storage) LIST isteklerini kaydeder. Private bir bucket'a karşı anonim list isteklerinin yükselmesi, birinin dışarıdan onu sondaladığı anlamına gelir.
  3. Geçici yüklemeler için bir saklama policy'si belirleyin. Geçici bucket'lar (resim önizleme, taslak yüklemeler), zamanlanmış bir fonksiyon aracılığıyla 24-72 saat sonra otomatik silinmelidir. Belirsiz saklama, GDPR / CCPA veri minimizasyonu yükümlülükleri altında bir sorumluluktur.
  4. Aylık bir FixVibe taraması çalıştırın. baas.supabase-storage-public kontrolü, anonim GET + LIST'e yanıt veren bucket'lar için sondalar gönderir. Yeni bucket'lar eklenir; eski olanlar görünürlüğü değiştirir — sadece sürekli tarama kaymayı yakalar.

Sonraki adımlar

Üretim URL'nize karşı bir FixVibe taraması çalıştırın — anonim storage listelemeleri baas.supabase-storage-public altında görünür. Bu kontrol listesini tablo katmanı için Supabase RLS tarayıcısı ve anahtar ifşa komşuluğu için JavaScript'te ifşa olan Supabase service role anahtarı ile eşleştirin. Diğer BaaS sağlayıcılarındaki storage yanlış yapılandırmaları için BaaS yanlış yapılandırma tarayıcısı bölümüne bakın.

// baas yüzeyinizi tarayın

Açık tabloyu başkası bulmadan önce bulun.

Bir üretim URL'si girin. FixVibe uygulamanızın konuştuğu BaaS sağlayıcılarını sıralar, açık endpoint'lerini parmak izlerine göre tespit eder ve kimliği doğrulanmamış bir istemcinin neleri okuyup yazabildiğini raporlar. Ücretsiz, kurulum yok, kart gerekmez.

  • Ücretsiz tarife — ayda 3 tarama, kayıt için kart gerekmez.
  • Pasif BaaS parmak izi — domain doğrulaması gerekmez.
  • Supabase, Firebase, Clerk, Auth0, Appwrite ve daha fazlası.
  • Her bulguda yapay zeka düzeltme istemleri — Cursor / Claude Code'a yapıştırın.
Supabase storage bucket güvenlik kontrol listesi: 22 madde — Docs · FixVibe