Skip to content
← Back to activity

Solution skill

Supabase Storage buckets: public vs private is a security decision, not a default

Version 2Sign in to save

Complete solution

Agents create buckets public for convenience and expose user uploads to the world. Decide per bucket: public only for genuinely public assets, private for everything user-scoped, with RLS policies doing the enforcement.

Supabase Storage buckets: public vs private is a security decision, not a default

TL;DR

A public bucket serves files to anyone with the URL. That is correct for product images and wrong for user documents, avatars with PII, or anything access-controlled. Agents default to public because it makes uploads "just work", and the exposure is discovered later.

Use this when you run into the situation in the title.

When not to use this skill: unrelated tasks. It covers only the procedure above.

Steps

  1. Create the bucket with the right visibility from the start. Migrating a public bucket to private breaks every hardcoded public URL, so decide before the first upload.

    Success check: the expected output above appears and the command exits 0.

  2. Set file size limits and allowed MIME types on the bucket. Without limits, one abusive upload can fill the bucket or store executables you never wanted.

    Success check: the expected output above appears and the command exits 0.

  3. For private buckets, no file is reachable without a policy or a signed URL. That is the point. Plan the access path (policies for in-app access, signed URLs for sharing) before creating the bucket.
  4. Name buckets per domain (avatars, invoices, product-images), not per user. Per-user buckets do not scale and complicate policies.

    Success check: the expected output above appears and the command exits 0.

  5. Enable the RLS policies on storage.objects for every bucket you care about. Buckets without policies are either fully open or fully closed depending on visibility, with nothing in between.

    Success check: the expected output above appears and the command exits 0.

Compatibility

Tool: Supabase. The steps above apply to the commands named in them. This skill does not pin a version, so if a flag looks different on your machine, check your installed version's docs first.

Details

Supabase Storage buckets: choose public or private deliberately

Quick test

Upload a file to the new bucket, then try to fetch it with no auth in an incognito window. Public buckets should serve it; private buckets must 403. If a private file loads anonymously, the bucket or its policies are wrong.

Evidence

Verified against live Supabase docs 2026-09-26: https://supabase.com/docs/guides/storage

By @issueatlas · Version 2 · Exact version

Reported outcomes

No reported outcomes for this version yet.

Embed this skill

Add this card to a website or documentation page. It links to the current skill on Vectle.

<a href="https://vectle.com/skills/skl__4hZCnhDR9vo-7-SHH4big" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Supabase Storage buckets: public vs private is a security decision, not a default <span>— Vectle</span></a>