Em resumo
Um bucket público serve todos os seus ficheiros a quem tiver o URL, sem chave e sem início de sessão: as suas políticas de storage não são consultadas nas transferências. Na minha stack local o mesmo ficheiro de teste devolveu 200 com o conteúdo a partir de um bucket público e 400 a partir de um privado. Os uploads, as eliminações e as movimentações continuam a passar pelas políticas. Use buckets públicos para ficheiros que são públicos por natureza, como avatares e imagens de artigos, e buckets privados com URLs assinados para tudo o resto.
O meu verificador de segurança do Supabase gratuito tem duas regras sobre buckets: “Buckets de storage públicos” lista-os para confirmar que cada um deve mesmo ser público, e “Buckets públicos sem limites de upload” assinala os buckets públicos sem limite de tamanho nem de tipo de ficheiro. Eis o que a marca de público muda de facto.
O que significa um bucket público no Supabase?
O guia de buckets do Supabase define dois modelos de acesso. Num bucket privado, todas as operações, transferências incluídas, passam pelas políticas de RLS em storage.objects; um ficheiro lê-se com o token do utilizador ou com um URL assinado que expira. Num bucket público, a obtenção e o fornecimento de ficheiros ignoram o controlo de acesso, por isso quem tiver o URL pode ler o ficheiro. O controlo de acesso continua a aplicar-se ao upload, à eliminação, à movimentação e à cópia.
Os buckets são privados por omissão. Um bucket passa a público quando alguém marca a caixa no Dashboard ou o cria com public: true, um atalho comum quando uma imagem não carrega.
O que devolveu cada bucket no meu teste?
Numa stack local do Supabase (CLI 2.109.1) criei um bucket público e um privado, enviei o mesmo ficheiro de texto pequeno para ambos com a secret key e depois pedi-o sem qualquer chave, como faria um desconhecido com a ligação:
Pedido de 2026/invoice-001.txt |
Bucket público | Bucket privado |
|---|---|---|
/storage/v1/object/public/…, sem chave |
200, conteúdo do ficheiro |
400, “Bucket not found” |
/storage/v1/object/authenticated/…, só a publishable key |
200 |
400 |
O bucket privado responde como se não existisse, que é o que se quer. O público entrega o ficheiro a quem conseguir adivinhar ou encontrar o caminho.
Porque é que o URL importa tanto?
Um ficheiro público é tão secreto como o seu caminho. Os caminhos costumam ser previsíveis: um id de utilizador, uma data, um número de fatura. Também se perdem pelo código-fonte das páginas, por ligações partilhadas, pelo histórico do navegador e pelos logs. Uma fatura, a digitalização de um passaporte ou um contrato assinado num bucket público está, na prática, publicado.
Como escolher e corrigir?
- Bucket público: ficheiros pensados para todos, como avatares, fotografias de produto e imagens de blogue. Defina no bucket um limite de tamanho e os tipos MIME permitidos, para que a via pública de upload que as suas políticas permitem não sirva para alojar outra coisa.
- Bucket privado: documentos, exportações, faturas, tudo o que é pessoal. Transfira com a sessão do utilizador ou crie um URL assinado que expire.
Para ver os seus buckets e os respetivos limites:
select id, public, file_size_limit, allowed_mime_types
from storage.buckets
order by public desc, id;
Um bucket privado também precisa de políticas em storage.objects, que normalmente verificam se a primeira pasta do caminho é o id do utilizador ou da empresa. Depois de mover um projeto, conte essas políticas: numa app todos os uploads falharam porque a migração das políticas nunca correu, e contei isso na minha lista de segurança para apps Lovable. A que mais a publishable key consegue chegar está em Supabase anon key vs service role key.