FixVibe

// docs / baas security / supabase storage

Checklista för Supabase storage-bucket-säkerhet: 22 punkter

Supabase Storage är ett tunt lager runt en S3-kompatibel bucket plus samma row-level security-modell som databasen. Det betyder att samma RLS-fallgropar som drabbar tabeller drabbar filåtkomst — plus några storage-specifika som dyker upp när AI-kodningsverktyg kopplar upp uppladdningar. Den här checklistan har 22 punkter i fem sektioner: bucket-konfiguration, RLS-policys, uppladdningsvalidering, signerade URL:er och operativ hygien. Var och en är verifierbar på under 15 minuter.

Varje punkt nedan är essentiell. För den underliggande RLS-mekaniken, se Supabase RLS-scanner. För nyckel-exponeringsklassen angränsande storage, se Supabase service-role-nyckel exponerad i JavaScript.

Bucket-konfiguration

Börja med rätt defaults. En felkonfigurerad bucket läcker filer oavsett om din RLS är korrekt eller inte.

  1. Sätt varje bucket som standard till privat. I Supabase-dashboarden → Storage → Buckets, sätt Public bucket-växeln till av om du inte har en explicit anledning (marknadsföringstillgångar, publika avatarer utan PII). Publika buckets kringgår RLS för läsoperationer — vem som helst med bucket-namnet kan lista och ladda ner.
  2. Sätt en hård filstorleksgräns på varje bucket. Dashboard → Bucket-inställningar → File size limit. 50 MB är en vettig standard för användaruppladdningar; höj den medvetet för video-/storfilsfall. Utan gräns kan en enda skadlig uppladdning förbruka din lagringskvot eller månadsbandbredd.
  3. Begränsa tillåtna MIME-typer per bucket. Tillåten MIME-typ-lista — explicit allowlist, inte blocklist. image/jpeg, image/png, image/webp för bild-bara-buckets. Tillåt aldrig text/html, application/javascript eller image/svg+xml i en användarinnehållsbucket — de exekverar i webbläsaren när de serveras via signerad URL.
  4. Använd en bucket per innehållstyp, inte en delad bucket. Per-bucket-inställningar (storlek, MIME-typer, RLS-policys) är den granularitet du har. En user-avatars-bucket, en document-uploads-bucket och en public-assets-bucket är lättare att låsa än en blandad bucket.
  5. Verifiera CORS-konfigurationen om frontend laddar upp. Om användare laddar upp direkt från webbläsaren till en signerad URL måste bucketens CORS lista din produktionsorigin. * är acceptabelt endast för publika buckets — aldrig för buckets som innehåller användar-PII.

RLS-policys på storage.objects

Supabase Storage lagrar fil-metadata i tabellen storage.objects. RLS på den tabellen styr vem som kan läsa, ladda upp, uppdatera eller radera filer. Utan RLS är bucketens public/private-flagga ditt enda skydd.

  1. Bekräfta att RLS är aktiverat på storage.objects. SELECT rowsecurity FROM pg_tables WHERE schemaname = 'storage' AND tablename = 'objects'; måste returnera true. Supabase aktiverar det som standard på nya projekt; verifiera att det inte har inaktiverats.
  2. Skriv en SELECT-policy begränsad till auth.uid() för privata buckets. CREATE POLICY "users_read_own_files" ON storage.objects FOR SELECT USING (auth.uid()::text = (storage.foldername(name))[1]);. Konventionen är att lagra filer under [user-id]/[filename] och använda storage.foldername() för att extrahera ägaren ur sökvägen.
  3. Skriv en INSERT-policy som tvingar fram samma sökvägskonvention. CREATE POLICY "users_upload_own" ON storage.objects FOR INSERT WITH CHECK (auth.uid()::text = (storage.foldername(name))[1]);. Utan WITH CHECK kan en autentiserad användare ladda upp i en annan användares mapp.
  4. Lägg till UPDATE- och DELETE-policys om din app stöder filändringar eller -borttagningar. Varje kommando behöver sin egen policy. Att hoppa över DELETE betyder att autentiserade användare inte kan ta bort sina egna filer; att hoppa över UPDATE betyder att filöverskrivningar tyst misslyckas.
  5. Testa korsanvändaråtkomst i två webbläsarsessioner. Logga in som användare A, ladda upp en fil, kopiera sökvägen. Logga in som användare B i en annan webbläsare, försök hämta filen via REST-API:t. Svaret måste vara 403 eller 404, aldrig 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]);

Uppladdningsvalidering

