FixVibe

// docs / baas security / supabase storage

Supabase storage bucket security checklist: 22 items

Ang Supabase Storage ay isang manipis na wrapper sa isang S3-compatible bucket kasama ang parehong Row-Level Security model gaya ng database. Iyon ay nangangahulugang ang parehong RLS pitfalls na nakakaapekto sa mga talahanayan ay nakakaapekto rin sa file access โ€” at ilang storage-specific na lumalabas kapag iniugnay ng AI coding tools ang mga uploads. Ang checklist na ito ay 22 items sa limang seksyon: konpigurasyon ng bucket, RLS policies, upload validation, signed URLs, at operational hygiene. Bawat isa ay maberipika sa wala pang 15 minuto.

Ang bawat item sa ibaba ay mahalaga. Para sa pinagbabatayang RLS mechanics, tingnan ang Supabase RLS scanner. Para sa key-exposure class na katabi ng storage, tingnan ang Supabase service role key na naka-expose sa JavaScript.

Konpigurasyon ng bucket

Magsimula sa tamang defaults. Ang isang maling konpigurasyon na bucket ay nag-le-leak ng files anuman ang katumpakan ng iyong RLS.

  1. I-default ang bawat bucket sa private. Sa Supabase Dashboard โ†’ Storage โ†’ Buckets, itakda ang Public bucket toggle sa off maliban kung mayroon kang tahasang dahilan (marketing assets, public avatars na walang PII). Ang mga public buckets ay nakaka-bypass sa RLS para sa read operations โ€” sino mang may pangalan ng bucket ay makakapag-list at mag-download.
  2. Magtakda ng hard file size limit sa bawat bucket. Dashboard โ†’ Bucket settings โ†’ File size limit. Ang 50 MB ay isang makatuwirang default para sa user uploads; itaas ito nang sinasadya para sa video / large-file use cases. Kung walang limit, ang isang malisyosong upload ay maaaring maubos ang iyong storage quota o ang iyong buwanang bandwidth.
  3. Limitahan ang mga pinapayagang MIME types bawat bucket. Allowed MIME types list โ€” tahasang allowlist, hindi blocklist. image/jpeg, image/png, image/webp para sa image-only buckets. Huwag kailanman pahintulutan ang text/html, application/javascript, o image/svg+xml sa isang user-content bucket โ€” naglalaro sila sa browser kapag iniserbisyo sa pamamagitan ng signed URL.
  4. Gumamit ng isang bucket bawat content type, hindi isang shared bucket. Ang per-bucket settings (size, MIME types, RLS policies) ay ang granularity na meron ka. Ang isang user-avatars bucket, isang document-uploads bucket, at isang public-assets bucket ay mas madali ipa-lock down kaysa sa isang halo-halong bucket.
  5. I-verify ang CORS configuration kung nag-a-upload ang frontend. Kung direktang nag-a-upload ang mga users mula sa browser papunta sa signed URL, ang bucket CORS ay dapat magtala ng iyong production origin. Ang * ay katanggap-tanggap para lamang sa public buckets โ€” hindi kailanman para sa mga buckets na naglalaman ng user PII.

Mga RLS policy sa storage.objects

Ang Supabase Storage ay nag-iimbak ng file metadata sa storage.objects table. Kinokontrol ng RLS sa table na iyon kung sino ang makakabasa, mag-upload, mag-update, o magtanggal ng mga files. Kung walang RLS, ang public/private flag ng bucket ay ang iyong tanging proteksyon.

  1. Kumpirmahin na naka-enable ang RLS sa storage.objects. Ang SELECT rowsecurity FROM pg_tables WHERE schemaname = 'storage' AND tablename = 'objects'; ay dapat magbalik ng true. Naka-enable ito ng Supabase by default sa mga bagong project; i-verify na hindi ito na-disable.
  2. Magsulat ng SELECT policy na sakop ng auth.uid() para sa private buckets. CREATE POLICY "users_read_own_files" ON storage.objects FOR SELECT USING (auth.uid()::text = (storage.foldername(name))[1]);. Ang convention ay mag-imbak ng files sa ilalim ng [user-id]/[filename] at gamitin ang storage.foldername() upang kuhanin ang owner mula sa path.
  3. Magsulat ng INSERT policy na nag-eenforce ng parehong path convention. CREATE POLICY "users_upload_own" ON storage.objects FOR INSERT WITH CHECK (auth.uid()::text = (storage.foldername(name))[1]);. Kung walang WITH CHECK, ang isang authenticated user ay makakapag-upload sa folder ng ibang user.
  4. Magdagdag ng UPDATE at DELETE policies kung sinusuportahan ng iyong app ang file edits o deletes. Bawat command ay nangangailangan ng sariling policy. Ang paglaktaw sa DELETE ay nangangahulugang ang mga authenticated users ay hindi makakapagtanggal ng sarili nilang files; ang paglaktaw sa UPDATE ay nangangahulugang ang mga file overwrites ay tahimik na nabibigo.
  5. I-test ang cross-user access sa dalawang browser sessions. Mag-sign in bilang User A, mag-upload ng file, kopyahin ang path. Mag-sign in bilang User B sa ibang browser, subukang kunin ang file sa pamamagitan ng REST API. Ang response ay dapat 403 o 404, hindi kailanman 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 validation

