// docs / baas security / supabase storage
Llista de comprovació de seguretat de contenidors de Supabase Storage: 22 punts
Supabase Storage és un embolcall prim sobre un contenidor compatible amb S3 més el mateix model de seguretat a nivell de fila que la base de dades. Això significa que els mateixos paranys de RLS que afecten les taules afecten l'accés als fitxers — i alguns específics de l'emmagatzematge que apareixen quan les eines de codificació amb IA configuren pujades. Aquesta llista són 22 punts repartits en cinc seccions: configuració del contenidor, polítiques RLS, validació de pujades, URLs signades i higiene operativa. Cadascun és verificable en menys de 15 minuts.
Cada punt de sota és essencial. Per a la mecànica subjacent de RLS, consulta Escàner de RLS de Supabase. Per a la classe d'exposició de claus adjacent a l'emmagatzematge, consulta Clau de rol de servei de Supabase exposada a JavaScript.
Configuració del contenidor
Comença amb els valors per defecte correctes. Un contenidor mal configurat filtra fitxers tant si el teu RLS és correcte com si no.
- Posa cada contenidor com a privat per defecte. Al panell de Supabase → Storage → Buckets, desactiva l'interruptor Public bucket tret que tinguis una raó explícita (actius de màrqueting, avatars públics sense PII). Els contenidors públics se salten RLS per a operacions de lectura — qualsevol amb el nom del contenidor pot llistar i descarregar.
- Estableix un límit dur de mida de fitxer a cada contenidor. Panell → Configuració del contenidor → Límit de mida de fitxer. 50 MB és un valor per defecte sensat per a pujades d'usuari; augmenta'l deliberadament per a casos d'ús de vídeo / fitxers grans. Sense límit, una sola pujada maliciosa pot exhaurir la teva quota d'emmagatzematge o el teu ample de banda mensual.
- Restringeix els tipus MIME permesos per contenidor. Llista de tipus MIME permesos — llista d'autoritzats explícita, no llista de bloqueig.
image/jpeg,image/png,image/webpper a contenidors només d'imatges. No permetis maitext/html,application/javascriptniimage/svg+xmlen un contenidor de contingut d'usuari — s'executen al navegador quan es serveixen via URL signada. - Fes servir un contenidor per tipus de contingut, no un contenidor compartit. La configuració per contenidor (mida, tipus MIME, polítiques RLS) és la granularitat que tens. Un contenidor
user-avatars, un contenidordocument-uploadsi un contenidorpublic-assetssón més fàcils de blindar que un sol contenidor barrejat. - Verifica la configuració CORS si fas pujades des del frontend. Si els usuaris pugen directament des del navegador a una URL signada, el CORS del contenidor ha de llistar el teu origen de producció.
*és acceptable només per a contenidors públics — mai per a contenidors que continguin PII d'usuari.
Polítiques RLS sobre storage.objects
Supabase Storage emmagatzema les metadades dels fitxers a la taula storage.objects. RLS sobre aquesta taula controla qui pot llegir, pujar, actualitzar o esborrar fitxers. Sense RLS, l'indicador públic/privat del contenidor és la teva única protecció.
- Confirma que RLS està habilitat a storage.objects.
SELECT rowsecurity FROM pg_tables WHERE schemaname = 'storage' AND tablename = 'objects';ha de retornartrue. Supabase l'habilita per defecte en projectes nous; verifica que no s'hagi deshabilitat. - Escriu una política SELECT delimitada a
auth.uid()per a contenidors privats.CREATE POLICY "users_read_own_files" ON storage.objects FOR SELECT USING (auth.uid()::text = (storage.foldername(name))[1]);. La convenció és emmagatzemar els fitxers sota[user-id]/[filename]i fer servirstorage.foldername()per extreure el propietari de la ruta. - Escriu una política INSERT que apliqui la mateixa convenció de ruta.
CREATE POLICY "users_upload_own" ON storage.objects FOR INSERT WITH CHECK (auth.uid()::text = (storage.foldername(name))[1]);. Sense WITH CHECK, un usuari autenticat pot pujar a la carpeta d'un altre usuari. - Afegeix polítiques UPDATE i DELETE si la teva aplicació permet editar o esborrar fitxers. Cada comanda necessita la seva pròpia política. Saltar-se DELETE significa que els usuaris autenticats no poden eliminar els seus propis fitxers; saltar-se UPDATE significa que les sobreescriptures de fitxers fallen en silenci.
- Prova l'accés entre usuaris en dues sessions de navegador. Inicia sessió com a Usuari A, puja un fitxer, copia la ruta. Inicia sessió com a Usuari B en un altre navegador, intenta obtenir el fitxer via l'API REST. La resposta ha de ser
403o404, mai200.
-- 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]);Validació de pujades
Valida cada pujada al servidor, fins i tot quan el contenidor té restriccions de MIME i mida. Les eines de codificació amb IA generen validació només-client per defecte; això no protegeix res.
- Torna a comprovar el tipus MIME al servidor des dels bytes reals del fitxer, no des de la capçalera
Content-Type. Fes servir una biblioteca comfile-type(Node) o sniffing de bytes màgics. Un atacant pot declararContent-Type: image/jpegen un fitxer que en realitat és un payload polyglot HTML / JavaScript. - Elimina les metadades EXIF de les imatges pujades. EXIF pot contenir coordenades GPS, números de sèrie del dispositiu i marques temporals. Fes servir
sharpamb.withMetadata(false)oexif-parserper netejar-les abans d'emmagatzemar. - Rebutja SVGs que continguin etiquetes
scripto gestorsonload. SVG és XML — i moltes aplicacions generades amb IA permeten pujades SVG com a "només una imatge". Fes servirDOMPurifyal servidor o rebutja directament les pujades SVG. - Fes servir noms de fitxer deterministes i impredictibles. No conservis el nom original del fitxer. Fes servir un UUID o un hash del contingut del fitxer. Els noms originals filtren ("
passport_scan_2024_01_15.jpg") i els noms predictibles permeten l'enumeració.
URLs signades
Les URLs signades són com els clients accedeixen als contenidors privats. La caducitat, l'àmbit del contenidor i què es registra importen.
- Posa la caducitat de les URLs signades a 1 hora o menys per defecte. El
createSignedUrl(path, expiresIn)del SDK de Supabase JS pren segons. No facis servir mai valors com31536000(un any) — l'URL es converteix en un enllaç semi-públic permanent. - No emmagatzemis mai URLs signades a la teva base de dades. Genera'n de noves al servidor a cada sol·licitud. Una URL signada emmagatzemada amb una caducitat d'un any que es filtri via un bolcat de base de dades atorga accés a llarg termini.
- Registra la generació d'URLs signades, no només les pujades de fitxers. Si sospites d'una vulneració més endavant, necessites saber qui ha generat quina URL i quan. Registra
auth.uid()+ contenidor + ruta de l'objecte + marca temporal. - Fes servir l'opció
downloadAsquan serveixis fitxers pujats per usuaris.createSignedUrl(path, expiresIn, { download: '.jpg' })força una capçaleraContent-Disposition: attachmentperquè el fitxer es descarregui en lloc de renderitzar-se — neutralitza la classe d'execució HTML / SVG / HTML-en-PDF.
Higiene operativa
La configuració de l'emmagatzematge deriva amb el temps. Aquests quatre punts operatius mantenen la superfície ajustada.
- Audita els contenidors trimestralment. Panell → Storage → Buckets. Confirma que l'estat públic/privat i les llistes de tipus MIME coincideixen amb el que espera l'aplicació. Els contenidors creats "temporalment" es tornen permanents si ningú els elimina.
- Monitoritza les operacions de llistat anònimes. Els registres d'emmagatzematge (Panell → Logs → Storage) registren les sol·licituds
LIST. Un pic de sol·licituds de llistat anònimes contra un contenidor privat significa que algú l'està sondejant des de fora. - Estableix una política de retenció per a pujades efímeres. Els contenidors temporals (vista prèvia d'imatges, esborranys de pujades) s'haurien d'autoeliminar després de 24-72 hores via una funció programada. La retenció indefinida és una responsabilitat sota les obligacions de minimització de dades del RGPD / CCPA.
- Executa un escaneig de FixVibe mensualment. La comprovació
baas.supabase-storage-publicsondeja contenidors que responen aGET+LISTanònims. S'afegeixen contenidors nous; els antics canvien de visibilitat — només l'escaneig continu detecta la deriva.
Següents passos
Executa un escaneig de FixVibe contra el teu URL de producció — els llistats d'emmagatzematge anònims apareixen sota baas.supabase-storage-public. Combina aquesta llista amb Escàner de RLS de Supabase per a la capa de taules i Clau de rol de servei de Supabase exposada a JavaScript per a l'adjacència d'exposició de claus. Per a configuracions errònies d'emmagatzematge en altres proveïdors BaaS, consulta Escàner de configuracions errònies de BaaS.
