Storage

Storage Access Control

Supabase Storage is designed to work perfectly with Postgres Row Level Security (RLS).

You can use RLS to create Security Access Policies that are incredibly powerful and flexible, allowing you to restrict access based on your business needs.

Access policies

By default Storage does not allow any uploads to buckets without RLS policies. You selectively allow certain operations by creating RLS policies on the storage.objects table.

You can find the documentation for the storage schema here , and to simplify the process of crafting your policies, you can utilize these helper functions .

For example, the only RLS policy required for uploading objects is to grant the INSERT permission to the storage.objects table.

To allow overwriting files using the upsert functionality you will need to additionally grant SELECT and UPDATE permissions.

Policy examples

An easy way to get started would be to create RLS policies for SELECT, INSERT, UPDATE, DELETE operations and restrict the policies to meet your security requirements. For example, one can start with the following INSERT policy:


_10
create policy "policy_name"
_10
ON storage.objects
_10
for insert with check (
_10
true
_10
);

and modify it to only allow authenticated users to upload assets to a specific bucket by changing it to:


_10
create policy "policy_name"
_10
on storage.objects for insert to authenticated with check (
_10
-- restrict bucket
_10
bucket_id = 'my_bucket_id'
_10
);

This example demonstrates how you would allow authenticated users to upload files to a folder called private inside my_bucket_id:


_10
create policy "Allow authenticated uploads"
_10
on storage.objects
_10
for insert
_10
to authenticated
_10
with check (
_10
bucket_id = 'my_bucket_id' and
_10
(storage.foldername(name))[1] = 'private'
_10
);

This example demonstrates how you would allow authenticated users to upload files to a folder called with their users.id inside my_bucket_id:


_10
create policy "Allow authenticated uploads"
_10
on storage.objects
_10
for insert
_10
to authenticated
_10
with check (
_10
bucket_id = 'my_bucket_id' and
_10
(storage.foldername(name))[1] = (select auth.uid()::text)
_10
);

Allow a user to access a file that was previously uploaded by the same user:


_10
create policy "Individual user Access"
_10
on storage.objects for select
_10
to authenticated
_10
using ( (select auth.uid()) = owner_id );


Bypassing access controls

If you exclusively use Storage from trusted clients, such as your own servers, and need to bypass the RLS policies, you can use the service key in the Authorization header. Service keys entirely bypass RLS policies, granting you unrestricted access to all Storage APIs.

Remember you should not share the service key publicly.