// 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 tabele pogađaju i pristup fajlovima — 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 politike, 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 konfigurisan bucket curi fajlove bez obzira na to da li je 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 — svako s imenom bucketa može da lista i preuzima.
- Postavite tvrdo ograničenje veličine fajla na svaki bucket. Dashboard → Bucket settings → File size limit. 50 MB je razuman default za korisničke uploade; namjerno povećajte za video / velike fajlove. Bez ograničenja, jedan zlonamjeran upload može iscrpiti vašu storage kvotu ili mjesečni bandwidth.
- Ograničite dozvoljene MIME tipove po bucketu. Lista dozvoljenih MIME tipova — eksplicitna lista dozvoljenih, ne blokiranih.
image/jpeg,image/png,image/webpza bucketove samo za slike. Nikada ne dozvoljavajtetext/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, ne jedan dijeljeni bucket. Postavke po bucketu (veličina, MIME tipovi, RLS politike) 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 uploaduje. Ako korisnici uploaduju direktno 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 politike na storage.objects
Supabase Storage čuva metapodatke fajlova u tabeli storage.objects. RLS na toj tabeli kontroliše ko može čitati, uploadovati, ažurirati ili brisati fajlove. 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 politiku ograničenu 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 fajlove čuvate pod[user-id]/[filename]i koristitestorage.foldername()da izvučete vlasnika iz putanje. - Napišite INSERT politiku koja 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 uploadovati u tuđi folder. - Dodajte UPDATE i DELETE politike ako vaša aplikacija podržava uređivanje ili brisanje fajlova. Svaka komanda treba svoju politiku. Preskakanje DELETE-a znači da autenticirani korisnici ne mogu ukloniti svoje fajlove; preskakanje UPDATE-a znači da prepisivanje fajla tiho ne uspijeva.
- Testirajte pristup između korisnika u dvije browser sesije. Prijavite se kao korisnik A, uploadujte fajl, kopirajte putanju. Prijavite se kao korisnik B u drugom pregledniku, pokušajte dohvatiti fajl 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 fajla, a ne iz headera
Content-Type. Koristite biblioteku poputfile-type(Node) ili magic-byte sniffing. Napadač može tvrditiContent-Type: image/jpegna fajlu koji je zapravo poliglotski HTML / JavaScript payload. - Uklonite EXIF metapodatke iz uploadovanih slika. EXIF može sadržavati GPS koordinate, serijske brojeve uređaja i timestampove. Koristite
sharps.withMetadata(false)iliexif-parserda to uklonite prije čuvanja. - Odbacite SVG-ove koji sadrže
scripttagove ilionloadhandlere. SVG je XML — i mnoge AI-generirane aplikacije dozvoljavaju SVG uploade kao "samo sliku". KoristiteDOMPurifyna serverskoj strani ili u potpunosti odbijte SVG uploade. - Koristite determinističke, nepogodive nazive fajlova. Ne čuvajte originalni naziv fajla. Koristite UUID ili hash sadržaja fajla. Originalni nazivi curi ("
passport_scan_2024_01_15.jpg"), a predvidljivi nazivi omogućavaju enumeraciju.
Signed URL-ovi
Signed URL-ovi su način na koji klijenti pristupaju privatnim bucketima. Istek, opseg bucketa i ono što se loguje 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 permanentni polujavni link. - Nikada ne čuvajte signed URL-ove u svojoj bazi. Generirajte svježe na serverskoj strani na svakom zahtjevu. Sačuvani signed URL s istekom od jedne godine koji procuri kroz database dump daje dugotrajan pristup.
- Logirajte generisanje signed URL-a, ne samo uploade fajlova. Ako kasnije posumnjate na kompromitaciju, morate znati ko je generisao koji URL i kada. Logirajte
auth.uid()+ bucket + putanja objekta + timestamp. - Koristite opciju
downloadAskada poslužujete fajlove koje su uploadovali korisnici.createSignedUrl(path, expiresIn, { download: '.jpg' })nameće headerContent-Disposition: attachmenttako da se fajl preuzima umjesto renderuje — 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.
- Auditujte buckete kvartalno. Dashboard → Storage → Buckets. Potvrdite da javni/privatni status i liste MIME tipova odgovaraju onome što aplikacija očekuje. Bucketi kreirani "privremeno" postaju trajni ako ih niko 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 neko ispituje izvana. - Postavite politiku 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 obavezama 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 — anonimne storage liste pojavljuju se pod baas.supabase-storage-public. Uparite ovu checklistu s Supabase RLS skenerom za sloj tabela 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.
