[{"data":1,"prerenderedAt":810},["ShallowReactive",2],{"blog-uk-supabase-security-checker":3,"blog-index-uk":570},{"id":4,"title":5,"body":6,"category":522,"cover":523,"coverAlt":524,"description":525,"draft":526,"extension":527,"faq":528,"image":544,"keywords":545,"meta":558,"navigation":559,"ogTitle":560,"path":561,"published":562,"seo":563,"stem":564,"tldr":565,"updated":562,"__hash__":569},"blog_uk\u002Fblog\u002Fsupabase-security-checker.md","Supabase security checker: п’ять перевірок, які зробите самі",{"type":7,"value":8,"toc":510},"minimark",[9,13,21,24,29,32,35,38,47,51,54,66,89,112,115,118,124,128,131,141,148,159,162,226,231,237,260,268,272,275,281,287,290,301,322,330,334,337,344,350,357,363,373,377,380,386,389,396,400,403,409,429,435,444,447,451,482,487,495,502],[10,11,12],"p",{},"Ви шукали Supabase security checker і отримали дев’ять штук. Один хоче ваш\nрепозиторій. Другий хоче розширення для браузера. Третій хоче доступ на читання\nдо всього вашого облікового запису Supabase, що досить близько до тієї самої\nречі, яка вас непокоїла, аби ви завагалися.",[10,14,15,16,20],{},"Ось те, чого жодна з тих сторінок не каже вголос. ",[17,18,19],"strong",{},"Перевірок п’ять, і кожну ви\nможете зробити самі",", без облікового запису, без встановлення і без жодних\nданих доступу, які було б небезпечно віддавати. Десять хвилин у терміналі\nпокривають те саме, що й ті інструменти.",[10,22,23],{},"П’ять нижче це ті, які наш власний сканер виконує проти проєкту Supabase,\nвиписані як команди. Якщо ви будували з Lovable, Bolt, v0, Cursor, Replit,\nWindsurf чи Base44 і ваш застосунок узагалі щось зберігає, база за ним дуже\nймовірно Supabase, і ось питання, які поставив би їй незнайомець.",[25,26,28],"h2",{"id":27},"що-насправді-перевіряє-supabase-security-checker","Що насправді перевіряє Supabase security checker?",[10,30,31],{},"Ваш опублікований застосунок. Налаштування всередині проєкту це робота іншого\nінструмента, і Supabase той інструмент уже дає.",[10,33,34],{},"Security Advisor у вашій панелі читає власний каталог проєкту: у яких таблиць\nвимкнена Row Level Security, у яких функцій нестрогий search path, які\nрозширення лежать у схемі public. Він читає те, що ви налаштували.",[10,36,37],{},"Чекер читає те, що ваш застосунок віддає незнайомцю. Бандл JavaScript, який\nзавантажують відвідувачі, відповідь таблиці на запит без входу, вміст бакета\nсховища, заголовки ваших сторінок. Вашої конфігурації він не бачить зовсім, і\nйому це не потрібно, бо він дивиться на її наслідок.",[10,39,40,41,46],{},"Дві половини розходяться частіше, ніж припускають назви. Таблиця може пройти\nAdvisor із увімкненим перемикачем і написаною політикою й усе одно віддавати\nсвої рядки будь-кому, бо написана політика впускає всіх. Це варте окремого\nчитання, якщо ви з цим не стикалися:\n",[42,43,45],"a",{"href":44},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","перемикач це не захист",".",[25,48,50],{"id":49},"перевірка-1-який-ключ-supabase-віддає-ваш-застосунок","Перевірка 1: який ключ Supabase віддає ваш застосунок?",[10,52,53],{},"Відкрийте застосунок у браузері, натисніть F12 і подивіться на один запит.",[10,55,56,57,61,62,65],{},"Перейдіть на вкладку Мережа, перезавантажте сторінку й наберіть ",[58,59,60],"code",{},"supabase"," у\nполі фільтра. Ваш застосунок зробить щонайменше один запит на адресу, що\nзакінчується на ",[58,63,64],{},".supabase.co",". Клацніть його. Там усередині лежать дві речі,\nпотрібні вам для решти статті:",[67,68,69,80],"ul",{},[70,71,72,75,76,79],"li",{},[17,73,74],{},"Адреса запиту"," починається з URL вашого проєкту, щось на кшталт\n",[58,77,78],{},"https:\u002F\u002Fabcdefghij.supabase.co",". Перевірки 2 і 3 націлені на неї.",[70,81,82,88],{},[17,83,84,85],{},"Заголовок запиту ",[58,86,87],{},"apikey"," несе ключ, який ваш застосунок віддає кожному\nвідвідувачу.",[10,90,91,92,95,96,99,100,103,104,107,108,46],{},"Скопіюйте обидві речі кудись, а тоді прочитайте сам ключ. Той, що починається з\n",[58,93,94],{},"sb_publishable_",", належить вашому застосунку, і тут нема чого лагодити. Той, що\nпочинається з ",[58,97,98],{},"sb_secret_",", не належить ніколи, і знайти його означає закінчити\nсписок достроково: змініть його сьогодні, поперед усього іншого на цій\nсторінці. Старіші проєкти несуть пару без читабельного префікса, ",[58,101,102],{},"anon"," і\n",[58,105,106],{},"service_role",", і розрізнити їх означає\n",[42,109,111],{"href":110},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","прочитати роль усередині ключа",[10,113,114],{},"Останній випадок трапляється рідко. Серед 30 998 робочих застосунків, які ми\nпросканували в серпні 2026 року, секретний ключ Supabase у браузері трапився\nтричі.",[10,116,117],{},"Поки вкладка Мережа відкрита, випишіть назви таблиць, які видно в тих адресах\nзапитів. Наступній перевірці вони потрібні.",[119,120],"diagram",{"alt":121,"caption":122,"src":123},"Панель бандла посередині, в якій лежать ключ і адреса. Одна стрілка йде ліворуч до вікна браузера, позначена цифрами 4 і 5. Друга йде праворуч до бази даних і бакета сховища з підписом .supabase.co, позначена цифрами 2 і 3.","Усе далі націлене на одну з двох адрес: адресу вашого застосунку й адресу вашого проєкту. Перевірка 1 це те, що дає вам другу.","\u002Fblog\u002Fsupabase-security-checker\u002Ftwo-addresses-1600x680.png",[25,125,127],{"id":126},"перевірка-2-чи-відповідають-ваші-таблиці-незнайомцю","Перевірка 2: чи відповідають ваші таблиці незнайомцю?",[10,129,130],{},"Спитайте базу, скільки рядків вона віддала б комусь без входу, і прочитайте\nчисло з відповіді.",[132,133,139],"pre",{"className":134,"code":136,"language":137,"meta":138},[135],"language-bash","curl -s -i \\\n  -H \"apikey: ВАШ_ПУБЛІЧНИЙ_КЛЮЧ\" \\\n  -H \"Prefer: count=exact\" \\\n  -H \"Range: 0-0\" \\\n  \"https:\u002F\u002FВАШ_ПРОЄКТ.supabase.co\u002Frest\u002Fv1\u002Fprofiles?select=count\" \\\n  | grep -i content-range\n","bash","",[58,140,136],{"__ignoreMap":138},[10,142,143,144,147],{},"Підставте ключ та адресу проєкту з перевірки 1, а замість ",[58,145,146],{},"profiles"," напишіть\nвласну назву таблиці. curl уже встановлений на macOS, на Linux і на сучасному\nWindows, тож нічого завантажувати наперед не треба.",[10,149,150,151,154,155,158],{},"Цей запит не забирає жодного рядка. ",[58,152,153],{},"select=count"," просить кількість,\n",[58,156,157],{},"Range: 0-0"," не просить самих рядків, і вся відповідь приходить в одному\nзаголовку. Це той самий запит, який робить наш сканер, і саме тому він може\nпрацювати проти чужого робочого застосунку, не торкаючись чужих даних.",[10,160,161],{},"Повернутися може чотири речі, і лише одна з них є знахідкою:",[163,164,165,178],"table",{},[166,167,168],"thead",{},[169,170,171,175],"tr",{},[172,173,174],"th",{},"Що друкується",[172,176,177],{},"Що це означає",[179,180,181,192,202,216],"tbody",{},[169,182,183,189],{},[184,185,186],"td",{},[58,187,188],{},"content-range: *\u002F0",[184,190,191],{},"Без входу не читається нічого. Ця таблиця робить свою роботу.",[169,193,194,199],{},[184,195,196],{},[58,197,198],{},"content-range: 0-0\u002F128",[184,200,201],{},"128 рядків доступні кожному, хто має ключ із вашої сторінки.",[169,203,204,213],{},[184,205,206,209,210],{},[58,207,208],{},"401"," або ",[58,211,212],{},"403",[184,214,215],{},"Ключ відхилили ще до таблиці. Без відповіді, а не чисто.",[169,217,218,223],{},[184,219,220],{},[58,221,222],{},"404",[184,224,225],{},"Таблиці з такою назвою немає. Або ви вгадували, або вона зветься інакше.",[119,227],{"alt":228,"caption":229,"src":230},"Дві панелі відповіді поруч. Обидві показують однаковий рядок статусу 200. Ліва обводить заголовок content-range, що закінчується скісною рискою і нулем, і отримує зелену галочку; права обводить той самий заголовок, що закінчується на 128, і отримує червоний хрестик.","Обидва запити були успішні. Один заголовок це вся різниця між таблицею, що робить свою роботу, і таблицею, яка віддає рядки кожному, хто попросить.","\u002Fblog\u002Fsupabase-security-checker\u002Fthe-one-header-1600x700.png",[10,232,233,234,236],{},"Відмова це той рядок, з яким слід бути обережним. ",[58,235,208],{}," каже, що запит спинився,\nне дійшовши до таблиці, а це не говорить вам нічого про те, чи таблиця\nзахищена, і з чотирьох саме його найлегше округлити до галочки.",[10,238,239,240,243,244,246,247,243,250,243,253,243,256,259],{},"Виконайте команду для кожної таблиці, яку ваш застосунок назвав у перевірці 1, а\nтоді для звичайних, які застосунок зазвичай має: ",[58,241,242],{},"users",", ",[58,245,146],{},",\n",[58,248,249],{},"customers",[58,251,252],{},"orders",[58,254,255],{},"messages",[58,257,258],{},"invoices",". У цих шести лежать дані інших\nлюдей.",[10,261,262,263,267],{},"Це перевірка, яка знаходить найбільше. Із 3 680 застосунків на Supabase, де ми\nзмогли її завершити, 2 096 мали щонайменше одну таблицю, що відповідала на\nзапит без входу, а в 394 із них відкрита таблиця мала назву про людей.\n",[42,264,266],{"href":265},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","Повний вимір і частка від чого це","\nє окремою статтею.",[25,269,271],{"id":270},"перевірка-3-чи-перелічує-бакет-сховища-власні-файли","Перевірка 3: чи перелічує бакет сховища власні файли?",[10,273,274],{},"Попросіть у бакета його вміст і подивіться, чи щось повернеться.",[132,276,279],{"className":277,"code":278,"language":137,"meta":138},[135],"curl -s -X POST \\\n  -H \"apikey: ВАШ_ПУБЛІЧНИЙ_КЛЮЧ\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"prefix\":\"\",\"limit\":1}' \\\n  \"https:\u002F\u002FВАШ_ПРОЄКТ.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Flist\u002Favatars\"\n",[58,280,278],{"__ignoreMap":138},[10,282,283,286],{},[17,284,285],{},"Надішліть тіло запиту."," POST на цю адресу без нічого всередині повертає \"Body\ncannot be empty\" для кожного бакета в кожному проєкті, хоч би як він був\nналаштований. Ми це знаємо, бо наша власна перевірка бакетів вийшла саме такою і\nмісяцями бадьоро повідомляла, що нічого не перелічується.",[10,288,289],{},"Дві форми відповіді:",[67,291,292,298],{},[70,293,294,297],{},[58,295,296],{},"[]"," означає, що бакет закритий або що бакета з такою назвою немає. Ззовні ви\nне скажете, що саме, тож порожній перелік не є доказом нічого.",[70,299,300],{},"Масив із файлом усередині означає, що незнайомець може попросити у вашого\nпроєкту каталог того бакета й отримати його.",[10,302,303,304,243,307,243,310,243,313,243,316,243,319,46],{},"Спробуйте назви бакетів, які використовує ваш застосунок, а тоді поширені:\n",[58,305,306],{},"avatars",[58,308,309],{},"public",[58,311,312],{},"uploads",[58,314,315],{},"files",[58,317,318],{},"images",[58,320,321],{},"documents",[10,323,324,325,329],{},"Перелічуваність і публічність це два різні налаштування у двох різних місцях, і\n",[42,326,328],{"href":327},"\u002Fblog\u002Fsupabase-storage-bucket-public","різниця вирішує, наскільки важливий публічний бакет",".\nПерелік це те, що варто закрити, бо він позбавляє незнайомця клопоту вгадувати\nназву файлу. Із 27 269 застосунків, де ми змогли спитати, 792 відповіли\nпереліком.",[25,331,333],{"id":332},"перевірка-4-чи-публікується-ваш-вихідний-код-поряд-із-застосунком","Перевірка 4: чи публікується ваш вихідний код поряд із застосунком?",[10,335,336],{},"Прочитайте останній рядок свого бандла JavaScript.",[10,338,339,340,343],{},"Поверніться на вкладку Мережа з перевірки 1, знайдіть найбільший файл ",[58,341,342],{},".js",",\nякий завантажив ваш застосунок, і скопіюйте його адресу. Тоді:",[132,345,348],{"className":346,"code":347,"language":137,"meta":138},[135],"curl -s \"https:\u002F\u002Fваш-застосунок.example\u002Fassets\u002Findex-abc123.js\" | tail -c 120\n",[58,349,347],{"__ignoreMap":138},[10,351,352,353,356],{},"Останній рядок із ",[58,354,355],{},"\u002F\u002F# sourceMappingURL=index-abc123.js.map"," означає, що ваша\nзбірка записала source map і сказала браузерам, де вона лежить. Чи опублікувала\nвона її насправді, з’ясовує ще один запит:",[132,358,361],{"className":359,"code":360,"language":137,"meta":138},[135],"curl -s -o \u002Fdev\u002Fnull -w \"%{http_code}\\n\" \\\n  \"https:\u002F\u002Fваш-застосунок.example\u002Fassets\u002Findex-abc123.js.map\"\n",[58,362,360],{"__ignoreMap":138},[10,364,365,368,369,46],{},[58,366,367],{},"200"," означає, що завантажити її може будь-хто. Source map перетворює стиснений\nJavaScript назад на ваші оригінальні файли, зі структурою тек, коментарями й\nлогікою. Вона відкриває ваш код, а будь-який ключ, який вона показує, і так уже\nлежав поруч у бандлі, про що й була перевірка 1. 3 885 із 30 987 застосунків,\nякі ми змогли перевірити, публікують свою, і в деяких білдерів це типове\nналаштування платформи, а не чиєсь рішення:\n",[42,370,372],{"href":371},"\u002Fblog\u002Fsource-maps-exposed-in-production","що показує опублікована source map",[25,374,376],{"id":375},"перевірка-5-що-ваш-хостинг-надсилає-з-кожною-сторінкою","Перевірка 5: що ваш хостинг надсилає з кожною сторінкою",[10,378,379],{},"Один запит на адресу вашого застосунку, і читаємо, що повернулося разом із ним.",[132,381,384],{"className":382,"code":383,"language":137,"meta":138},[135],"curl -s -i \"https:\u002F\u002Fваш-застосунок.example\" | grep -i -E \\\n  \"content-security-policy|strict-transport-security|x-frame-options|x-content-type-options|referrer-policy\"\n",[58,385,383],{"__ignoreMap":138},[10,387,388],{},"П’ять заголовків, і ті, що не надрукувалися, це ті, яких вам бракує. Вони кажуть\nбраузеру відмовити сторінці, якщо її завантажують усередині чужого сайту,\nнаступного разу вимагати зашифроване з’єднання й перестати вгадувати, який тип\nфайлу він щойно отримав.",[10,390,391,392,46],{},"Майже кожен застосунок провалює цю перевірку, і майже ніхто не може на неї\nвплинути. У 30 756 із 30 981 застосунку, який ми змогли перевірити, бракувало\nщонайменше одного, бо ці заголовки надсилає платформа хостингу, а власник на\nпіддомені білдера не має де їх змінити. Ми це рахуємо й обмежуємо середнім\nрівнем:\n",[42,393,395],{"href":394},"\u002Fblog\u002Fmissing-security-headers","що передвіщають і чого не передвіщають відсутні заголовки",[25,397,399],{"id":398},"як-читати-те-що-ви-знайшли","Як читати те, що ви знайшли",[10,401,402],{},"За серйозністю, і це не той порядок, у якому ви їх виконували.",[10,404,405,408],{},[17,406,407],{},"Секретний ключ у бандлі йде першим."," Він пропускає кожне правило, яке ви\nнаписали на кожній таблиці, тож змініть його, перш ніж дивитися на будь-що інше\nтут.",[10,410,411,414,415,246,417,243,419,421,422,424,425,428],{},[17,412,413],{},"Таблиця з людьми, що відповіла на перевірку 2, іде наступною."," У ",[58,416,242],{},[58,418,146],{},[58,420,252],{}," і ",[58,423,255],{}," лежать дані інших людей, і вони доступні прямо\nзараз. Таблиця ",[58,426,427],{},"products",", що відповідає так само, може бути цілком правильною, і\nви єдина людина, яка розрізнить ці два випадки.",[10,430,431,434],{},[17,432,433],{},"Далі перелічуваний бакет, далі мапи й заголовки",", які зазвичай є типовими\nналаштуваннями вашої платформи, а не чимось, що ви обрали.",[10,436,437,438,441,443],{},"Одна річ із усіх п’яти. ",[17,439,440],{},"Перевірка, яка не отримала відповіді, не пройшла.",[58,442,208],{},", запит, у якого вичерпався час, таблиця, назву якої ви вгадали\nнеправильно: кожне з цього є питанням, що досі відкрите. Наш сканер пише\n«Не вдалося перевірити» в таких рядках і не чіпає оцінку, а робити це вручну\nозначає вести той список самому.",[10,445,446],{},"Усе це також описує застосунок, який був у роботі в ту мить, коли ви спитали.\nRow Level Security вимикають, щоб сторінка завантажилася, бакет відкривають\nзаради одного завантаження, ключ вставляють, щоб функція вийшла сьогодні\nввечері.",[25,448,450],{"id":449},"що-зробити-цього-тижня","Що зробити цього тижня",[452,453,454],"key-takeaways",{},[67,455,456,470,473,476,479],{},[70,457,458,459,243,461,243,463,243,465,421,467,469],{},"Виконайте перевірку 2 проти кожної таблиці, яку називає ваш застосунок, а тоді проти ",[58,460,242],{},[58,462,146],{},[58,464,249],{},[58,466,252],{},[58,468,255],{},". Саме там знахідки.",[70,471,472],{},"Якщо перевірка 1 виявила секретний ключ, спершу змініть його. Видалення з коду лишає старе значення робочим для тих, хто вже його має.",[70,474,475],{},"Випишіть кожну пробу, що отримала відмову або взагалі не отримала відповіді. Вони лишилися без відповіді, а питання без відповіді це не чистий результат.",[70,477,478],{},"Не чіпайте таблиці, які й мають бути публічними. Список товарів, що відповідає незнайомцю, це ваш застосунок, який працює правильно.",[70,480,481],{},"Виконайте всі п’ять знову після деплою і після того, як хтось змінить правило бази. Жодна з цих подій не оголошує про себе.",[119,483],{"alt":484,"caption":485,"src":486},"Звіт Reeve. Велика бурштинова плитка з літерою C, під нею число 85 зі 100, а праворуч дев’ять рядків, у кожному значок перевірки й смуга. Сім рядків мають зелену галочку, рядок сховища має червоний хрестик, а рядок бази даних має порожнє пунктирне поле замість позначки.","Ті самі п’ять перевірок і ще чотири, повернуті як звіт. Бал це 85, а оцінка C, бо одна висока знахідка обмежує літеру, хай що каже арифметика. Пунктирний рядок це база даних, яка так і не відповіла.","\u002Fblog\u002Fsupabase-security-checker\u002Fgrade-score-and-checks-1600x760.png",[10,488,489,490,494],{},"Наш ",[42,491,493],{"href":492},"\u002Fsecurity-scanner","безкоштовний сканер безпеки"," виконує ці п’ять і ще\nчотири перевірки на будь-якій робочій адресі приблизно за двадцять секунд, без\nоблікового запису й без переданих даних доступу. Він читає, ніколи не пише, а\nтам, де не отримує відповіді, пише про це в рядку.",[10,496,497,498,46],{},"Усі п’ять ви можете зробити самі сьогодні. Чого не скаже вам жоден окремий\nпрохід, так це чи будуть відповіді тими самими наступного місяця, і саме для\nцього ми зробили Reeve Care: він повторює ці перевірки за розкладом, пише вам\nлиста, коли відповідь погіршується, і тримає перевірені резервні копії вашої\nбази Supabase, а також файли ваших користувачів, щойно ви під’єднаєте доступ до\nсховища. ",[42,499,501],{"href":500},"\u002F#pricing","Що він стежить і скільки коштує",[10,503,504,505,509],{},"Якщо термінал це не те місце, де вам хочеться бути, покрокова інструкція\nпростою мовою для ",[42,506,508],{"href":507},"\u002Fis-your-supabase-app-safe","застосунків на Supabase"," пояснює,\nдля чого кожне з цих налаштувань і де знайти його в панелі.",{"title":138,"searchDepth":511,"depth":511,"links":512},3,[513,515,516,517,518,519,520,521],{"id":27,"depth":514,"text":28},2,{"id":49,"depth":514,"text":50},{"id":126,"depth":514,"text":127},{"id":270,"depth":514,"text":271},{"id":332,"depth":514,"text":333},{"id":375,"depth":514,"text":376},{"id":398,"depth":514,"text":399},{"id":449,"depth":514,"text":450},"Основи безпеки","\u002Fblog\u002Fsupabase-security-checker\u002Fcover-1200x630.png","Вікно термінала прямо перед вами, п’ять коротких команд під зеленим запрошенням і курсор, що чекає на шостому рядку.","Supabase security checker читає ваш опублікований застосунок, а не налаштування проєкту. Ось п’ять перевірок і як виконати кожну самостійно.",false,"md",[529,532,535,538,541],{"q":530,"a":531},"Чи знаходить Supabase Security Advisor усе?","У своїй половині він знаходить усе. Advisor читає конфігурацію вашого проєкту й повідомляє про таблиці з вимкненою Row Level Security, функції з нестрогим search path та подібні налаштування, якими ви керуєте з панелі. Чого він не бачить, так це вашого опублікованого застосунку: який ключ опинився в JavaScript, що завантажують ваші відвідувачі, чи справді написана вами політика зупиняє анонімний запит, і які заголовки надсилає ваш хостинг. Запустіть і Advisor, і п’ять перевірок із цієї статті, бо вони дивляться на різні речі.",{"q":533,"a":534},"Чи безпечно запускати ці перевірки проти власного проєкту?","Так. Кожна команда тут читає, і жодна не пише. Перевірка таблиць просить у бази кількість рядків і читає число із заголовка відповіді, тож жоден рядок ніколи не завантажується. Перевірка бакетів просить перелік і на цьому спиняється, не завантажуючи жодного файлу. Останні дві є звичайним запитом сторінки, таким самим, які ваші відвідувачі роблять цілий день. Запускати їх проти чужого проєкту це вже інше питання, і відповідь на нього одна: спершу спитати власника.",{"q":536,"a":537},"Мій ключ anon лежить у бандлі. Це проблема?","Ні. Ключ anon у старіших проєктах і sb_publishable_ у новіших зроблені саме для того, щоб бути в коді, який завантажують ваші відвідувачі. Він називає ваш проєкт і сам собою не дає нічого; те, які рядки поверне запит, вирішує Row Level Security. Ключ, якого там не має бути ніколи, це секретний: service_role у старіших проєктах і sb_secret_ у новіших, бо він пропускає кожне правило, яке ви написали.",{"q":539,"a":540},"Що означає content-range: *\u002F0?","Це ваша база каже, що видасть цьому запитувачу нуль рядків із тієї таблиці. Зірочка означає, що у відповіді немає жодного рядка, а число після скісної риски це кількість, яку запитувачу дозволено бачити. Тож *\u002F0 це відповідь, якої ви хочете від таблиці з персональними даними, а 0-0\u002F128 означає, що 128 рядків доступні кожному, хто має ключ із вашого застосунку.",{"q":542,"a":543},"Чи потрібен мені ключ service_role, щоб це перевірити?","Ні, і чекер, який його просить, просить не те. Кожна перевірка тут використовує публічний ключ, який і так лежить у вашому застосунку, бо саме такий був би в незнайомця. Перевірка секретним ключем скаже вам, до чого дістанеться адміністратор, а це ніколи не було під питанням. Не вставляйте ключ service_role чи sb_secret_ у жоден сканер, наш зокрема: ніщо з того, що ми робимо, його не потребує.","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",[546,547,548,549,550,551,552,553,554,555,556,557],"supabase security checker","перевірити безпеку supabase","supabase rls checker","сканер безпеки supabase","аудит безпеки supabase","перевірити row level security supabase","supabase security advisor","відкриті таблиці supabase","чи публічна моя база supabase","ключ anon supabase відкритий","перевірити публічний бакет supabase","сканер витоків supabase",{},true,"Supabase security checker: п’ять перевірок","\u002Fblog\u002Fsupabase-security-checker","2026-09-06",{"title":5,"description":525},"blog\u002Fsupabase-security-checker",[566,567,568],"Supabase security checker читає ваш робочий застосунок так, як його читає незнайомець: бандл, який ви віддаєте, відповіді ваших таблиць, ваші бакети сховища, ваші заголовки.","Власний Security Advisor від Supabase читає другу половину, тобто конфігурацію вашого проєкту. Жоден із двох не бачить того, що бачить інший.","П’ять перевірок покривають погляд ззовні. Кожна запускається з термінала, не потребує облікового запису, а разом вони займають близько десяти хвилин.","nbTmiROgBLqPb4hw5cXDNnrxlal3EK6SfEuLnDXTsz0",[571,578,584,590,596,602,608,614,620,626,632,638,644,650,656,662,668,674,675,681,686,692,698,704,710,716,722,728,734,740,746,752,757,763,769,774,778,784,790,795,800,806],{"path":572,"title":573,"description":574,"published":575,"category":576,"image":577,"draft":526},"\u002Fblog\u002Fsupabase-backup-auth-users","Чому у вашому дампі Supabase немає користувачів","Запустіть supabase db dump окремо і отримаєте форму вашої бази та жодного її рядка, без схеми auth, у якій живуть ваші користувачі.","2026-09-23","Backups","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":579,"title":580,"description":581,"published":582,"category":522,"image":583,"draft":526},"\u002Fblog\u002Fdomain-and-certificate-expiry","Домен закінчився, сайт лежить: що буде далі","Ваш домен закінчився і сайт лежить. Ось який годинник уже пішов, чому прострочений сертифікат це менша з двох бід, і як перевірити обидва.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":585,"title":586,"description":587,"published":588,"category":522,"image":589,"draft":526},"\u002Fblog\u002Fis-lovable-safe","Чи безпечний Lovable? Що показали 18 554 застосунки Lovable","Чи безпечний Lovable? Ми прогнали 18 554 живі застосунки Lovable через дев’ять перевірок. Платформа виявилася найчистішою з п’яти. Знахідки були в застосунках.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":591,"title":592,"description":593,"published":594,"category":522,"image":595,"draft":526},"\u002Fblog\u002Fvibe-coded-app-security-checklist","Чек-лист безпеки для vibe coding, у девʼяти перевірках","Чек-лист безпеки для vibe coding із девʼяти пунктів, кожен з яких будь-хто може перевірити у вашому живому застосунку ззовні, і кожен має тест на один рядок.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":597,"title":598,"description":599,"published":600,"category":522,"image":601,"draft":526},"\u002Fblog\u002Fstripe-secret-key-in-frontend","Секретний ключ Stripe у фронтенді може рухати гроші","Секретний ключ Stripe, відкритий у вашому фронтенді, може повертати кошти, списувати й читати кожну картку клієнта. А ключ pk_live_ там і має бути.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":603,"title":604,"description":605,"published":606,"category":522,"image":607,"draft":526},"\u002Fblog\u002Fvite-and-next-public-env-vars","Змінні оточення Vite відкриті: префікс означає опублікувати це","Змінні оточення Vite відкриті у вашому застосунку, бо так просив префікс. VITE_ і NEXT_PUBLIC_ означають опублікувати це, а ШІ, який їх додав, не знав ціни.","2026-09-18","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcard-800x500.png",{"path":609,"title":610,"description":611,"published":612,"category":522,"image":613,"draft":526},"\u002Fblog\u002Fbase44-source-maps","Безпека Base44: що позначає скан і що з цього виправляти вам","Безпека Base44 на 5 438 просканованих застосунках: три знахідки майже на кожному належать платформі, source map є бейджем Base44, а ваша частина коротка.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":615,"title":616,"description":617,"published":618,"category":522,"image":619,"draft":526},"\u002Fblog\u002Fis-cursor-ai-safe","Чи безпечний Cursor AI? Редактор, код і опублікований застосунок","Чи безпечний Cursor AI? Три запитання в одному пошуку: що Cursor зберігає, у чому помиляється його код і чи відкритий застосунок, який ви опублікували.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":621,"title":622,"description":623,"published":624,"category":522,"image":625,"draft":526},"\u002Fblog\u002Fis-replit-safe","Чи безпечний Replit? Що ми знайшли в 3 042 живих застосунках Replit","Чи безпечний Replit? Ми прогнали 3 042 живі застосунки Replit через дев’ять зовнішніх перевірок. Знахідки були в опублікованому застосунку, а не в хостингу.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":627,"title":628,"description":629,"published":630,"category":576,"image":631,"draft":526},"\u002Fblog\u002Fsupabase-storage-backup","Supabase storage backup: у копії бази даних немає жодного файлу","Supabase storage backup це окрема робота. Копії бази даних зберігають список ваших файлів і жодного з них, тож після відновлення кожне завантаження зламане.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":633,"title":634,"description":635,"published":636,"category":576,"image":637,"draft":526},"\u002Fblog\u002Fsupabase-point-in-time-recovery","Point-in-time recovery у Supabase: ціна та межі","Point-in-time recovery у Supabase відмотує базу на будь-яку секунду за останній тиждень. Коштує $100 на місяць понад Pro і покриває лише базу даних.","2026-09-13","\u002Fblog\u002Fsupabase-point-in-time-recovery\u002Fcard-800x500.png",{"path":639,"title":640,"description":641,"published":642,"category":576,"image":643,"draft":526},"\u002Fblog\u002Fsupabase-project-paused-recover","Проєкт Supabase на паузі? Ваші дані нікуди не зникли","Supabase поставив ваш проєкт на паузу після тижня без активності. Нічого не видалено, кнопка Restore стоїть поруч із назвою, і у вас є рік, щоб натиснути.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":645,"title":646,"description":647,"published":648,"category":522,"image":649,"draft":526},"\u002Fblog\u002Fsafest-ai-app-builder","Який білдер застосунків з ШІ найбезпечніший? 30 998 тестів","Який білдер застосунків з ШІ найбезпечніший? Ми просканували 30 998 живих застосунків з Lovable, Base44, Replit, v0 і Bolt. Оцінку вирішує не білдер.","2026-09-11","\u002Fblog\u002Fsafest-ai-app-builder\u002Fcard-800x500.png",{"path":651,"title":652,"description":653,"published":654,"category":522,"image":655,"draft":526},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","Увімкніть Row Level Security на кожній таблиці Supabase і перевірте","Row Level Security у Supabase без політики закриває таблицю повністю. Політика без увімкненого перемикача не робить нічого. Ось SQL, і ось перевірка.","2026-09-10","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcard-800x500.png",{"path":657,"title":658,"description":659,"published":660,"category":522,"image":661,"draft":526},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","Supabase \"RLS disabled in public\": чого не бачить попередження","Supabase позначає \"RLS disabled in public\" як помилку. Про політику читання, яка лишає вашу таблицю так само відкритою, він не каже нічого.","2026-09-09","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",{"path":663,"title":664,"description":665,"published":666,"category":522,"image":667,"draft":526},"\u002Fblog\u002Frotate-supabase-service-role-key","Як замінити злитий ключ service_role у Supabase","Supabase каже спершу закрити витік. Інші посібники кажуть міняти негайно. Що правильно, залежить від того, куди саме потрапив ваш ключ service_role.","2026-09-08","\u002Fblog\u002Frotate-supabase-service-role-key\u002Fcard-800x500.png",{"path":669,"title":670,"description":671,"published":672,"category":522,"image":673,"draft":526},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Сканери безпеки для vibe coding у порівнянні, наш теж","Найкращий сканер безпеки для vibe coding залежить від трьох питань, на які не відповідає жоден перелік функцій. Десять інструментів і ціни.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":561,"title":5,"description":525,"published":562,"category":522,"image":544,"draft":526},{"path":676,"title":677,"description":678,"published":679,"category":522,"image":680,"draft":526},"\u002Fblog\u002Fvibe-coding-security-scanner","Сканер безпеки для vibe coding: чого не бачить скан URL","Сканер безпеки для vibe coding читає ваш робочий застосунок ззовні. Що це охоплює, чотири речі, яких він не бачить, і як читати результат.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":394,"title":682,"description":683,"published":684,"category":522,"image":685,"draft":526},"Відсутні заголовки безпеки: коли це справді важливо","Відсутні заголовки безпеки трапляються в наших звітах найчастіше. Від чого вони захищають і коли це найменш терміновий рядок вашого звіту.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":687,"title":688,"description":689,"published":690,"category":522,"image":691,"draft":526},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","Ваш ключ API OpenAI відкритий у фронтенді. Замініть його.","Ключ API OpenAI, відкритий у фронтенді, не можна прив'язати до домену. Замініть його сьогодні, перенесіть виклик на свій сервер і обмежте витрати.","2026-09-03","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":693,"title":694,"description":695,"published":696,"category":522,"image":697,"draft":526},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","Ключ API у фронтенді: що насправді віддають 30 998 застосунків","Ключ API, відкритий у вашому фронтенді, зазвичай є ключем Google Maps. Ми просканували 30 998 vibe-coded застосунків і порахували, що витікає насправді.","2026-09-02","\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps\u002Fcard-800x500.png",{"path":699,"title":700,"description":701,"published":702,"category":576,"image":703,"draft":526},"\u002Fblog\u002Fsupabase-backup-tools-compared","Інструменти резервного копіювання Supabase, і наш серед них","Чотири види інструментів резервного копіювання Supabase, що копіює кожен і коли безкоштовна GitHub Action виграє в будь-якої оплати, нашої теж.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":705,"title":706,"description":707,"published":708,"category":522,"image":709,"draft":526},"\u002Fblog\u002Freplit-secrets-explained","Як користуватися секретами в Replit і що все одно публікується","Як користуватися секретами в Replit: додати, прочитати і усунути дві причини undefined. А ще ключі, які цей інструмент не здатен зберегти в таємниці.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":711,"title":712,"description":713,"published":714,"category":576,"image":715,"draft":526},"\u002Fblog\u002Fback-up-supabase-free-tier","Резервні копії на безкоштовному тарифі Supabase без терміналу","На безкоштовному тарифі Supabase резервних копій немає: копію робите ви. Як зробити її з панелі та що втрачає шлях через CSV.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":717,"title":718,"description":719,"published":720,"category":522,"image":721,"draft":526},"\u002Fblog\u002Fis-supabase-secure","Чи безпечний Supabase? Так. Ваш проєкт це інше питання","Чи безпечний Supabase? Платформа проходить аудити, шифрує дані й тримає пентести. Їхня документація каже, де це закінчується і починаються ваші налаштування.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":723,"title":724,"description":725,"published":726,"category":522,"image":727,"draft":526},"\u002Fblog\u002Fwhere-to-find-supabase-api-keys","Де знайти API-ключі Supabase: anon, service_role і URL","URL проєкту, ключ anon і ключ service_role лежать на одній сторінці панелі. Ось де вона, і яке з чотирьох значень має бути у вашому застосунку.","2026-08-28","\u002Fblog\u002Fwhere-to-find-supabase-api-keys\u002Fcard-800x500.png",{"path":729,"title":730,"description":731,"published":732,"category":522,"image":733,"draft":526},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","New row violates row-level security policy в Supabase. Що далі?","\"New row violates row-level security policy\" означає, що Supabase відмовив у записі. Швидке виправлення знову відкриває таблицю для всіх.","2026-08-27","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",{"path":735,"title":736,"description":737,"published":738,"category":522,"image":739,"draft":526},"\u002Fblog\u002Fcors-wildcard-security-risk","Чи є вайлдкард CORS ризиком для безпеки? Майже ніколи.","Чи є вайлдкард CORS ризиком для безпеки? Зазвичай це типове налаштування вашого білдера, і воно не видає нічого, що ваш сервер і так віддавав кожному.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":741,"title":742,"description":743,"published":744,"category":576,"image":745,"draft":526},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","Branching у Supabase це не бекап. Він іде тільки вперед.","Чому branching у Supabase це не бекап: гілка стартує без ваших даних, а мердж переносить саму лише схему. Для чого він потрібен і що брати замість нього.","2026-08-25","\u002Fblog\u002Fsupabase-branching-is-not-a-backup\u002Fcard-800x500.png",{"path":747,"title":748,"description":749,"published":750,"category":576,"image":751,"draft":526},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","Як відновити резервну копію Supabase, і що ламається потім","Як відновити резервну копію Supabase з панелі або з файлу дампа, що саме замінює відновлення і чому ваш застосунок може лишитися зламаним після нього.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":327,"title":753,"description":754,"published":755,"category":522,"image":756,"draft":526},"Ваш бакет Supabase Storage публічний. Чи це проблема?","Публічний бакет Supabase Storage означає, що той, хто має URL файлу, може його відкрити. Він не означає, що хтось може переглянути список вмісту.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":758,"title":759,"description":760,"published":761,"category":522,"image":762,"draft":526},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","Чи є проблемою ключ API Google у вашому браузері?","Ключ API Google у відкритому коді сторінки наш сканер знаходить найчастіше, і зазвичай усе гаразд. Вирішує це одне безкоштовне налаштування.","2026-08-22","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":764,"title":765,"description":766,"published":767,"category":576,"image":768,"draft":526},"\u002Fblog\u002Fai-agent-deleted-my-database","ШІ-агент видалив мої дані в Supabase. Що можна відновити?","ШІ-агент видалив дані з вашої бази. Те, що ви зможете відновити, вирішилося раніше, а наступні хвилини вирішують, скільки з цього вціліє.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":265,"title":770,"description":771,"published":772,"category":522,"image":773,"draft":526},"Чи може будь-хто прочитати вашу базу Supabase? 3 680 застосунків","Чи може будь-хто прочитати вашу базу даних Supabase без входу? Ми просканували 30 998 живих застосунків, зроблених ШІ-білдерами, і виміряли, як часто так.","2026-08-18","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",{"path":371,"title":775,"description":776,"published":772,"category":522,"image":777,"draft":526},"Відкриті source maps: ваш застосунок публікує свій вихідний код","Відкрита source map дає будь-кому прочитати оригінальний код вашого застосунку, разом із коментарями. Перевірка за 30 секунд, і що важить насправді.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":779,"title":780,"description":781,"published":782,"category":522,"image":783,"draft":526},"\u002Fblog\u002Fsupabase-new-api-keys","Нові API-ключі Supabase: який із них безпечний у застосунку?","Supabase замінив anon і service_role публічними та секретними ключами. Який із них має бути у вашому застосунку, а який не має бути ніколи?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":785,"title":786,"description":787,"published":788,"category":576,"image":789,"draft":526},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","Чи робить Supabase резервні копії моєї бази? Залежить від тарифу.","Чи робить Supabase резервні копії вашої бази даних? На платних тарифах щодня, на безкоштовному жодної. Як дізнатися, що у вас насправді є.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":44,"title":791,"description":792,"published":793,"category":522,"image":794,"draft":526},"Supabase Row Level Security увімкнено. Таблиця досі публічна.","Увімкнути Supabase Row Level Security не означає захистити таблицю. Захищають політики, а та, що полагодила застосунок, часто впускає всіх.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":796,"title":797,"description":798,"published":793,"category":576,"image":799,"draft":526},"\u002Fblog\u002Fversion-history-is-not-a-backup","Історія версій не є резервною копією. Вона не поверне таблицю.","Lovable і Bolt ведуть історію версій вашого коду. Ваша база даних працює як окремий сервіс, тож відкат назад не поверне ваші дані.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":801,"title":802,"description":803,"published":804,"category":576,"image":805,"draft":526},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Три способи зробити резервну копію бази Supabase, і чого бракує","Панель, pg_dump і керований сервіс. Що насправді зберігає кожен спосіб, що тихо лишає осторонь і який із них переживе втрату акаунта.","2026-08-09","\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database\u002Fcard-800x500.png",{"path":110,"title":807,"description":808,"published":804,"category":522,"image":809,"draft":526},"Які API-ключі безпечні у браузері, а які ні","Ваш ключ anon у Supabase створений, щоб бути публічним. Ключ service_role для цього не створений, і він ігнорує всі правила, які ви задали. Як їх розрізнити.","\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend\u002Fcard-800x500.png",1790150956281]