// docs / baas security / supabase storage
Контролен списък за сигурност на storage bucket на Supabase: 22 точки
Supabase Storage е тънка обвивка около S3-съвместим bucket плюс същия модел Row-Level Security като базата данни. Това означава, че същите RLS капани, които засягат таблиците, засягат и достъпа до файлове — и няколко специфични за storage, които се появяват, когато AI инструментите за кодиране свързват качвания. Този контролен списък е 22 точки в пет секции: конфигурация на bucket, RLS политики, валидиране на качване, signed URL и оперативна хигиена. Всяка е проверима за по-малко от 15 минути.
Всяка точка по-долу е съществена. За основните RLS механики вижте Сканер за Supabase RLS. За класа разкриване на ключове, съседен на хранилището, вижте Сервизният ключ на Supabase, разкрит в JavaScript.
Конфигурация на bucket
Започнете с правилните настройки по подразбиране. Неправилно конфигуриран bucket изтича файлове, независимо дали вашият RLS е правилен или не.
- По подразбиране всеки bucket е частен. В Supabase Dashboard → Storage → Buckets, задайте превключвателя Public bucket на изключен, освен ако нямате явна причина (маркетингови активи, публични аватари без PII). Публичните bucket-и заобикалят RLS за операции по четене — всеки с името на bucket-а може да изброява и изтегля.
- Задайте твърд лимит за размер на файл на всеки bucket. Dashboard → Bucket settings → File size limit. 50 MB е разумна стойност по подразбиране за потребителски качвания; повишавайте я съзнателно за video / large-file случаи. Без лимит едно злонамерено качване може да изчерпи квотата ви за хранилище или месечната ви широчина на честотната лента.
- Ограничете разрешените MIME типове за всеки bucket. Списък на разрешени MIME типове — явен allowlist, а не blocklist.
image/jpeg,image/png,image/webpза bucket-и само за изображения. Никога не разрешавайтеtext/html,application/javascriptилиimage/svg+xmlв bucket с потребителско съдържание — те се изпълняват в браузъра, когато се сервират чрез signed URL. - Използвайте един bucket на тип съдържание, а не един споделен bucket. Настройките за всеки bucket (размер, MIME типове, RLS политики) са детайлността, която имате. Bucket
user-avatars, bucketdocument-uploadsи bucketpublic-assetsса по-лесни за заключване, отколкото един смесен bucket. - Проверете конфигурацията на CORS, ако имате качвания от frontend. Ако потребителите качват директно от браузъра в signed URL, CORS на bucket-а трябва да изброява вашия production origin.
*е приемливо само за публични bucket-и — никога за bucket-и, съдържащи потребителски PII.
RLS политики на storage.objects
Supabase Storage съхранява метаданни за файлове в таблицата storage.objects. RLS на тази таблица контролира кой може да чете, качва, актуализира или изтрива файлове. Без RLS, флагът public/private на bucket-а е единствената ви защита.
- Потвърдете, че RLS е активиран на storage.objects.
SELECT rowsecurity FROM pg_tables WHERE schemaname = 'storage' AND tablename = 'objects';трябва да върнеtrue. Supabase го активира по подразбиране за нови проекти; проверете, че не е бил деактивиран. - Напишете SELECT политика, ограничена до
auth.uid()за частни bucket-и.CREATE POLICY "users_read_own_files" ON storage.objects FOR SELECT USING (auth.uid()::text = (storage.foldername(name))[1]);. Конвенцията е да съхранявате файлове под[user-id]/[filename]и да използватеstorage.foldername(), за да извлечете собственика от пътя. - Напишете INSERT политика, която налага същата конвенция за път.
CREATE POLICY "users_upload_own" ON storage.objects FOR INSERT WITH CHECK (auth.uid()::text = (storage.foldername(name))[1]);. Без WITH CHECK, автентикиран потребител може да качи в папката на друг потребител. - Добавете UPDATE и DELETE политики, ако приложението ви поддържа редактиране или изтриване на файлове. Всяка команда се нуждае от собствена политика. Пропускането на DELETE означава, че автентикираните потребители не могат да премахнат собствените си файлове; пропускането на UPDATE означава, че презаписванията на файлове тихомълком се проваляли.
- Тествайте достъп между потребители в две браузърни сесии. Влезте като Потребител A, качете файл, копирайте пътя. Влезте като Потребител B в друг браузър, опитайте се да изтеглите файла чрез REST API. Отговорът трябва да бъде
403или404, никога200.
-- 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]);Валидиране на качване
Валидирайте всяко качване от страна на сървъра, дори когато bucket-ът има ограничения за MIME и размер. AI инструментите за кодиране генерират валидиране само на клиента по подразбиране; това не защитава нищо.
- Проверете отново MIME типа на сървъра от действителните байтове на файла, а не от заглавката
Content-Type. Използвайте библиотека катоfile-type(Node) или magic-byte sniffing. Нападател може да твърдиContent-Type: image/jpegна файл, който всъщност е полиглот HTML / JavaScript payload. - Изтрийте EXIF метаданните от качените изображения. EXIF може да съдържа GPS координати, серийни номера на устройства и timestamps. Използвайте
sharpс.withMetadata(false)илиexif-parser, за да изтриете преди съхранение. - Отхвърляйте SVG, които съдържат тагове
scriptилиonloadhandlers. SVG е XML — и много AI-генерирани приложения позволяват SVG качвания като "просто изображение". ИзползвайтеDOMPurifyна сървъра или откажете SVG качванията напълно. - Използвайте детерминистични, неотгадаеми имена на файлове. Не запазвайте оригиналното име на файла. Използвайте UUID или хеш на съдържанието на файла. Оригиналните имена изтичат ("
passport_scan_2024_01_15.jpg") и предсказуемите имена позволяват изброяване.
Signed URL
Signed URL са начинът, по който клиентите получават достъп до частни bucket-и. Срокът на валидност, обхватът на bucket-а и това, което се логва, имат значение.
- Срокът на signed URL по подразбиране е 1 час или по-малко.
createSignedUrl(path, expiresIn)на Supabase JS SDK приема секунди. Никога не използвайте стойности като31536000(една година) — URL става постоянна полупублична връзка. - Никога не съхранявайте signed URL в базата си данни. Генерирайте свежи на сървъра при всяка заявка. Съхранен signed URL с едногодишен срок, който изтича чрез database dump, дава дългосрочен достъп.
- Логвайте генерирането на signed URL, а не само качването на файлове. Ако подозирате компрометиране по-късно, трябва да знаете кой е генерирал коя URL кога. Логвайте
auth.uid()+ bucket + път на обекта + timestamp. - Използвайте опцията
downloadAs, когато сервирате файлове, качени от потребители.createSignedUrl(path, expiresIn, { download: '.jpg' })налага заглавкаContent-Disposition: attachment, така че файлът се изтегля вместо да се рендира — побеждава класа на изпълнение на HTML / SVG / HTML-в-PDF.
Оперативна хигиена
Конфигурацията на хранилището се отклонява с времето. Тези четири оперативни точки поддържат повърхността стегната.
- Одитирайте bucket-ите тримесечно. Dashboard → Storage → Buckets. Потвърдете състоянието public/private и списъците с MIME типове съответстват на това, което приложението очаква. Bucket-и, създадени "временно", стават постоянни, ако никой не ги премахне.
- Мониторирайте анонимните операции за изброяване. Storage логовете (Dashboard → Logs → Storage) записват
LISTзаявки. Скок на анонимни list заявки срещу частен bucket означава, че някой го сондира отвън. - Задайте политика за съхранение на ефимерни качвания. Временни bucket-и (преглед на изображение, чернови на качвания) трябва да се изтриват автоматично след 24-72 часа чрез scheduled function. Безсрочното задържане е отговорност съгласно задълженията за минимизиране на данните по GDPR / CCPA.
- Изпълнявайте FixVibe сканиране месечно. Проверката
baas.supabase-storage-publicсондира за bucket-и, които отговарят на анонимниGET+LIST. Добавят се нови bucket-и; стари променят видимостта си — само непрекъснатото сканиране улавя дрейфа.
Следващи стъпки
Изпълнете FixVibe сканиране срещу production URL — анонимните списъци на хранилището се появяват под baas.supabase-storage-public. Сдвоете този контролен списък с Сканер за Supabase RLS за слоя на таблиците и Сервизният ключ на Supabase, разкрит в JavaScript за съседството на разкриването на ключове. За неправилни конфигурации на хранилището при други BaaS доставчици вижте Скенер за неправилни конфигурации на BaaS.
