FixVibe

// 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 е правилен или не.

  1. По подразбиране всеки bucket е частен. В Supabase Dashboard → Storage → Buckets, задайте превключвателя Public bucket на изключен, освен ако нямате явна причина (маркетингови активи, публични аватари без PII). Публичните bucket-и заобикалят RLS за операции по четене — всеки с името на bucket-а може да изброява и изтегля.
  2. Задайте твърд лимит за размер на файл на всеки bucket. Dashboard → Bucket settings → File size limit. 50 MB е разумна стойност по подразбиране за потребителски качвания; повишавайте я съзнателно за video / large-file случаи. Без лимит едно злонамерено качване може да изчерпи квотата ви за хранилище или месечната ви широчина на честотната лента.
  3. Ограничете разрешените MIME типове за всеки bucket. Списък на разрешени MIME типове — явен allowlist, а не blocklist. image/jpeg, image/png, image/webp за bucket-и само за изображения. Никога не разрешавайте text/html, application/javascript или image/svg+xml в bucket с потребителско съдържание — те се изпълняват в браузъра, когато се сервират чрез signed URL.
  4. Използвайте един bucket на тип съдържание, а не един споделен bucket. Настройките за всеки bucket (размер, MIME типове, RLS политики) са детайлността, която имате. Bucket user-avatars, bucket document-uploads и bucket public-assets са по-лесни за заключване, отколкото един смесен bucket.
  5. Проверете конфигурацията на CORS, ако имате качвания от frontend. Ако потребителите качват директно от браузъра в signed URL, CORS на bucket-а трябва да изброява вашия production origin. * е приемливо само за публични bucket-и — никога за bucket-и, съдържащи потребителски PII.

RLS политики на storage.objects

Supabase Storage съхранява метаданни за файлове в таблицата storage.objects. RLS на тази таблица контролира кой може да чете, качва, актуализира или изтрива файлове. Без RLS, флагът public/private на bucket-а е единствената ви защита.

  1. Потвърдете, че RLS е активиран на storage.objects. SELECT rowsecurity FROM pg_tables WHERE schemaname = 'storage' AND tablename = 'objects'; трябва да върне true. Supabase го активира по подразбиране за нови проекти; проверете, че не е бил деактивиран.
  2. Напишете 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(), за да извлечете собственика от пътя.
  3. Напишете INSERT политика, която налага същата конвенция за път. CREATE POLICY "users_upload_own" ON storage.objects FOR INSERT WITH CHECK (auth.uid()::text = (storage.foldername(name))[1]);. Без WITH CHECK, автентикиран потребител може да качи в папката на друг потребител.
  4. Добавете UPDATE и DELETE политики, ако приложението ви поддържа редактиране или изтриване на файлове. Всяка команда се нуждае от собствена политика. Пропускането на DELETE означава, че автентикираните потребители не могат да премахнат собствените си файлове; пропускането на UPDATE означава, че презаписванията на файлове тихомълком се проваляли.
  5. Тествайте достъп между потребители в две браузърни сесии. Влезте като Потребител A, качете файл, копирайте пътя. Влезте като Потребител B в друг браузър, опитайте се да изтеглите файла чрез REST API. Отговорът трябва да бъде 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]);

Валидиране на качване

Валидирайте всяко качване от страна на сървъра, дори когато bucket-ът има ограничения за MIME и размер. AI инструментите за кодиране генерират валидиране само на клиента по подразбиране; това не защитава нищо.

  1. Проверете отново MIME типа на сървъра от действителните байтове на файла, а не от заглавката Content-Type. Използвайте библиотека като file-type (Node) или magic-byte sniffing. Нападател може да твърди Content-Type: image/jpeg на файл, който всъщност е полиглот HTML / JavaScript payload.
  2. Изтрийте EXIF метаданните от качените изображения. EXIF може да съдържа GPS координати, серийни номера на устройства и timestamps. Използвайте sharp с .withMetadata(false) или exif-parser, за да изтриете преди съхранение.
  3. Отхвърляйте SVG, които съдържат тагове script или onload handlers. SVG е XML — и много AI-генерирани приложения позволяват SVG качвания като "просто изображение". Използвайте DOMPurify на сървъра или откажете SVG качванията напълно.
  4. Използвайте детерминистични, неотгадаеми имена на файлове. Не запазвайте оригиналното име на файла. Използвайте UUID или хеш на съдържанието на файла. Оригиналните имена изтичат ("passport_scan_2024_01_15.jpg") и предсказуемите имена позволяват изброяване.

