// docs / baas security / supabase storage
Sigurnosna checklista za Supabase storage bucket: 22 stavke
Supabase Storage je tanki wrapper oko S3-kompatibilnog bucketa plus isti Row-Level Security model kao baza podataka. To znači da iste RLS zamke koje pogađaju tablice pogađaju i pristup datotekama — uz nekoliko specifičnih za storage koje se pojavljuju kada AI alati za kodiranje žice upload. Ova checklista ima 22 stavke u pet odjeljaka: konfiguracija bucketa, RLS pravila, validacija uploada, signed URL-ovi i operativna higijena. Svaka je provjerljiva u manje od 15 minuta.
Svaka stavka u nastavku je ključna. Za osnovnu mehaniku RLS-a, pogledajte Supabase RLS skener. Za susjednu klasu izlaganja ključeva uz storage, pogledajte Supabase service role ključ izložen u JavaScriptu.
Konfiguracija bucketa
Počnite s ispravnim defaultima. Pogrešno konfiguriran bucket propušta datoteke bez obzira na to je li vaš RLS ispravan ili nije.
- Svaki bucket po defaultu postavite na privatan. U Supabase Dashboardu → Storage → Buckets, isključite prekidač Public bucket osim ako imate eksplicitan razlog (marketinški resursi, javni avatari bez PII-ja). Javni bucketi zaobilaze RLS za operacije čitanja — svatko s imenom bucketa može popisivati i preuzimati.
- Postavite tvrdo ograničenje veličine datoteke na svaki bucket. Dashboard → Bucket settings → File size limit. 50 MB je razuman default za korisničke uploade; namjerno povećajte za video / velike datoteke. Bez ograničenja, jedan zlonamjeran upload može iscrpiti vašu storage kvotu ili mjesečni bandwidth.
- Ograničite dopuštene MIME tipove po bucketu. Popis dopuštenih MIME tipova — eksplicitan popis dopuštenih, ne blokiranih.
image/jpeg,image/png,image/webpza bucketove samo za slike. Nikada ne dopuštajtetext/html,application/javascriptiliimage/svg+xmlu bucketu za korisnički sadržaj — oni se izvršavaju u pregledniku kada se poslužuju preko signed URL-a. - Koristite jedan bucket po tipu sadržaja, a ne jedan dijeljeni bucket. Postavke po bucketu (veličina, MIME tipovi, RLS pravila) jedina su granularnost koju imate. Bucket
user-avatars, bucketdocument-uploadsi bucketpublic-assetslakše je zaključati nego jedan miješani bucket. - Provjerite CORS konfiguraciju ako frontend uploada. Ako korisnici uploadaju izravno iz preglednika na signed URL, CORS bucketa mora navoditi vaš produkcijski origin.
*je prihvatljivo samo za javne buckete — nikada za buckete koji sadrže korisnički PII.
RLS pravila na storage.objects
Supabase Storage pohranjuje metapodatke datoteka u tablici storage.objects. RLS na toj tablici kontrolira tko može čitati, uploadati, ažurirati ili brisati datoteke. Bez RLS-a, javna/privatna oznaka bucketa je vaša jedina zaštita.
- Potvrdite da je RLS uključen na storage.objects.
SELECT rowsecurity FROM pg_tables WHERE schemaname = 'storage' AND tablename = 'objects';mora vratititrue. Supabase ga po defaultu uključuje na novim projektima; provjerite da nije onemogućen. - Napišite SELECT pravilo ograničeno preko
auth.uid()za privatne buckete.CREATE POLICY "users_read_own_files" ON storage.objects FOR SELECT USING (auth.uid()::text = (storage.foldername(name))[1]);. Konvencija je da datoteke pohranjujete pod[user-id]/[filename]i koristitestorage.foldername()da izvučete vlasnika iz putanje. - Napišite INSERT pravilo koje primjenjuje istu konvenciju putanje.
CREATE POLICY "users_upload_own" ON storage.objects FOR INSERT WITH CHECK (auth.uid()::text = (storage.foldername(name))[1]);. Bez WITH CHECK, autenticirani korisnik može uploadati u tuđu mapu. - Dodajte UPDATE i DELETE pravila ako vaša aplikacija podržava uređivanje ili brisanje datoteka. Svaka naredba treba svoje pravilo. Preskakanje DELETE-a znači da autenticirani korisnici ne mogu ukloniti svoje datoteke; preskakanje UPDATE-a znači da prepisivanje datoteke tiho ne uspijeva.
- Testirajte pristup između korisnika u dvije sesije preglednika. Prijavite se kao korisnik A, uploadajte datoteku, kopirajte putanju. Prijavite se kao korisnik B u drugom pregledniku, pokušajte dohvatiti datoteku preko REST API-ja. Odgovor mora biti
403ili404, nikada200.
-- 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]);Validacija uploada
Validirajte svaki upload na serverskoj strani, čak i kada bucket ima ograničenja za MIME i veličinu. AI alati za kodiranje po defaultu generiraju samo klijentsku validaciju; ona ne štiti ništa.
- Ponovo provjerite MIME tip na serverskoj strani iz stvarnih bajtova datoteke, a ne iz headera
Content-Type. Koristite knjižnicu poputfile-type(Node) ili magic-byte sniffing. Napadač može tvrditiContent-Type: image/jpegna datoteci koja je zapravo poliglotski HTML / JavaScript payload. - Uklonite EXIF metapodatke iz uploadanih slika. EXIF može sadržavati GPS koordinate, serijske brojeve uređaja i timestampe. Koristite
sharps.withMetadata(false)iliexif-parserda to uklonite prije pohrane. - Odbijte SVG-ove koji sadrže
scripttagove ilionloadhandlere. SVG je XML — i mnoge AI-generirane aplikacije dopuštaju SVG uploade kao "samo sliku". KoristiteDOMPurifyna serverskoj strani ili u potpunosti odbijte SVG uploade. - Koristite determinističke, nepogodive nazive datoteka. Ne čuvajte originalni naziv datoteke. Koristite UUID ili hash sadržaja datoteke. Originalni nazivi cure ("
passport_scan_2024_01_15.jpg"), a predvidljivi nazivi omogućuju enumeraciju.
Signed URL-ovi
Signed URL-ovi su način na koji klijenti pristupaju privatnim bucketima. Istek, opseg bucketa i ono što se logira su važni.
- Postavite default istek signed URL-a na 1 sat ili manje. Metoda
createSignedUrl(path, expiresIn)u Supabase JS SDK-u uzima sekunde. Nikada ne koristite vrijednosti poput31536000(jedna godina) — URL postaje trajan polujavni link. - Nikada ne pohranjujte signed URL-ove u svojoj bazi. Generirajte svježe na serverskoj strani na svakom zahtjevu. Pohranjen signed URL s istekom od jedne godine koji procuri kroz database dump daje dugotrajan pristup.
- Logirajte generiranje signed URL-a, ne samo uploade datoteka. Ako kasnije posumnjate u kompromitaciju, morate znati tko je generirao koji URL i kada. Logirajte
auth.uid()+ bucket + putanju objekta + timestamp. - Koristite opciju
downloadAskada poslužujete datoteke koje su uploadali korisnici.createSignedUrl(path, expiresIn, { download: '.jpg' })nameće headerContent-Disposition: attachmenttako da se datoteka preuzima umjesto renderira — neutralizira klasu izvršavanja HTML / SVG / HTML-u-PDF-u.
Operativna higijena
Konfiguracija storagea s vremenom driftuje. Ove četiri operativne stavke održavaju površinu napada uskom.
- Auditirajte buckete kvartalno. Dashboard → Storage → Buckets. Potvrdite da javni/privatni status i popisi MIME tipova odgovaraju onome što aplikacija očekuje. Bucketi stvoreni "privremeno" postaju trajni ako ih nitko ne ukloni.
- Pratite anonimne list operacije. Storage logovi (Dashboard → Logs → Storage) bilježe
LISTzahtjeve. Skok anonimnih list zahtjeva prema privatnom bucketu znači da ga netko ispituje izvana. - Postavite pravila zadržavanja za efemerne uploade. Privremeni bucketi (pregled slika, draft uploadi) trebaju automatski brisati nakon 24-72 sata preko zakazane funkcije. Neograničeno zadržavanje je odgovornost prema obvezama minimizacije podataka u GDPR-u / CCPA-i.
- Pokrećite FixVibe sken mjesečno. Provjera
baas.supabase-storage-publicispituje buckete koji odgovaraju na anonimniGET+LIST. Novi bucketi se dodaju; stari mijenjaju vidljivost — samo kontinuirano skeniranje hvata drift.
Sljedeći koraci
Pokrenite FixVibe sken prema svom produkcijskom URL-u — anonimni storage popisi pojavljuju se pod baas.supabase-storage-public. Uparite ovu checklistu s Supabase RLS skenerom za sloj tablica i Supabase service role ključem izloženim u JavaScriptu za susjednost izlaganja ključeva. Za pogrešne konfiguracije storagea kod ostalih BaaS providera, pogledajte Skener BaaS pogrešnih konfiguracija.
