[{"data":1,"prerenderedAt":425},["ShallowReactive",2],{"blog-uk-supabase-rls-on-but-table-still-public":3},{"id":4,"title":5,"body":6,"category":387,"cover":388,"coverAlt":388,"description":389,"draft":390,"extension":391,"faq":392,"image":405,"keywords":406,"meta":412,"navigation":413,"ogTitle":414,"path":415,"published":416,"seo":417,"stem":418,"tldr":419,"updated":423,"__hash__":424},"blog_uk\u002Fblog\u002Fsupabase-rls-on-but-table-still-public.md","Supabase Row Level Security увімкнено. Таблиця досі публічна.",{"type":7,"value":8,"toc":376},"minimark",[9,13,21,26,29,32,35,39,42,45,56,77,80,89,93,104,195,201,204,212,216,223,230,233,239,249,253,256,259,298,301,306,310,313,316,327,330,334,363],[10,11,12],"p",{},"Ви увімкнули Row Level Security, бо щось вам це підказало: advisor усередині\nSupabase, чекліст, результат сканування, хтось у Discord. Перемикач у вашій\nпанелі тепер зелений. І вам усе одно кажуть, що вашу таблицю досі можуть читати\nсторонні.",[10,14,15,16,20],{},"Ось те, що посібник за посібником переказує неправильно: ",[17,18,19],"strong",{},"перемикач не захищає\nнічого."," Він вирішує, що ваші правила почнуть перевіряти. Правила лишаються\nокремою річчю, писати їх маєте ви, а найшвидше правило з усіх (те, з яким\nзламаний застосунок знову працює) впускає всіх.",[22,23,25],"h2",{"id":24},"row-level-security-увімкнено-в-supabase-чому-таблиця-досі-публічна","Row Level Security увімкнено в Supabase. Чому таблиця досі публічна?",[10,27,28],{},"Бо увімкнути й вирішити, кого пускати, означає два різні кроки, і лише перший з\nних перемикач.",[10,30,31],{},"Уявіть перемикач як людину, яку ви поставили біля дверей. Перевести його не\nозначає вирішити, хто пройде. Це означає, що тепер хтось звіряє список. Ваші\nполітики і є той список. Порожній список не пускає нікого; список зі словом\n«усі» не спиняє нікого. І те, і те лишається Row Level Security в увімкненому стані, і\nваша панель показує однакову зелень в обох випадках.",[10,33,34],{},"Саме тому налаштування саме по собі відповідає на дуже мало, і саме тому наш\nсканер ніколи не питає Supabase, чи воно активне. Він питає таблицю. Він\nнадсилає той самий запит, що надіслав би сторонній, з публічним ключем, який\nїде всередині вашого застосунку, і дивиться, чи повернеться відповідь. Він\nпросить кількість, а не самі рядки, тож дізнається, що двері відчинилися, не\nчитаючи нічого за ними.",[22,36,38],{"id":37},"політика-яка-полагодила-застосунок-найімовірніше-і-є-проблемою","Політика, яка полагодила застосунок, найімовірніше і є проблемою",[10,40,41],{},"Тієї миті, коли ви вмикаєте Row Level Security, ваш застосунок перестає\nпоказувати дані, і те, що ви зробили далі, аби він знову запрацював, і є тим,\nна що варто подивитися.",[10,43,44],{},"Ця послідовність цілком звичайна, і саме тут усе йде не так. З увімкненим\nналаштуванням і без жодної написаної політики Postgres (рушій бази даних, на\nякому працює Supabase) за замовчуванням відхиляє кожен запит, тож ваші списки\nповертаються порожніми, а екрани лишаються\nбілими. Щось має потрапити до списку. Якщо ви попросили Cursor чи Lovable це\nполагодити або вставили перший уривок, після якого помилка зникла, те, що ви\nмаєте зараз, найпевніше має такий вигляд:",[46,47,52],"pre",{"className":48,"code":50,"language":51},[49],"language-text","CREATE POLICY \"Enable read access for all users\"\n  ON public.profiles\n  FOR SELECT\n  USING (true);\n","text",[53,54,50],"code",{"__ignoreMap":55},"",[10,57,58,61,62,65,66,69,70,73,74,76],{},[53,59,60],{},"USING (true)"," задає умову, яку рядок має задовольнити, перш ніж база даних його\nвіддасть. Умову ",[53,63,64],{},"true"," задовольняє кожен рядок. Там усередині є друга деталь,\nповз яку легко пройти: без клаузи ",[53,67,68],{},"TO"," політика діє для ",[53,71,72],{},"public",", а ",[53,75,72],{},"\nоднаково охоплює й відвідувачів, які увійшли, і цілком сторонніх людей.",[10,78,79],{},"Отже, застосунок знову працює, ніде немає помилки, а таблиця читається рівно\nтак само, як і до того, як ви почали.",[10,81,82,83,88],{},"Це лагодить читання, і тільки читання. Якщо ваш застосунок ще й зберігає в цю\nтаблицю, наступне, що ви зустрінете, це\n",[84,85,87],"a",{"href":86},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","new row violates row-level security policy",", тобто те саме налаштування,\nяке відмовляє в записі, і жодна політика читання цього не прибере.",[22,90,92],{"id":91},"чотири-стани-в-яких-може-бути-таблиця","Чотири стани, в яких може бути таблиця",[10,94,95,96,99,100,103],{},"Два з них безпечні, а два ні, і перемикач не каже вам, які саме. «Публічний\nключ» нижче означає той, якому місце у вашому застосунку: ",[53,97,98],{},"sb_publishable_…"," у нових\nпроєктах Supabase, ",[53,101,102],{},"anon"," у старіших.",[105,106,107,126],"table",{},[108,109,110],"thead",{},[111,112,113,117,120,123],"tr",{},[114,115,116],"th",{},"Row Level Security",[114,118,119],{},"Політика",[114,121,122],{},"Ваш застосунок",[114,124,125],{},"Сторонній з вашим публічним ключем Supabase",[127,128,129,148,165,179],"tbody",{},[111,130,131,135,138,141],{},[132,133,134],"td",{},"Вимкнено",[132,136,137],{},"байдуже, жодну не читають",[132,139,140],{},"Працює",[132,142,143],{},[144,145,147],"key-verdict",{"type":146},"danger","Читає кожен рядок",[111,149,150,153,156,159],{},[132,151,152],{},"Увімкнено",[132,154,155],{},"жодної не написано",[132,157,158],{},"Зламаний",[132,160,161],{},[144,162,164],{"type":163},"safe","Не читає нічого",[111,166,167,169,173,175],{},[132,168,152],{},[132,170,171],{},[53,172,60],{},[132,174,140],{},[132,176,177],{},[144,178,147],{"type":146},[111,180,181,183,188,190],{},[132,182,152],{},[132,184,185],{},[53,186,187],{},"USING (auth.uid() = user_id)",[132,189,140],{},[132,191,192],{},[144,193,194],{"type":163},"Читає лише свої",[196,197],"diagram",{"alt":198,"caption":199,"src":200},"Чотири таблиці поруч. У першої перемикач вимкнено, і всі шість рядків читаються. У другої перемикач увімкнено, поле політики порожнє, і не читається жоден рядок. У третьої перемикач увімкнено, політика каже true, і всі шість рядків знову читаються. У четвертої перемикач увімкнено, політика порівнює власника рядка, і читаються лише два рядки.","Позначка під кожним стовпцем не повторює перемикач над ним. Два з них увімкнені, і один із цих двох віддає все.","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Frls-four-states-1600x760.png",[10,202,203],{},"Два середні стовпці і є саме тією парою, на якій люди спотикаються. Те саме\nналаштування, той самий зелений значок, протилежні наслідки, а різниця вміщається\nв одне слово всередині правила, яке майже ніхто ніколи не відкриває.",[10,205,206,207,211],{},"Якщо вам не хочеться читати кожну політику самотужки, наше безкоштовне\nсканування ставить вашій живій базі те саме запитання, що й сторонній, і каже,\nякі таблиці відповіли. Це триває близько 20 секунд і не потребує акаунта:\n",[84,208,210],{"href":209},"\u002F#scan","просканувати застосунок",".",[22,213,215],{"id":214},"authenticated-не-означає-те-саме-що-ваш","«Authenticated» не означає те саме, що «ваш»",[10,217,218,219,222],{},"Політика, яка дозволяє ",[53,220,221],{},"authenticated",", дозволяє всім, хто має акаунт, а це\n(якщо у вашому застосунку відкрита реєстрація) усі, хто готовий її заповнити.",[10,224,225,226,229],{},"Це тонший варіант тієї самої помилки, і він переживає чимало переглядів, бо має\nохайний вигляд. ",[53,227,228],{},"TO authenticated USING (true)"," читається як обмеження, і воно\nним є: воно відсікає тих, хто ніколи не реєструвався. Чого воно не робить, так\nце не спиняє одного вашого клієнта від читання рядків іншого клієнта, а саме це\nви зазвичай і мали на увазі під словом «приватне».",[10,231,232],{},"Правило, яке це робить, називає власника рядка:",[46,234,237],{"className":235,"code":236,"language":51},[49],"CREATE POLICY \"Users read their own rows\"\n  ON public.orders\n  FOR SELECT\n  TO authenticated\n  USING (auth.uid() = user_id);\n",[53,238,236],{"__ignoreMap":55},[10,240,241,244,245,248],{},[53,242,243],{},"auth.uid()"," означає того, хто питає. ",[53,246,247],{},"user_id"," означає стовпець у рядку, який каже, кому\nцей рядок належить. Рядок повертається, коли ці двоє збігаються, і лишається на\nмісці, коли ні.",[22,250,252],{"id":251},"як-перевірити-власні-таблиці-за-дві-хвилини","Як перевірити власні таблиці за дві хвилини",[10,254,255],{},"Відкрийте Supabase, зайдіть в Authentication → Policies і читайте вираз\nусередині кожної політики, а не значок біля кожної таблиці.",[10,257,258],{},"Три речі, які варто шукати:",[260,261,262,271,279],"ul",{},[263,264,265,270],"li",{},[17,266,267,268,211],{},"Політику, умова якої ",[53,269,64],{}," Вирішуйте таблиця за таблицею, чи спокійно\nвам було б бачити ці дані на відкритій сторінці. Для переліку опублікованих\nстатей відповідь буде «так», для будь-чого, де є людина, – «ні».",[263,272,273,278],{},[17,274,275,276,211],{},"Політику без клаузи ",[53,277,68],{}," Вона діє для всіх, хоч ви увійшли, хоч ні,\nнавіть коли решта правила має дуже конкретний вигляд.",[263,280,281,284,285,288,289,292,293,297],{},[17,282,283],{},"Таблицю з увімкненим налаштуванням, без жодної політики, і застосунок, який\nпопри це працює."," Це поєднання означає, що до ваших даних дістається щось\nіншим шляхом, і звичним поясненням є секретний ключ: ",[53,286,287],{},"sb_secret_…",", або\n",[53,290,291],{},"service_role"," у старішому проєкті. Він ігнорує кожну написану вами політику.\n",[84,294,296],{"href":295},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","Які ключі API безпечні у фронтенді","\nрозповідає, як відрізнити його від безпечного.",[10,299,300],{},"Інша перевірка, до якої вдаються, полягає в тому, щоб відкрити застосунок у\nприватному вікні без входу. Її варто зробити, але знайте, що саме вона доводить. Ваш застосунок\nвирішує, що показати. Ваша база даних вирішує, що віддати. Це різні рішення, і\nсторонній, який оминає ваші екрани, отримує друге.",[196,302],{"alt":303,"caption":304,"src":305},"Два шляхи до тих самих рядків. Через екрани застосунку повертаються два рядки з шести. Прямо на адресу бази даних повертаються всі шість.","Екрани вашого застосунку не є парканом. Та сама таблиця може показати два рядки через ваш застосунок і віддати всі шість запиту, який його ніколи не відкривав.","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fapp-view-vs-database-1600x620.png",[22,307,309],{"id":308},"який-вигляд-це-має-поки-триває","Який вигляд це має, поки триває",[10,311,312],{},"Ніякого. Саме такої форми ця річ, і саме тому вона лишається на місці місяцями.",[10,314,315],{},"У вашому білдері не з'являється жодної помилки. Ніщо не сповільнюється, жоден\nекран не ламається, жоден лист не приходить. Ваш застосунок поводиться точно\nтак, як у день запуску, бо з його боку нічого не змінилося: він завжди мав\nправо читати ці рядки. Змінилося те, що це право мають і всі інші, з ключем,\nякий їде в коді, що ваш сайт надсилає кожному відвідувачу.",[10,317,318,319,322,323,326],{},"Коли це випливає, то випливає збоку. Клієнтка питає, звідки хтось знав те, що\nзнав лише ваш застосунок. Список адрес, який ви ніколи не публікували, десь\nвиринає. А якщо щедре правило охоплює і запис, ",[53,320,321],{},"FOR ALL"," замість ",[53,324,325],{},"FOR SELECT",",\nто будь-хто може ще й змінювати та видаляти рядки. Цей варіант люди помічають\nяк таблицю, що раптом стала порожньою.",[10,328,329],{},"Правила ще й зсуваються. Міграція, зміна схеми, чергова нічна лагодка, якій\nтреба було, щоб дані завантажились: будь-що з цього здатне послабити політику,\nнічого про це не сказавши. Тому тут вартий уваги другий погляд згодом, а не\nлише один тепер. Стежити за цим є частиною того, що робить Reeve Care, хоча\nнагадування у вашому календарі виконує те саме завдання.",[22,331,333],{"id":332},"що-зробити-цього-тижня","Що зробити цього тижня",[335,336,337],"key-takeaways",{},[260,338,339,342,345,354,360],{},[263,340,341],{},"Відкрийте Authentication → Policies у Supabase і прочитайте умову кожної політики, таблиця за таблицею. Значок на таблиці не є відповіддю.",[263,343,344],{},"Для кожної таблиці, де є люди (користувачі, профілі, замовлення, повідомлення), перевірте, що правило називає власника рядка, а не дозволяє всім.",[263,346,347,348,350,351,353],{},"Замініть кожне ",[53,349,60],{}," на цих таблицях правилом, яке порівнює ",[53,352,243],{}," зі стовпцем власника, і після цього переконайтеся, що застосунок ще завантажується.",[263,355,356,357,359],{},"Додайте клаузу ",[53,358,68],{},", яку ви мали на увазі. Політика без неї діє на сторонніх так само, як на відвідувачів, що увійшли.",[263,361,362],{},"Якщо в таблиці налаштування увімкнено, політик немає, а застосунок усе одно показує її дані, з'ясуйте, що це обходить, перш ніж чіпати щось інше.",[10,364,365,366,370,371,375],{},"Почніть з тієї таблиці, за яку вам було б найніяковіше, якби вона була\nвідкритою сторінкою, і розберіться з нею сьогодні.\n",[84,367,369],{"href":368},"\u002Fchecklist","10-хвилинний чеклист безпеки"," охоплює це разом з рештою того, що\nварто переглянути у щойно запущеному застосунку, а\n",[84,372,374],{"href":373},"\u002Fis-your-supabase-app-safe","посібник із безпеки Supabase"," проходить по тому, що\nще зазвичай лишається відкритим.",{"title":55,"searchDepth":377,"depth":377,"links":378},3,[379,381,382,383,384,385,386],{"id":24,"depth":380,"text":25},2,{"id":37,"depth":380,"text":38},{"id":91,"depth":380,"text":92},{"id":214,"depth":380,"text":215},{"id":251,"depth":380,"text":252},{"id":308,"depth":380,"text":309},{"id":332,"depth":380,"text":333},"Основи безпеки",null,"Увімкнути Supabase Row Level Security не означає захистити таблицю. Захищають політики, а та, що полагодила застосунок, часто впускає всіх.",false,"md",[393,396,399,402],{"q":394,"a":395},"Я увімкнув Row Level Security, і застосунок перестав показувати дані. Я щось зламав?","Ні, це налаштування працює так, як має. Коли Row Level Security увімкнено, а політик не написано, Postgres (рушій бази даних під Supabase) за замовчуванням відхиляє кожен запит, зокрема й запити вашого власного застосунку. Розв'язання полягає в тому, щоб додати політику, яка описує, хто які рядки має бачити. Помилка, якої варто уникнути: додати таку, що дозволяє всім, бо саме вона повертає застосунок до життя і лишає таблицю відкритою.",{"q":397,"a":398},"Чи буває USING (true) правильною політикою?","Так, для даних, які справді публічні. Таблиця опублікованих статей, каталог товарів, перелік закладів на карті: вони й створені, щоб їх читав будь-хто, і політика, яка це дозволяє, тут доречна. Вона перестає бути доречною тієї миті, коли в таблиці з'являються люди. Запитайте себе, чи спокійно вам було б викласти вміст цієї таблиці на відкриту сторінку, і нехай відповідь вирішить політику.",{"q":400,"a":401},"Чи захистить мене Row Level Security, якщо витік секретний ключ?","Ні. Секретний ключ Supabase (sb_secret_ у нових проєктах, service_role у старіших) повністю обходить Row Level Security, саме для цього він і існує. Кожну написану вами політику буде пропущено, на кожній таблиці. Якщо цей ключ у вашому фронтенді, ваші політики нічого для вас не роблять, і перевипуск ключа стає першим завданням, ще до будь-якої роботи над правилами.",{"q":403,"a":404},"Чи потрібен Row Level Security, якщо в застосунку вже є екран входу?","Так. Екран входу керує вашим застосунком, а ваш застосунок не є єдиним шляхом до вашої бази даних. Supabase дає кожному проєкту вебадресу, яка відповідає на запити напряму, а ключ до неї лежить у коді, який ваш застосунок надсилає кожному відвідувачу. Політики і є тією частиною, що діє незалежно від того, крізь які двері прийшов запит.","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",[407,408,409,410,411],"supabase rls","row level security політика","таблиця supabase публічна","rls не працює","безпека supabase",{},true,"Supabase RLS увімкнено. Ваша таблиця досі публічна.","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","2026-08-10",{"title":5,"description":389},"blog\u002Fsupabase-rls-on-but-table-still-public",[420,421,422],"У Supabase вмикач і правила працюють як дві різні речі. Увімкнено без правила не пускає нікого; увімкнено з хибним правилом не спиняє нікого.","Правило, яке повертає зламаний застосунок до життя, зазвичай дозволяє будь-який запит від будь-кого.","Читайте політику, а не перемикач. Одне-єдине слово в ній вирішує, чи прочитає вашу таблицю сторонній.","2026-08-12","2JRbQYbWEtjhyvw3T01CzQXmG21R4Zp3oHmf9duQTjs",1787826051167]