Search code examples
pythonpostgresqlsupabase

Supabase python client returns an empty list when making a query


My configuration is very basic. A simple supabase database with one table.

I use supabase-py to interact with it. The problem is that I always get an empty list :

from supabase import create_client

URL = "MY_URL_HERE"
API_KEY = "MY_API_KEY_HERE"

supabase = create_client(URL, API_KEY)

response = supabase.table("prod_vxf").select("*").execute()

print(respnse.data)
# []

After checking some similar topics like this one, it seems that the only solution is by turning off RLS. So I went to the dashboard and turned off the RLS for the table prod_vxf and it worked. Now, the code above gives a non empty list :

print(response.data)
[
    {"id": 1, "created_at": "2024-01-01T00:00:00+00:00"},
    {"id": 2, "created_at": "2024-01-02T00:00:00+00:00"},
    {"id": 3, "created_at": "2024-01-03T00:00:00+00:00"},
]

But what is very confusing is the warning below that hits my screen when I try to turn off the RLS for a given table in supabase dashboard. Does it mean that anyone on the internet (even without knowing url + api key) can access (read and write) my database and its tables ? Honestly, I'm super confused by the term publicly used by the warning.

enter image description here


Solution

  • Does it mean that anyone on the internet (even without knowing url + api key) can access (read and write) my database and its tables ?

    It's publicly as in the database role PUBLIC:

    The special “role” name PUBLIC can be used to grant a privilege to every role on the system.

    That is every role inside that db, not the general, public internet public. It's not like that change suddenly peels away all security from your entire database cluster. The answer to your question is a hard no.

    Everyone still needs to know the connection string to get in or the URL plus an API key to perform operations indirectly.
    Anyone that does get in either way, still needs to do so as a user that has the privileges to access the table. Only then can they CRUD records in that table freely, but since RLS is a per-table setting, it only applies to that one single table. You can check others to confirm they are still protected.
    The Auth policies they also mention won't work because they rely on RLS.

    If it's just you and your friends working on the app, this doesn't matter much. If you plan to make the app available to a broader audience, make sure you read up on this and other security features and keep them in mind. Later on it might be pretty difficult and laborious to redesign everything if it's built as a ring-0-only, everyone-is-superuser creative mode playground.