FixVibe

// docs / baas security / supabase storage

Supabase storage-bucket sikkerhedstjekliste: 22 punkter

Supabase Storage er en tynd indpakning omkring en S3-kompatibel bucket plus den samme Row-Level Security-model som databasen. Det betyder, at de samme RLS-faldgruber, der påvirker tabeller, påvirker filadgang — og nogle få storage-specifikke, der dukker op, når AI-kodeværktøjer kobler uploads. Denne tjekliste er 22 punkter på tværs af fem afsnit: bucket-konfiguration, RLS-politikker, upload-validering, signed URLs og operationel hygiejne. Hvert er verificerbart på under 15 minutter.

Hvert punkt nedenfor er essentielt. For den underliggende RLS-mekanik, se Supabase RLS-scanner. For den nøgleeksponeringsklasse, der støder op til storage, se Supabase service-role-nøgle eksponeret i JavaScript.

Bucket-konfiguration

Start med de rigtige standarder. En fejlkonfigureret bucket lækker filer, uanset om din RLS er korrekt eller ej.

  1. Sæt som standard alle buckets til private. I Supabase Dashboard → Storage → Buckets, sæt Public bucket-toggle til off, medmindre du har en eksplicit grund (marketingaktiver, offentlige avatarer uden PII). Offentlige buckets omgår RLS for læseoperationer — enhver med bucket-navnet kan liste og downloade.
  2. Sæt en hård filstørrelsesgrænse på hver bucket. Dashboard → Bucket settings → File size limit. 50 MB er en fornuftig standard for brugeruploads; hæv den bevidst for video / store filer. Uden en grænse kan en enkelt ondsindet upload udmatte din storage-kvote eller din månedlige båndbredde.
  3. Begræns tilladte MIME-typer per bucket. Listen over tilladte MIME-typer — eksplicit tilladelsesliste, ikke blokliste. image/jpeg, image/png, image/webp for billed-kun-buckets. Tillad aldrig text/html, application/javascript eller image/svg+xml i en brugerindholdsbucket — de eksekveres i browseren, når de serveres via signed URL.
  4. Brug én bucket per indholdstype, ikke én delt bucket. Per-bucket-indstillinger (størrelse, MIME-typer, RLS-politikker) er den granularitet, du har. En user-avatars-bucket, en document-uploads-bucket og en public-assets-bucket er nemmere at låse ned end én blandet bucket.
  5. Verificer CORS-konfiguration, hvis frontend uploader. Hvis brugere uploader direkte fra browseren til en signed URL, skal bucket-CORS angive din produktionsoprindelse. * er kun acceptabelt for offentlige buckets — aldrig for buckets, der indeholder bruger-PII.

RLS-politikker på storage.objects

Supabase Storage gemmer filmetadata i storage.objects-tabellen. RLS på den tabel styrer, hvem der kan læse, uploade, opdatere eller slette filer. Uden RLS er bucketens offentlige/private-flag din eneste beskyttelse.

  1. Bekræft, at RLS er aktiveret på storage.objects. SELECT rowsecurity FROM pg_tables WHERE schemaname = 'storage' AND tablename = 'objects'; skal returnere true. Supabase aktiverer det som standard på nye projekter; verificer, at det ikke er deaktiveret.
  2. Skriv en SELECT-politik begrænset til auth.uid() for private buckets. CREATE POLICY "users_read_own_files" ON storage.objects FOR SELECT USING (auth.uid()::text = (storage.foldername(name))[1]);. Konventionen er at gemme filer under [user-id]/[filename] og bruge storage.foldername() til at udtrække ejeren fra stien.
  3. Skriv en INSERT-politik, der håndhæver den samme stikonvention. CREATE POLICY "users_upload_own" ON storage.objects FOR INSERT WITH CHECK (auth.uid()::text = (storage.foldername(name))[1]);. Uden WITH CHECK kan en autentificeret bruger uploade i en anden brugers mappe.
  4. Tilføj UPDATE- og DELETE-politikker, hvis din app understøtter filredigeringer eller -sletninger. Hvert kommando har brug for sin egen politik. At springe DELETE over betyder, at autentificerede brugere ikke kan fjerne deres egne filer; at springe UPDATE over betyder, at filoverskrivninger fejler lydløst.
  5. Test cross-user-adgang i to browsersessioner. Log ind som Bruger A, upload en fil, kopier stien. Log ind som Bruger B i en anden browser, prøv at hente filen via REST-API'en. Svaret skal være 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]);

Upload-validering

