FixVibe

// docs / baas security / supabase storage

Supabase storage bucket security checklist፦ 22 ንጥሎች

Supabase Storage በS3-ተኳሃኝ bucket እና ከdatabase ጋር ተመሳሳዩ Row-Level Security ሞዴል ላይ ቀጭን wrapper ነው። ይህ ማለት table-ዎችን የሚነኩ ተመሳሳዩ የRLS አደጋዎች file access-ንም ይነካሉ — እና AI coding tool-ዎች upload-ዎች ሲያዘጋጁ ጥቂት storage-ተኮር አደጋዎች ይታያሉ። ይህ checklist 22 ንጥሎች በአምስት ክፍሎች ነው፦ bucket configuration፣ RLS policies፣ upload validation፣ signed URLs፣ እና operational hygiene። እያንዳንዱ በ15 ደቂቃዎች ሊረጋገጥ ይችላል።

ከታች ያለ እያንዳንዱ ንጥል አስፈላጊ ነው። ለtable RLS mechanics-ን፣ Supabase RLS scanner ይመልከቱ። ከstorage አጠገብ ላለው key-exposure class፣ Supabase service role key በJavaScript የተጋለጠ ይመልከቱ።

Bucket configuration

በትክክለኛው ነባሪ ይጀምሩ። የተበላሸ bucket RLS ትክክለኛ ቢሆንም file-ዎችን ያፈሳል።

  1. እያንዳንዱን bucket private እንዲሆን ነባሪ ያድርጉ። በSupabase Dashboard → Storage → Buckets፣ ግልጽ ምክንያት ካልኖሮት በስተቀር (marketing assets፣ PII የሌላቸው public avatars) የPublic bucket toggle ወደoff ያድርጉ። Public bucket-ዎች ለread operation-ዎች RLS-ን ይዘላሉ — የbucket ስም ያለው ሁሉ list ሊያደርግ እና ሊያወርድ ይችላል።
  2. በእያንዳንዱ bucket ላይ hard file size limit ያስቀምጡ። Dashboard → Bucket settings → File size limit። ለuser upload 50 MB ምክንያታዊ ነባሪ ነው፤ ለvideo / large-file ጉዳዮች በሆን ብለው ይጨምሩት። ያለ ገደብ፣ አንድ ተንኮለኛ upload የstorage quota-ዎን ወይም ወርሃዊ bandwidth-ዎን ሊጨርስ ይችላል።
  3. በእያንዳንዱ bucket የተፈቀዱ MIME type-ዎችን ይገድቡ። የተፈቀዱ MIME type list — ግልጽ allowlist እንጂ blocklist አይደለም። ለimage-only bucket-ዎች image/jpegimage/pngimage/webp። በuser-content bucket ውስጥ text/htmlapplication/javascript ወይም image/svg+xml በፍጹም አይፍቀዱ — በsigned URL ሲቀርቡ በbrowser ውስጥ ይተገበራሉ።
  4. አንድ bucket ለeach content type ይጠቀሙ፣ ሁለንተናዊ bucket አይደለም። Per-bucket settings (size፣ MIME types፣ RLS policies) ያለዎት granularity ነው። user-avatars bucket፣ document-uploads bucket እና public-assets bucket ከአንድ የተደባለቀ bucket ለመቆለፍ የቀላሉ ናቸው።
  5. Frontend upload ካለ CORS configuration-ን ያረጋግጡ። User-ዎች በቀጥታ ከbrowser ወደ signed URL upload ካደረጉ፣ የbucket CORS production origin-ዎን list ማድረግ አለበት። * ለpublic bucket-ዎች ብቻ ተቀባይነት አለው — በፍጹም user PII የያዙ bucket-ዎች አይደለም።

በstorage.objects ላይ RLS policies