I-validate ang bawat upload server-side, kahit na ang bucket ay may MIME at size constraints. Ang AI coding tools ay gumagawa ng client-only validation by default; iyon ay hindi nagpoprotekta sa anumang bagay.

  1. I-recheck ang MIME type server-side mula sa aktwal na bytes ng file, hindi sa Content-Type header. Gumamit ng library tulad ng file-type (Node) o magic-byte sniffing. Maaaring i-claim ng umaatake ang Content-Type: image/jpeg sa isang file na aktwal na polyglot HTML / JavaScript payload.
  2. Tanggalin ang EXIF metadata mula sa mga upload na imahe. Ang EXIF ay maaaring maglaman ng GPS coordinates, device serial numbers, at timestamps. Gumamit ng sharp na may .withMetadata(false) o exif-parser upang tanggalin bago mag-storage.
  3. Tanggihan ang mga SVG na naglalaman ng script tags o onload handlers. Ang SVG ay XML โ€” at maraming AI-generated apps ang pumapayag sa SVG uploads bilang "isa pang image lang." Gumamit ng DOMPurify server-side o tumanggi sa SVG uploads nang buo.
  4. Gumamit ng deterministic, hindi mahuhulaang filenames. Huwag panatilihin ang orihinal na filename. Gumamit ng UUID o hash ng nilalaman ng file. Ang mga orihinal na filename ay nag-le-leak ("passport_scan_2024_01_15.jpg") at ang mga predictable na pangalan ay nagbibigay-daan sa enumeration.

Mga signed URL

Ang mga signed URLs ay kung paano nag-a-access ng mga private buckets ang mga clients. Mahalaga ang expiry, ang bucket scope, at kung ano ang nila-log.

  1. I-default ang signed-URL expiry sa 1 oras o mas kaunti. Ang createSignedUrl(path, expiresIn) ng Supabase JS SDK ay tumatanggap ng segundo. Huwag kailanman gumamit ng mga value tulad ng 31536000 (isang taon) โ€” ang URL ay nagiging isang permanenteng semi-public na link.
  2. Huwag kailanman mag-imbak ng signed URLs sa iyong database. Gumawa ng mga sariwang URL server-side sa bawat request. Ang isang naka-imbak na signed URL na may 1-year expiry na nag-le-leak sa pamamagitan ng database dump ay nagbibigay ng pangmatagalang access.
  3. I-log ang signed-URL generation, hindi lamang ang file uploads. Kung may pinaghihinalaang kompromiso later, kailangan mong malaman kung sino ang gumawa ng aling URL at kailan. I-log ang auth.uid() + bucket + object path + timestamp.
  4. Gamitin ang downloadAs option kapag nagse-serve ng mga user-uploaded na files. createSignedUrl(path, expiresIn, { download: '.jpg' }) ay nagpipilit ng Content-Disposition: attachment header upang mag-download ang file sa halip na mag-render โ€” tinatalo ang HTML / SVG / HTML-in-PDF execution class.

Operational hygiene

Ang storage configuration ay umaanod sa paglipas ng panahon. Ang apat na operational items na ito ay nagpapanatiling masikip ang surface.

  1. I-audit ang mga bucket quarterly. Dashboard โ†’ Storage โ†’ Buckets. Kumpirmahin na ang public/private state at MIME-type lists ay tumutugma sa inaasahan ng app. Ang mga bucket na ginawa "pansamantala" ay nagiging permanente kung walang nag-aalis ng mga ito.
  2. Monitor ang anonymous list operations. Ang storage logs (Dashboard โ†’ Logs โ†’ Storage) ay nagre-record ng LIST requests. Ang isang biglaang pagdami ng anonymous list requests laban sa isang private bucket ay nangangahulugan na may nagpo-probe nito mula sa labas.
  3. Magtakda ng retention policy para sa ephemeral uploads. Ang mga temp bucket (image preview, draft uploads) ay dapat awtomatikong magtanggal pagkatapos ng 24-72 oras sa pamamagitan ng scheduled function. Ang walang-katapusang retention ay isang pananagutan sa ilalim ng GDPR / CCPA data-minimisation obligations.
  4. Magpatakbo ng FixVibe scan buwan-buwan. Ang baas.supabase-storage-public check ay nagpo-probe para sa mga buckets na tumutugon sa anonymous GET + LIST. Ang mga bagong bucket ay nadadagdag; ang mga lumang bucket ay nagbabago ang visibility โ€” tanging tuluy-tuloy na pag-scan ang nakakahuli sa drift.

Mga susunod na hakbang

Magpatakbo ng FixVibe scan laban sa iyong production URL โ€” ang mga anonymous storage listings ay lumalabas sa ilalim ng baas.supabase-storage-public. Ipares ang checklist na ito sa Supabase RLS scanner para sa table layer at sa Supabase service role key na naka-expose sa JavaScript para sa adjacency ng key-exposure. Para sa mga storage misconfigurations sa iba pang BaaS providers, tingnan ang BaaS misconfiguration scanner.

// i-scan ang iyong baas surface

Hanapin ang bukas na talahanayan bago ito mahanap ng iba.

Ilagay ang isang production URL. Ine-enumerate ng FixVibe ang mga BaaS providers na kausap ng iyong app, kine-fingerprint ang kanilang mga pampublikong endpoints, at iniuulat kung ano ang mababasa o maisusulat ng isang unauthenticated client. Libre, walang install, walang card.

  • Libreng tier โ€” 3 scan / buwan, walang signup card.
  • Passive BaaS fingerprinting โ€” walang kailangang domain verification.
  • Supabase, Firebase, Clerk, Auth0, Appwrite, at iba pa.
  • Mga AI fix prompts sa bawat finding โ€” i-paste pabalik sa Cursor / Claude Code.
Supabase storage bucket security checklist: 22 items โ€” Docs ยท FixVibe