Signed URL

Signed URL са начинът, по който клиентите получават достъп до частни bucket-и. Срокът на валидност, обхватът на bucket-а и това, което се логва, имат значение.

  1. Срокът на signed URL по подразбиране е 1 час или по-малко. createSignedUrl(path, expiresIn) на Supabase JS SDK приема секунди. Никога не използвайте стойности като 31536000 (една година) — URL става постоянна полупублична връзка.
  2. Никога не съхранявайте signed URL в базата си данни. Генерирайте свежи на сървъра при всяка заявка. Съхранен signed URL с едногодишен срок, който изтича чрез database dump, дава дългосрочен достъп.
  3. Логвайте генерирането на signed URL, а не само качването на файлове. Ако подозирате компрометиране по-късно, трябва да знаете кой е генерирал коя URL кога. Логвайте auth.uid() + bucket + път на обекта + timestamp.
  4. Използвайте опцията downloadAs, когато сервирате файлове, качени от потребители. createSignedUrl(path, expiresIn, { download: '.jpg' }) налага заглавка Content-Disposition: attachment, така че файлът се изтегля вместо да се рендира — побеждава класа на изпълнение на HTML / SVG / HTML-в-PDF.

Оперативна хигиена

Конфигурацията на хранилището се отклонява с времето. Тези четири оперативни точки поддържат повърхността стегната.

  1. Одитирайте bucket-ите тримесечно. Dashboard → Storage → Buckets. Потвърдете състоянието public/private и списъците с MIME типове съответстват на това, което приложението очаква. Bucket-и, създадени "временно", стават постоянни, ако никой не ги премахне.
  2. Мониторирайте анонимните операции за изброяване. Storage логовете (Dashboard → Logs → Storage) записват LIST заявки. Скок на анонимни list заявки срещу частен bucket означава, че някой го сондира отвън.
  3. Задайте политика за съхранение на ефимерни качвания. Временни bucket-и (преглед на изображение, чернови на качвания) трябва да се изтриват автоматично след 24-72 часа чрез scheduled function. Безсрочното задържане е отговорност съгласно задълженията за минимизиране на данните по GDPR / CCPA.
  4. Изпълнявайте FixVibe сканиране месечно. Проверката baas.supabase-storage-public сондира за bucket-и, които отговарят на анонимни GET + LIST. Добавят се нови bucket-и; стари променят видимостта си — само непрекъснатото сканиране улавя дрейфа.

Следващи стъпки

Изпълнете FixVibe сканиране срещу production URL — анонимните списъци на хранилището се появяват под baas.supabase-storage-public. Сдвоете този контролен списък с Сканер за Supabase RLS за слоя на таблиците и Сервизният ключ на Supabase, разкрит в JavaScript за съседството на разкриването на ключове. За неправилни конфигурации на хранилището при други BaaS доставчици вижте Скенер за неправилни конфигурации на BaaS.

// сканирайте вашата baas повърхност

Намерете отворената таблица, преди някой друг да го направи.

Въведете production URL. FixVibe изброява доставчиците на BaaS, с които комуникира приложението ви, снема отпечатъци от публичните им крайни точки и докладва какво може да прочете или запише неавтентикиран клиент. Безплатно, без инсталация, без карта.

  • Безплатен план — 3 сканирания / месец, без карта при регистрация.
  • Пасивен отпечатък на BaaS — не се изисква проверка на домейн.
  • Supabase, Firebase, Clerk, Auth0, Appwrite и още.
  • AI промптове за поправка на всяко откритие — поставете обратно в Cursor / Claude Code.
Стартирайте безплатно BaaS сканиране

не се изисква регистрация

Контролен списък за сигурност на storage bucket на Supabase: 22 точки — Docs · FixVibe