Supabase Storage በstorage.objects table ውስጥ file metadata ያከማቻል። በዚያ table ላይ ያለ RLS ማን file-ዎችን ሊያነብ፣ ሊጭን፣ ሊያዘምን ወይም ሊሰርዝ እንደሚችል ይቆጣጠራል። ያለ RLS፣ የbucket public/private flag ብቸኛ ጥበቃዎ ነው።

  1. RLS በstorage.objects ላይ enable መሆኑን ያረጋግጡ። SELECT rowsecurity FROM pg_tables WHERE schemaname = 'storage' AND tablename = 'objects'; true መመለስ አለበት። Supabase በአዲሶቹ project-ዎች ላይ በነባሪ ያስችላል፤ ያልተደነቀ መሆኑን ያረጋግጡ።
  2. ለprivate bucket-ዎች በauth.uid() የተወሰነ SELECT policy ይጻፉ። CREATE POLICY "users_read_own_files" ON storage.objects FOR SELECT USING (auth.uid()::text = (storage.foldername(name))[1]);። ስምምነቱ file-ዎች በ[user-id]/[filename] ስር ማከማቸት እና ከpath ባለቤትን ለማውጣት storage.foldername()ን መጠቀም ነው።
  3. ተመሳሳዩን path convention የሚያስፈጽም INSERT policy ይጻፉ። CREATE POLICY "users_upload_own" ON storage.objects FOR INSERT WITH CHECK (auth.uid()::text = (storage.foldername(name))[1]);። ያለ WITH CHECK፣ authenticated user ወደ ሌላ user folder ሊጭን ይችላል።
  4. App-ዎ file edits ወይም deletes ካደገፈ UPDATE እና DELETE policies ይጨምሩ። እያንዳንዱ command የራሱ policy ይፈልጋል። DELETE-ን መዝለል authenticated user-ዎች የራሳቸውን file-ዎች ማስወገድ አይችሉም ማለት ነው፤ UPDATE-ን መዝለል የfile overwrite በዝምታ ይወድቃል ማለት ነው።
  5. በሁለት browser session ላይ cross-user access ይፈትኑ። እንደ User A sign in ያድርጉ፣ file ይጭኑ፣ path ይቅዱ። እንደ User B በሌላ browser sign in ያድርጉ፣ file-ውን በREST API ለማግኘት ይሞክሩ። Response 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]);

Upload validation

Bucket MIME እና size constraint ሲኖራቸውም እያንዳንዱን upload server-side validate ያድርጉ። AI coding tool-ዎች በነባሪ client-only validation ይፈጥራሉ፤ ይህ ምንም አይጠብቅም።

  1. MIME type-ን ከContent-Type header ሳይሆን ከfile ትክክለኛ bytes server-side እንደገና ይፈትሹ። እንደ file-type (Node) ወይም magic-byte sniffing የመሳሰሉ library ይጠቀሙ። Attacker በትክክል polyglot HTML / JavaScript payload በሆነ file ላይ Content-Type: image/jpeg ሊያስታውቅ ይችላል።
  2. ከተጫኑ image-ዎች EXIF metadata-ን ይቆፍሩ። EXIF GPS coordinate-ዎች፣ device serial number-ዎች እና timestamp-ዎች ሊይዝ ይችላል። ከstorage በፊት ለመቁረጥ sharpን ከ.withMetadata(false) ጋር ወይም exif-parser ይጠቀሙ።
  3. script tag-ዎች ወይም onload handler-ዎች የያዙ SVG-ዎችን ይከለክሉ። SVG XML ነው — እና ብዙ AI-የተፈጠሩ app-ዎች SVG upload-ዎችን "እንደ image ብቻ" ይፈቅዳሉ። DOMPurifyን server-side ይጠቀሙ ወይም SVG upload-ዎችን ጨርሶ ይከለክሉ።
  4. Deterministic፣ unguessable filename-ዎችን ይጠቀሙ። ኦርጅናል filename ይዘው አይቀመጡ። UUID ወይም file content-ን hash ይጠቀሙ። ኦርጅናል filename-ዎች ይፈሳሉ ("passport_scan_2024_01_15.jpg") እና predictable ስም-ዎች enumeration-ን ይፈቅዳሉ።

Signed URLs