Valider hver upload server-side, selv når bucketen har MIME- og størrelsesbegrænsninger. AI-kodeværktøjer genererer client-only-validering som standard; det beskytter intet.

  1. Tjek MIME-type igen server-side fra filens faktiske bytes, ikke Content-Type-headeren. Brug et bibliotek som file-type (Node) eller magic-byte-sniffing. En angriber kan hævde Content-Type: image/jpeg på en fil, der faktisk er en polyglot HTML / JavaScript-payload.
  2. Fjern EXIF-metadata fra uploadede billeder. EXIF kan indeholde GPS-koordinater, enhedsserienumre og tidsstempler. Brug sharp med .withMetadata(false) eller exif-parser for at fjerne det før storage.
  3. Afvis SVG'er, der indeholder script-tags eller onload-handlers. SVG er XML — og mange AI-genererede apps tillader SVG-uploads som "bare et billede." Brug DOMPurify server-side eller afvis SVG-uploads helt.
  4. Brug deterministiske, ugættelige filnavne. Bevar ikke det originale filnavn. Brug et UUID eller et hash af filindholdet. Originale filnavne lækker ("passport_scan_2024_01_15.jpg"), og forudsigelige navne muliggør optælling.

Signed URLs

Signed URLs er, hvordan klienter tilgår private buckets. Udløb, bucket-omfang og hvad der logges betyder noget.

  1. Sæt signed-URL-udløb til 1 time eller mindre som standard. Supabase JS SDK's createSignedUrl(path, expiresIn) tager sekunder. Brug aldrig værdier som 31536000 (et år) — URL'en bliver et permanent semi-offentligt link.
  2. Gem aldrig signed URLs i din database. Generer friske server-side på hver anmodning. En gemt signed URL med 1-års udløb, der lækker via en database-dump, giver langvarig adgang.
  3. Log signed-URL-generering, ikke kun filuploads. Hvis du mistænker en kompromittering senere, har du brug for at vide, hvem der genererede hvilken URL hvornår. Log auth.uid() + bucket + objektsti + tidsstempel.
  4. Brug downloadAs-optionen, når du serverer brugeruploadede filer. createSignedUrl(path, expiresIn, { download: '.jpg' }) tvinger en Content-Disposition: attachment-header, så filen downloades i stedet for at blive renderet — slår HTML / SVG / HTML-i-PDF-eksekveringsklassen.

Operationel hygiejne

Storage-konfiguration drifter over tid. Disse fire operationelle punkter holder overfladen stram.

  1. Revider buckets kvartalsvis. Dashboard → Storage → Buckets. Bekræft offentlig/privat tilstand og MIME-typelister matcher, hvad appen forventer. Buckets oprettet "midlertidigt" bliver permanente, hvis ingen fjerner dem.
  2. Overvåg anonyme listeoperationer. Storage-logfiler (Dashboard → Logs → Storage) registrerer LIST-anmodninger. En stigning i anonyme listeanmodninger mod en privat bucket betyder, at nogen sonderer den udefra.
  3. Sæt en opbevaringspolitik for kortlivede uploads. Temp-buckets (billedforhåndsvisning, kladdeuploads) skal automatisk slettes efter 24-72 timer via en planlagt funktion. Ubegrænset opbevaring er en byrde under GDPR / CCPA-dataminimeringsforpligtelser.
  4. Kør en FixVibe-scanning månedligt. baas.supabase-storage-public-checken sonderer for buckets, der svarer på anonym GET + LIST. Nye buckets tilføjes; gamle ændrer synlighed — kun kontinuerlig scanning fanger driften.

Næste skridt

Kør en FixVibe-scanning mod din produktions-URL — anonyme storage-listninger dukker op under baas.supabase-storage-public. Par denne tjekliste med Supabase RLS-scanner for tabellaget og Supabase service-role-nøgle eksponeret i JavaScript for nøgleeksponeringsnaboskabet. For storage-fejlkonfigurationer på tværs af andre BaaS-udbydere, se BaaS-fejlkonfigurationsscanner.

// scan din baas-overflade

Find den åbne tabel, før nogen anden gør det.

Indsæt en produktions-URL. FixVibe opregner de BaaS-udbydere, din app taler med, fingeraftrykker deres offentlige endpoints og rapporterer, hvad en uautentificeret klient kan læse eller skrive. Gratis, ingen installation, intet kort.

  • Gratis niveau — 3 scanninger/måned, intet kort ved tilmelding.
  • Passiv BaaS-fingeraftrykning — ingen domæneverifikation påkrævet.
  • Supabase, Firebase, Clerk, Auth0, Appwrite og flere.
  • AI-fix-prompts på hvert fund — indsæt tilbage i Cursor / Claude Code.
Kør en gratis BaaS-scanning

ingen tilmelding krævet

Supabase storage-bucket sikkerhedstjekliste: 22 punkter — Docs · FixVibe