Validera varje uppladdning serverside, även när bucketen har MIME- och storleksrestriktioner. AI-kodningsverktyg genererar som standard endast klientsidesvalidering; det skyddar ingenting.

  1. Kontrollera MIME-typen serverside på nytt utifrån filens faktiska bytes, inte Content-Type-headern. Använd ett bibliotek som file-type (Node) eller magic-byte-sniffing. En angripare kan deklarera Content-Type: image/jpeg på en fil som i själva verket är en polyglott HTML-/JavaScript-payload.
  2. Strippa EXIF-metadata från uppladdade bilder. EXIF kan innehålla GPS-koordinater, enhetens serienummer och tidsstämplar. Använd sharp med .withMetadata(false) eller exif-parser för att strippa innan lagring.
  3. Avvisa SVG:er som innehåller script-taggar eller onload-handlers. SVG är XML — och många AI-genererade appar tillåter SVG-uppladdningar som "bara en bild". Använd DOMPurify serverside eller vägra SVG-uppladdningar helt.
  4. Använd deterministiska, icke gissningsbara filnamn. Behåll inte det ursprungliga filnamnet. Använd en UUID eller en hash av filinnehållet. Ursprungliga filnamn läcker ("passport_scan_2024_01_15.jpg") och förutsägbara namn möjliggör enumeration.

Signerade URL:er

Signerade URL:er är hur klienter kommer åt privata buckets. Förfallotiden, bucket-scopet och vad som loggas spelar roll.

  1. Sätt signerad-URL-förfallotid till 1 timme eller mindre som standard. Supabase JS-SDK:ts createSignedUrl(path, expiresIn) tar sekunder. Använd aldrig värden som 31536000 (ett år) — URL:en blir en permanent semi-publik länk.
  2. Lagra aldrig signerade URL:er i din databas. Generera färska serverside vid varje förfrågan. En lagrad signerad URL med 1-årsförfall som läcker via en databasdump ger långsiktig åtkomst.
  3. Logga signerad-URL-generering, inte bara filuppladdningar. Om du misstänker en kompromettering senare behöver du veta vem som genererade vilken URL när. Logga auth.uid() + bucket + objektsökväg + tidsstämpel.
  4. Använd downloadAs-alternativet när du serverar användaruppladdade filer. createSignedUrl(path, expiresIn, { download: '.jpg' }) tvingar fram en Content-Disposition: attachment-header så att filen laddas ner istället för att renderas — avväpnar HTML-/SVG-/HTML-i-PDF-exekveringsklassen.

Operativ hygien

Storage-konfiguration driftar över tid. Dessa fyra operativa punkter håller ytan stram.

  1. Granska buckets kvartalsvis. Dashboard → Storage → Buckets. Bekräfta att public/private-status och MIME-typ-listor matchar vad appen förväntar sig. Buckets som skapats "tillfälligt" blir permanenta om ingen tar bort dem.
  2. Övervaka anonyma listoperationer. Storage-loggar (Dashboard → Logs → Storage) registrerar LIST-förfrågningar. En spik av anonyma list-förfrågningar mot en privat bucket betyder att någon sonderar den utifrån.
  3. Sätt en retentionspolicy för efemära uppladdningar. Temp-buckets (förhandsgranskning, utkast-uppladdningar) bör auto-raderas efter 24–72 timmar via en schemalagd funktion. Obegränsad retention är en skyldighet under GDPR/CCPA-dataminimerings-åtaganden.
  4. Kör en FixVibe-scanning månadsvis. baas.supabase-storage-public-checken sonderar buckets som svarar på anonyma GET + LIST. Nya buckets tillkommer; gamla ändrar synlighet — bara kontinuerlig skanning fångar driften.

Nästa steg

Kör en FixVibe-scanning mot din produktions-URL — anonyma storage-listningar dyker upp under baas.supabase-storage-public. Kombinera den här checklistan med Supabase RLS-scanner för tabell-lagret och Supabase service-role-nyckel exponerad i JavaScript för den angränsande nyckel-exponeringen. För storage-felkonfigurationer hos andra BaaS-leverantörer, se BaaS-felkonfigurationsscanner.

// skanna din baas-yta

Hitta den öppna tabellen innan någon annan gör det.

Klistra in en produktions-URL. FixVibe identifierar BaaS-leverantörerna din app pratar med, fingeravtryckar deras publika endpoints och rapporterar vad en oautentiserad klient kan läsa eller skriva. Gratis, ingen installation, inget kort.

  • Gratisnivå — 3 skanningar/månad, inget kort vid registrering.
  • Passiv BaaS-fingeravtryckning — ingen domänverifiering krävs.
  • Supabase, Firebase, Clerk, Auth0, Appwrite och fler.
  • AI-fixprompter på varje fynd — klistra tillbaka in i Cursor / Claude Code.
Kör en gratis BaaS-skanning

ingen registrering krävs

Checklista för Supabase storage-bucket-säkerhet: 22 punkter — Docs · FixVibe