Чи безпечний ваш застосунок на Supabase?
Чи можна тримати в Supabase справжні дані користувачів? Так, і його зроблено для запитів просто з браузера. Саме тому все вирішують два налаштування.

Логотипи належать їхнім власникам і показані, щоб позначити сумісність.
Коротко
- У Supabase можна тримати справжні дані користувачів, і його зроблено так, щоб запитувати їх просто з браузера. Саме тому всю роботу виконують правила на ваших таблицях.
- Публічний ключ має бути у вашому застосунку. sb_secret_… і service_role обходять кожне написане вами правило.
- Таблиці, зроблені в Table Editor, отримують Row Level Security автоматично. Створені виконанням SQL не отримують.
Supabase дає вам справжню базу даних Postgres із уже готовим API перед нею, і саме тому застосунок може говорити з живими даними через двадцять хвилин після початку. Згодом людей дивує те, що той самий API доступний будь-кому, звідки завгодно, з обліковими даними, надрукованими всередині вашого застосунку.
Ось що гайд за гайдом подає неправильно: це не вада, і ховати це не розв'язання. Supabase спроєктовано так, щоб його запитували просто з браузера. Захист від початку мав жити в іншому місці, і знати, у якому саме, – це майже все знання, потрібне, щоб спокійно тримати застосунок на Supabase.
Чому ваша база даних в інтернеті навмисно
Бо ваш застосунок говорить із нею з браузера вашого відвідувача, а не з сервера, який тримаєте ви.
Уявіть крамницю. Ваш застосунок є вітриною, яку цілком вручають кожному відвідувачу. Ваша база даних є складом, і в Supabase у складу навмисно є власні двері на вулицю, щоб ваша вітрина могла брати звідти без служби доставки посередині. Саме ці двері рятують вас від написання бекенду.
А отже, двері публічні, і їхня адреса лежить у вашому застосунку, бо саме ваш застосунок має в них постукати. Немає такого влаштування, за якого ця адреса лишалася б таємною. Тож питання ніколи не було «чи можуть сторонні дістатися моєї бази даних»: можуть, і так задумано. Питання в тому, що вона їм видасть, коли вони попросять.
Чи має ключ Supabase бути в моєму застосунку?
Один із них має. Другий не має ніколи, і виглядають вони майже однаково.
Публічний ключ (sb_publishable_… у нових проєктах, anon у старіших)
каже, до якого проєкту належить запит. Він не має власних привілеїв, і саме тому
власна документація Supabase описує його як безпечний для вбудовування у
вебсторінки та мобільні застосунки. Знайти його у вашому застосунку не знахідка.
Секретний ключ, sb_secret_… або старіший service_role, робить протилежне.
Він повністю обходить ваші правила й читає та змінює кожен рядок у кожній
таблиці, звідки завгодно. Його місце на сервері, в edge-функції, у воркері: ніде, куди
дістає браузер.
Вони лежать поруч на одній сторінці панелі й мають однакову форму. Якщо один із них колись потрапляв у код фронтенду, замініть його в панелі, перш ніж щось редагувати, бо видалення рядка двері не зачиняє.
Шукайте її в Settings, далі API Keys, і там чотири значення, а не два.
Налаштування, яке вирішує, що саме двері видають
Row Level Security: перемикач для кожної таблиці, який рядок за рядком вирішує, кому що читати. Саме в ньому вся причина, чому публічний ключ безпечний.
Коли вона вимкнена, цей ключ повертає всю таблицю кожному, хто попросить. Коли ввімкнена і політику написано, база даних сама фільтрує кожен запит, включно з тими, що ніколи не проходили через ваш застосунок.
Дві дрібниці вирішують, чи справді вона у вас є, і жодної з них не видно з вашого застосунку:
Як таблиця була створена. Supabase вмикає Row Level Security автоматично для таблиць, зроблених у Table Editor панелі. Таблиці, створені виконанням SQL, її не отримують, і вмикати доводиться свідомо. Файли міграцій, скрипти та згенеровані ШІ схеми створюють таблиці через SQL, тож у зібраному так проєкті може бути цілий ряд незахищених таблиць, які виглядають точнісінько як захищені.
Що каже політика. «Увімкнено» означає «закрито, доки політика не відчинить». Політика, яка дозволяє всім, відчиняє навстіж, тоді як панель і далі повідомляє, що в таблиці ввімкнена Row Level Security. Такий стан виглядає захищеним і не є ним.
Сховище знову окремо. Публічне сховище може переглянути й завантажити будь-хто з адресою вашого проєкту, хоч би що казали правила ваших таблиць.
Як перевірити власний проєкт на Supabase приблизно за десять хвилин
Authentication → Policies. Прочитайте весь список. Будь-яку таблицю, у якої Row Level Security показано як вимкнену, може прочитати будь-хто. Для тих, де її показано ввімкненою, відкрийте політику й прочитайте, що вона насправді дозволяє.
Settings → API. Підтвердьте, що ключ, який відвантажує ваш застосунок,
публічний. Якщо секретний ключ колись бував у коді фронтенду, спершу замініть
його тут.
Якщо у вашій панелі ключі починаються з sb_publishable_ і sb_secret_, а не з
anon і service_role, це новіший формат, і те
саме правило вирішує, який із двох належить вашому застосунку.
Storage → Buckets. Перевірте, які з них публічні й чи саме цього ви хотіли для файлів усередині.
А потім подивіться ззовні. Усе вище показує те, що ваша панель називає налаштованим. Що анонімний запит отримує назад насправді, лишається іншим питанням, і саме на нього відповідає наше безкоштовне сканування: воно запитує так, як запитав би сторонній, не читаючи жодного вашого рядка, і дає оцінку приблизно за 20 секунд: перевірити, що показує ваш застосунок.
Що робити
- Ваш API у Supabase публічний навмисно. Захист дають правила на ваших таблицях, а ніколи не таємність адреси.
- Публічний ключ має бути у вашому застосунку.
sb_secret_…іservice_roleне мають бути там ніколи, а той, що витік, ігнорує кожне написане вами правило. - Таблиці, зроблені в Table Editor, отримують Row Level Security автоматично. Створені виконанням SQL не отримують.
- «Увімкнено» не «обмежено». Читайте політику, а не лише перемикач.
- У сховищ власні налаштування, тож замкнені таблиці нічого не кажуть про ваші файли.
Відкрийте Authentication → Policies і пройдіть список один раз. З таблиць, позначених як вимкнені, варто почати; а якщо вам зручніше пройти всю поверхню списком, коротку версію дає 10-хвилинний чекліст безпеки. Що б ви не знайшли, знати, що ви зможете повернути дані на місце, важить не менше за те, щоб їх замкнути, а це цілком залежить від того, що ви копіюєте.
Якщо ви не хочете, щоб це залежало від вашої памʼяті, ось як працюють автоматичні резервні копії Supabase.
Що насправді може піти не так із Supabase
Жоден із цих пунктів не означає, що ви зробили щось не так: це звичайні прогалини, коли рухаєшся швидко. Ось що варто перевірити:
Вимкнений Row Level Security (RLS)
RLS є правилом Supabase про те, хто може читати чи змінювати кожен рядок таблиці. З публічним «anon» ключем (який і має бути у вашому застосунку) будь-хто може напряму робити запити до вашої бази даних. Саме RLS не дає їм бачити рядки, які не їхні. Якщо його вимкнено, таблиця може бути повністю доступна для читання, або й редагування, будь-ким. Це найважливіший параметр Supabase, і Reeve перевіряє його, рахуючи рядки, а не читаючи їх.
Витік service_role ключа
Supabase дає вам два ключі. «anon» ключ публічний за задумом і безпечний у браузері. «service_role» ключ обходить усі ваші правила безпеки й має жити лише на сервері. Якщо він колись опиниться у фронтенд-коді вашого застосунку, будь-хто зможе робити з вашими даними будь-що. Reeve декодує знайдені ключі й точно каже, який із них відкритий: безпечний «anon» отримує зелену позначку, а «service_role» отримує червону тривогу.
Публічні бакети сховища
Файли, які завантажують люди, живуть у «бакетах» Supabase Storage. Бакет, налаштований як публічний, означає, що будь-хто може переглянути список і завантажити те, що всередині, тож приватні завантаження можуть стати видимими всім. Reeve перевіряє, чи можна переглянути список ваших бакетів; він ніколи не завантажує чужих файлів.
Ваш API відкритий будь-якому сайту (CORS)
Supabase дає вашій базі даних вебадресу (через PostgREST). У поєднанні із занадто дозвільним налаштуванням обміну інший сайт міг би звертатися до ваших даних із браузера відвідувача. Reeve перевіряє, чи відповідають ваші ендпоінти стороннім та іншим сайтам, жодного разу не використовуючи їх, щоб щось змінити.
Таблиці й ендпоінти, відкриті без правил
Кожна створена вами таблиця досяжна через API Supabase: це за задумом, і RLS має її охороняти. Але нова таблиця, додана поспіхом, до того як задано її правила, може бути ненадовго (чи надовго) відкритою. Reeve перевіряє, що насправді досяжне ззовні.
Ключі чи конфігурація, лишені в задеплоєному застосунку
Окрім власних ключів Supabase, застосунки часто несуть інші налаштування й секрети у своєму фронтенд-коді або у відкритому .env. Reeve читає завантажений код застосунку й перевіряє досяжні файли конфігурації, а потім каже, які значення безпечно робити публічними, а які ні.
Що таке Reeve і чим він не є
Reeve є безкоштовною перевіркою ззовні в режимі читання, наче інспектор, який перевіряє двері, не заходячи всередину. Це швидко, і це ловить поширені помилки з великими наслідками. Це не повний аудит безпеки, і чиста оцінка не є гарантією: вона означає, що очевидні двері зачинені. Усе, що робить Reeve, лишається пасивним: він рахує рядки, а не читає їх, і ніколи не завантажує ваших файлів.
Supabase дає вам справжні інструменти безпеки (Security Advisor і лінтер бази даних, що позначають проблеми з RLS і відкритістю прямо в панелі керування), і ними справді варто користуватися. Що додає Reeve: більшість тих, хто будує на Supabase, живуть у своєму конструкторі застосунків, а не в SQL-редакторі, і радник говорить мовою розробників. Reeve перевіряє весь ваш застосунок ззовні, так, як зловмисник дістався б до ваших даних, і пояснює знайдене простими словами. А якщо ви не хочете стежити за цим самі, це можемо зробити ми.
Хочете, щоб цим займалися, а не лише перевірили?
Reeve Care продовжує стежити за вашим застосунком, робить резервні копії даних і допомагає полагодити, коли щось ламається, щоб ви могли будувати далі, а не хвилюватися.
Дізнатися про Reeve CareПоширені запитання
Що таке Supabase RLS і чи справді він мені потрібен?
RLS (Row Level Security) вирішує, хто може бачити чи змінювати кожен рядок ваших таблиць. Оскільки ваш застосунок несе публічний «anon» ключ, яким можна напряму робити запити до бази даних, саме RLS не дає даним одного користувача стати видимими всім. Так: для будь-якої таблиці зі справжніми даними його треба ввімкнути. Reeve перевіряє, чи ввімкнено, не читаючи ваших даних.
Чи безпечно розкривати anon ключ Supabase?
Так. «anon» ключ створено, щоб жити у вашому фронтенді, і сам по собі він робить лише те, що дозволяють ваші правила RLS. Ключ, який ніколи не можна розкривати, – це «service_role», який ігнорує всі правила. Reeve декодує ключі у вашому застосунку й каже, який із них який.
Що станеться, якщо витече мій service_role ключ?
service_role ключ обходить кожне правило безпеки, тож будь-хто, хто його має, може читати, змінювати чи видаляти всі ваші дані. Якщо він у вашому фронтенд-коді, вважайте його скомпрометованим: замініть його в панелі керування Supabase й перенесіть на сервер. Reeve позначає відкритий service_role ключ як критичну проблему.
Чи може Reeve перевірити мій Supabase без пароля до бази даних?
Так. Reeve використовує лише те, що ваш застосунок уже публічно розкриває: той самий anon ключ і ендпоінти, якими користується браузер будь-якого відвідувача. Йому ніколи не потрібен пароль до вашої бази даних, він ніколи не входить як адміністратор і ніколи не читає й не завантажує ваших рядків чи файлів.
Чому Supabase узагалі дозволяє браузеру говорити з моєю базою даних?
Бо це і є продукт. Supabase ставить API перед Postgres, щоб ваш застосунок міг запитувати дані, а вам не довелося писати й хостити бекенд, і саме це й робить розробку такою швидкою. Безпека береться не з приховування цього API: сховати його неможливо. Вона береться з того, що Postgres відмовляється повертати рядки, на які відвідувач не має права.
Чи робить таблицю приватною те, що я вмикаю Row Level Security?
Це робить її закритою, доки ви не напишете політику, і це безпечна відправна точка. Але політика, що дозволяє всім, відкриває таблицю знову, тоді як панель і далі показує Row Level Security як увімкнену. «Увімкнено» й «обмежено» є двома різними станами, і лише один із них видно з першого погляду.
Які таблиці найімовірніше лишилися незахищеними?
Ті, що створені виконанням SQL, а не клацанням у Table Editor: файли міграцій, скрипти й схеми, написані для вас білдером зі ШІ. Table Editor вмикає Row Level Security автоматично. SQL не вмикає, і потім ніщо на цю різницю не вказує.
Чи покриває Row Level Security моє сховище у Supabase?
У сховища власні окремі налаштування, тож щільно замкнена база даних не каже нічого про ваші файли. Сховище, позначене як публічне, може переглянути й завантажити будь-хто, хто знає адресу вашого проєкту, незалежно від того, чи посилається ваш застосунок на його вміст.