Signed URL-ዎች client-ዎች private bucket-ዎችን የሚደርሱበት መንገድ ነው። Expiry፣ bucket scope እና የሚdog log የሆነው ጠቃሚ ናቸው።

  1. Signed-URL expiry-ን ለ1 ሰዓት ወይም በታች ነባሪ ያድርጉ። የSupabase JS SDK createSignedUrl(path, expiresIn) ሰከንዶችን ይወስዳል። እንደ 31536000 (አንድ ዓመት) ዓይነት እሴት በፍጹም አይጠቀሙ — URL-ው ቋሚ semi-public link ይሆናል።
  2. Signed URL-ዎችን በdatabase ውስጥ በፍጹም አያከማቹ። በእያንዳንዱ request server-side ትኩስ ይፍጠሩ። 1-ዓመት expiry ያለው የተቀመጠ signed URL በdatabase dump በኩል ቢፈስ የረዥም-ጊዜ access ይሰጣል።
  3. Signed-URL generation-ን ይlog ያድርጉ፣ file upload-ዎችን ብቻ አይደለም። በኋላ ላይ compromise ቢጠሮጠር፣ ማን ምን URL መቼ እንደፈጠረ ማወቅ ያስፈልጋል። auth.uid() + bucket + object path + timestamp ይlog ያድርጉ።
  4. User-የተጫኑ file-ዎችን ሲያቀርቡ downloadAs option-ን ይጠቀሙ። createSignedUrl(path, expiresIn, { download: '.jpg' }) file ከመስራት ይልቅ እንዲወርድ Content-Disposition: attachment header ያስከትላል — የHTML / SVG / HTML-in-PDF execution class-ን ይከላከላል።

Operational hygiene

Storage configuration ከጊዜ ጋር ያንሰራፋል። እነዚህ አራት operational ንጥሎች surface-ን ያጠናክራሉ።

  1. Bucket-ዎችን ሩብ-ዓመታዊ audit ያድርጉ። Dashboard → Storage → Buckets። Public/private state እና MIME-type list-ዎች app የሚጠብቀውን የሚዛመዱ መሆኑን ያረጋግጡ። "በጊዜያዊነት" የተፈጠሩ bucket-ዎች ማንም ካላስወገዳቸው ቋሚ ይሆናሉ።
  2. Anonymous list operation-ዎችን ይከታተሉ። Storage logs (Dashboard → Logs → Storage) LIST request-ዎችን ይመዘግባል። በprivate bucket ላይ የanonymous list request-ዎች ድንገተኛ መጨመር ከውጭ የሚመረምር ሰው አለ ማለት ነው።
  3. ለephemeral upload-ዎች retention policy ያስቀምጡ። Temp bucket-ዎች (image preview፣ draft uploads) በscheduled function 24-72 ሰዓታት በኋላ auto-delete መደረግ አለባቸው። Indefinite retention በGDPR / CCPA data-minimisation ግዴታዎች ስር ኃላፊነት ነው።
  4. FixVibe scan ወርሃዊ ያስኪዱ።baas.supabase-storage-public check anonymous GET + LIST ምላሽ የሚሰጡ bucket-ዎችን ይመረምራል። አዲስ bucket-ዎች ይታከላሉ፤ የቆዩት visibility ይቀየራሉ — drift-ን የሚይዘው ቀጣይ scanning ብቻ ነው።

ቀጣይ እርምጃዎች

በproduction URL-ዎ ላይ FixVibe scan ያስኪዱ — anonymous storage listing-ዎች በbaas.supabase-storage-public ስር ይታያሉ። ይህን checklist ከSupabase RLS scanner ጋር ለtable layer እና ከSupabase service role key በJavaScript የተጋለጠ ጋር ለkey-exposure ጎረቤት ያጋጩ። በሌሎች BaaS provider-ዎች ላይ storage misconfiguration-ዎች ለማየት BaaS misconfiguration scanner ይመልከቱ።

// የbaas surface-ዎን scan ያድርጉ

ሌላ ሰው ከማግኘቱ በፊት ክፍት table-ውን ይፈልጉ።

የproduction URL ያስገቡ። FixVibe app-ዎ ከሚነጋገራቸው BaaS provider-ዎች ጋር enumerate ያደርጋል፣ የእነሱን public endpoint-ዎች fingerprint ያደርጋል፣ እና unauthenticated client ሊያነብ ወይም ሊጽፍ የሚችለውን ይዘግባል። ነጻ ነው፣ install አይፈልግም፣ card አያስፈልግም።

  • ነጻ tier — በወር 3 scan፣ ለsignup card አያስፈልግም።
  • Passive BaaS fingerprinting — domain verification አያስፈልገውም።
  • Supabase፣ Firebase፣ Clerk፣ Auth0፣ Appwrite እና ሌሎች።
  • በእያንዳንዱ finding ላይ AI fix prompt — ወደ Cursor / Claude Code ይለጥፉት።
ነጻ BaaS scan ያስኪዱ

signup አያስፈልግም

Supabase storage bucket security checklist፦ 22 ንጥሎች — Docs · FixVibe