[{"data":1,"prerenderedAt":921},["ShallowReactive",2],{"blog-uk-open-api-endpoint-exposed":3,"blog-index-uk":571},{"id":4,"title":5,"body":6,"category":529,"cover":530,"coverAlt":531,"description":532,"draft":533,"extension":534,"faq":535,"image":550,"keywords":551,"meta":559,"navigation":560,"ogTitle":561,"path":562,"published":563,"seo":564,"stem":565,"tldr":566,"updated":563,"__hash__":570},"blog_uk\u002Fblog\u002Fopen-api-endpoint-exposed.md","Чи є відкритий API-ендпоінт проблемою безпеки? Читайте JSON",{"type":7,"value":8,"toc":515},"minimark",[9,13,21,26,29,32,35,41,44,48,51,54,118,121,125,128,138,144,150,168,179,188,192,195,202,274,282,294,298,301,304,307,312,322,326,329,332,356,359,363,366,369,379,382,388,399,421,427,430,436,445,450,453,459,462,471,475,495,502],[10,11,12],"p",{},"Ваше сканування повернулося з рядком, який не читається як вирок: деякі\nAPI-ендпоінти відповідають без логіна. Можливо, хтось сказав вам це прямішими\nсловами, що у вас відкритий API-ендпоінт. Під ним стоїть адреса, і цілком\nімовірно, що ви її не впізнаєте.",[10,14,15,16,20],{},"Ось та частина, яку посібник за посібником переказують хибно: ",[17,18,19],"strong",{},"звична порада\nщодо цього висновку полягає в тому, щоб поставити логін перед вашим ендпоінтом,\nа в більшості застосунків, які ми сканували, взагалі немає вашого ендпоінта,\nперед яким його ставити."," Семеро з десяти знайдених належать платформі, на\nякій опубліковано застосунок. Тож читання цього висновку починається з того,\nщоб з'ясувати, чия це адреса, і відповідь зазвичай видно вже в першому рядку\nтого, що повертається.",[22,23,25],"h2",{"id":24},"що-відкритий-api-ендпоінт-означає-у-вашому-звіті","Що відкритий API-ендпоінт означає у вашому звіті",[10,27,28],{},"Це означає, що шлях, записаний у коді вашого застосунку, відповів на запит, який\nне ніс логіна, і що повернувся JSON.",[10,30,31],{},"Три кроки, і жоден із них не хитрий. Ми завантажуємо ваш застосунок у браузері\nтак само, як це робить відвідувач, і читаємо код, який той браузер завантажив.\nУсередині лежать адреси, до яких ваш застосунок звертається, коли йому потрібні\nдані. Тоді ми просимо дані в кожної з них, без облікового запису, без cookie і\nбез ключа. Якщо адреса відповідає JSON, який не є повідомленням про помилку,\nвона потрапляє у звіт.",[10,33,34],{},"Це фіксує те, що сталося. Це не присуд про дані, бо ніщо, що стоїть поза вашим\nзастосунком, не здатне розпізнати, чи є перелік речей переліком публічних речей.\nСаме тому висновок сформульовано так, як його сформульовано: ці ендпоінти\nвіддали дані без будь-якої автентифікації, для публічних даних так може бути\nзадумано, перевірте, що жоден із них не розкриває приватної інформації.",[36,37],"diagram",{"alt":38,"caption":39,"src":40},"Код, завантажений із застосунку, з якого виділено чотири адреси. У кожної адреси просить дані запит із перекресленим ключем, тобто без логіна. Три повертаються порожніми або відмовою, а одна повертається з блоком даних.","Адреси беруться з вашого ж коду, і в кожної питають, нічого не додаючи. Те, що відповість, і потрапляє у звіт.","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fwhat-the-check-does-1600x620.png",[10,42,43],{},"Отже, звіт подає вам перелік адрес, які треба відкрити. Кожну з них слід\nвідкрити в розлогіненому браузері, і вирішують справу перші рядки відповіді.",[22,45,47],{"id":46},"чи-кожен-відкритий-api-ендпоінт-є-проблемою-безпеки","Чи кожен відкритий API-ендпоінт є проблемою безпеки?",[10,49,50],{},"Ні. Їх три різновиди, і проблемою є лише третій.",[10,52,53],{},"Уявіть багатоквартирний будинок. Дещо в ньому призначене для кожного, хто\nзайде: години роботи біля дверей, аварійні виходи, оголошення про обслуговування\nліфта у вівторок. Десь в іншому місці того самого будинку стоїть шафа з\nдокументами мешканців. З коридору дошка оголошень і незамкнена шафа з\nдокументами є просто меблями, які можна відчинити, і розрізнити їх можна тільки\nпрочитавши те, що написано на папері.",[55,56,57,73],"table",{},[58,59,60],"thead",{},[61,62,63,67,70],"tr",{},[64,65,66],"th",{},"Що відповіло",[64,68,69],{},"Чия це адреса",[64,71,72],{},"Де ви стоїте",[74,75,76,92,104],"tbody",{},[61,77,78,82,85],{},[79,80,81],"td",{},"Налаштування платформи: cookie-банери, перемикачі функцій",[79,83,84],{},"Вашого білдера, у кожному застосунку, який він видає",[79,86,87],{},[88,89,91],"key-verdict",{"type":90},"safe","Нічого робити",[61,93,94,97,100],{},[79,95,96],{},"Ваші власні публічні дані: прайс-лист, стаття",[79,98,99],{},"Ваша, і призначена для читання",[79,101,102],{},[88,103,91],{"type":90},[61,105,106,109,112],{},[79,107,108],{},"Рядки про людей: імена, пошта, замовлення, повідомлення",[79,110,111],{},"Ваша, і доступна кожному, хто має адресу",[79,113,114],{},[88,115,117],{"type":116},"danger","Закрити сьогодні",[10,119,120],{},"Перший рядок це дошка оголошень, яку прикрутив до стіни хтось інший. Другий це\nдошка, яку ви повісили навмисно. Третій це шафа з документами, і вона стоїть\nвідчиненою стільки, скільки існує адреса.",[22,122,124],{"id":123},"як-перевірити-що-віддають-ваші-ендпоінти","Як перевірити, що віддають ваші ендпоінти",[10,126,127],{},"Відкрийте кожен розлогіненим і прочитайте, що приходить. Читання забирає більше\nчасу, ніж підказує висновок, і це єдиний крок, який відповідає на питання.",[10,129,130,133,134,137],{},[17,131,132],{},"Знайдіть адреси."," Відкрийте ваш застосунок у продакшені, натисніть F12, щоб\nвикликати інструменти розробника браузера, перейдіть на вкладку ",[17,135,136],{},"Мережа"," і\nперезавантажте сторінку. Перегляньте запити, які повертаються як JSON. Це адреси,\nз яких ваш застосунок бере дані, а перелік у звіті є їхньою підмножиною.",[10,139,140,143],{},[17,141,142],{},"Запитайте кожну як незнайомець."," Скопіюйте URL, відкрийте приватне вікно\nбраузера, щоб бути розлогіненим, і вставте його. Те, що ви бачите, і є рівно\nтим, що за цією адресою бачить будь-хто в інтернеті.",[10,145,146,149],{},[17,147,148],{},"Прочитайте перші рядки."," Повернутися може одне з трьох:",[151,152,153,162,165],"ul",{},[154,155,156,157,161],"li",{},"Помилка, відмова або ",[158,159,160],"code",{},"[]",". Адреса хоче логін, або для розлогіненого\nвідвідувача там нічого немає. Ідіть далі.",[154,163,164],{},"Налаштування. Прапорці, перемикачі, колір, перелік увімкнених функцій, номер\nверсії. Нікого не названо і нічого не описано. Ідіть далі.",[154,166,167],{},"Рядки. Поштова адреса, ім'я людини, сума замовлення, текст повідомлення,\nномер телефону. Зупиніться, ось вона.",[10,169,170,171,174,175,178],{},"Якщо ви знайшли рядки, спробуйте змінити число в URL, перш ніж закрити вкладку.\nАдреса, яка на ",[158,172,173],{},"id=1"," видає запис однієї людини, а на ",[158,176,177],{},"id=2"," іншої, видає їх\nусі, і це варто знати, перш ніж вирішувати, наскільки це терміново.",[10,180,181,182,187],{},"Наше безкоштовне сканування робить за вас перші два кроки: воно читає в коді\nвашого застосунку адреси, до яких той звертається, питає кожну без логіна і\nперелічує ті, що відповіли даними. Це займає близько 20 секунд і не потребує\nоблікового запису: ",[183,184,186],"a",{"href":185},"\u002Fsecurity-scanner","скануйте свій застосунок",". Третій крок\nваш, бо ви єдина людина, яка знає, чи є ім'я в тому переліку справжнім клієнтом.",[22,189,191],{"id":190},"більшість-знайденого-належить-платформі","Більшість знайденого належить платформі",[10,193,194],{},"У нашому серпневому обході 2026 року 3 852 із 30 926 застосунків, де ця\nперевірка змогла отримати відповідь, мали щонайменше одну адресу, яка відповідає\nбез логіна. Із них 2 705 були застосунками Base44, і в Base44 адреса майже\nзавжди та сама.",[10,196,197,198,201],{},"Це ",[158,199,200],{},"\u002Fapi\u002Fconsent\u002Fconfig",", налаштування cookie цієї платформи. У вересні ми\nповторно відкрили вибірку позначених застосунків Base44, і єдиною адресою, яка\nвідповіла, була саме ця. Вона віддає налаштування, вона однакова в усіх\nзастосунках, і нічиїх даних у ній немає. Сканер повідомляє про неї правильно, а\nвласникові нема чого виправляти.",[55,203,204,217],{},[58,205,206],{},[61,207,208,211,214],{},[64,209,210],{},"Платформа",[64,212,213],{},"Застосунків із висновком",[64,215,216],{},"Застосунків, де перевірка відповіла",[74,218,219,230,241,252,263],{},[61,220,221,224,227],{},[79,222,223],{},"Base44",[79,225,226],{},"2 705",[79,228,229],{},"5 419",[61,231,232,235,238],{},[79,233,234],{},"Власні домени",[79,236,237],{},"82",[79,239,240],{},"955",[61,242,243,246,249],{},[79,244,245],{},"Bolt",[79,247,248],{},"4",[79,250,251],{},"1 120",[61,253,254,257,260],{},[79,255,256],{},"Lovable",[79,258,259],{},"8",[79,261,262],{},"18 518",[61,264,265,268,271],{},[79,266,267],{},"v0",[79,269,270],{},"0",[79,272,273],{},"1 786",[10,275,276,277,281],{},"Однієї платформи в цій таблиці немає навмисно. На Replit припадає великий блок\nрешти висновків, і ніхто не відкривав їхньої вибірки повторно так, як ми\nзробили це з Base44, тож ми ще не знаємо, чиї це адреси. Публікувати число як\nпроблему власника, перш ніж хтось на нього подивився, це рівно той шлях, яким\nналаштування платформи Base44 перетворюється на статистику про недбалих\nвласників. Кожне число вище походить із\n",[183,278,280],{"href":279},"\u002Fresearch\u002Fvibe-coded-app-security-2026","нашого сканування 30 998 живих vibe-coded застосунків",",\nяке публікує кожне разом із базою, на якій його виміряли.",[10,283,284,285,288,289,293],{},"Прочитайте обидва кінці цієї таблиці разом, бо корисною є саме різниця. У\nLovable це 8 застосунків із 18 518, а в v0 жодного. У таких застосунків немає\nсвого маленького сервера: сторінка говорить із Supabase просто з браузера, тож\nніде немає вашого ",[158,286,287],{},"\u002Fapi\u002F…",", який ця перевірка могла б знайти. Дані в такому\nзастосунку захищають правила на кожній таблиці, а це вже інший висновок зі\n",[183,290,292],{"href":291},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","своїм способом ламатися",".",[22,295,297],{"id":296},"коли-json-це-налаштування-а-коли-це-люди","Коли JSON це налаштування, а коли це люди",[10,299,300],{},"Вирішує одне питання: чи описує щось у відповіді людину?",[10,302,303],{},"Налаштування описують ваш застосунок. Прапорець про те, чи увімкнено темну\nтему, перелік валют, які ви приймаєте, версія чогось, текст для cookie-банера.\nПублікація цього видає, як налаштований ваш застосунок, а ваш застосунок і так\nпрацює у всіх на очах.",[10,305,306],{},"Рядки описують ваших користувачів. Ім'я, поштова адреса, що людина купила, що\nнаписала, де живе. Це не речення про конфігурацію, це вміст тієї шафи з\nдокументами, і важить воно через те, наскільки буденно його забрати. Жодного\nзламу немає. Адреса це рядок тексту, який працює в будь-якому браузері, тож її\nвставляють у груповий чат, зберігають у чиїхось нотатках і за розкладом\nзавантажують скриптом, за яким ніхто не стежить.",[36,308],{"alt":309,"caption":310,"src":311},"Дві відповіді однакового розміру і форми. Ліва містить чотири перемикачі, два увімкнені й два вимкнені. Права містить чотири рядки, у кожному постать людини і зафарбований рядок поруч.","Обидві є кодом 200 і блоком JSON, і це все, що бачить перевірка. Різниця між ними і є цілим питанням, а відповісти на нього можна читанням.","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fsettings-or-people-1600x660.png",[313,314,316],"callout",{"type":315},"note",[10,317,318,321],{},[17,319,320],{},"Незручний випадок це адреса, яка колись була налаштуваннями."," Ендпоінт, який\nвіддавав перелік категорій вашого застосунку, був публічними даними того дня,\nколи його написали. Потім хтось додав колонку до таблиці за ним, щоб сторінка\nмогла показувати, хто створив кожну категорію, і та сама адреса почала видавати\nімена. На екрані не змінилося нічого, адреса не зрушила з місця, а висновок у\nвашому звіті читається рівно так само, як раніше.",[22,323,325],{"id":324},"як-закрити-ендпоінт-і-чому-перейменування-шляху-його-не-закриває","Як закрити ендпоінт і чому перейменування шляху його не закриває",[10,327,328],{},"Вимагайте логін на адресі й відповідайте кодом 401 тому, хто звертається без\nнього.",[10,330,331],{},"У цьому все виправлення, і місце йому на самій адресі, а не деінде. Три речі,\nякі виглядають як виправлення і ним не є:",[151,333,334,340,350],{},[154,335,336,339],{},[17,337,338],{},"Перейменувати шлях або прибрати його з коду."," Саме цього варто стерегтися,\nбо висновок зникає. У кого URL уже був, у того він і лишився, він є в історіях\nбраузерів і серверних логах, а шафа й далі стоїть незамкненою, тільки без\nтаблички спереду.",[154,341,342,345,346,293],{},[17,343,344],{},"Звузити ваш заголовок CORS."," Він вирішує, які інші сайти можуть прочитати\nвідповідь усередині чийогось браузера, і більше його ніщо не читає. Скрипт або\nтермінал читає ту саму адресу в обох випадках, і саме тому\n",[183,347,349],{"href":348},"\u002Fblog\u002Fcors-wildcard-security-risk","висновок про вайлдкард є іншим питанням",[154,351,352,355],{},[17,353,354],{},"Фільтрувати в застосунку."," Якщо сторінка ховає рядки, яких не має\nпоказувати, адреса однаково їх надсилає. Фільтрувати треба до того, як\nвідповідь піде назовні.",[10,357,358],{},"Є четвертий варіант, і на публічній сторінці він часто найкращий: не мати\nендпоінта взагалі. Якщо дані потрібні лише вашій власній сторінці, сторінка може\nотримати їх під час складання, а адреса піде з вашого коду разом із ними.",[22,360,362],{"id":361},"який-вигляд-виправлення-має-в-коді","Який вигляд виправлення має в коді",[10,364,365],{},"Дві речі в обробнику, який відповідає на адресу: з'ясувати, хто питає, і\nзупинитися, якщо відповідь це ніхто.",[10,367,368],{},"Можливо, ви ніколи не наберете цього самі, і це нормально. Прочитайте все одно,\nбо саме цим ви перевіряєте, чи справді ваш білдер зробив те, про що ви просили.\nОсь як це виглядало до, і це те, що знайшло сканування:",[370,371,376],"pre",{"className":372,"code":374,"language":375},[373],"language-text","app.get('\u002Fapi\u002Forders', async (req, res) => {\n  const orders = await db.orders.findMany()\n  res.json(orders)\n})\n","text",[158,377,374],{"__ignoreMap":378},"",[10,380,381],{},"А ось після:",[370,383,386],{"className":384,"code":385,"language":375},[373],"app.get('\u002Fapi\u002Forders', async (req, res) => {\n  const user = await getUserFromRequest(req)\n  if (!user) {\n    return res.status(401).json({ error: 'Not signed in' })\n  }\n\n  const orders = await db.orders.findMany({ where: { userId: user.id } })\n  res.json(orders)\n})\n",[158,387,385],{"__ignoreMap":378},[10,389,390,391,394,395,398],{},"Змінилося дві речі, і важать обидві. ",[158,392,393],{},"401"," це двері. ",[158,396,397],{},"where"," це причина, чому\nдвері варті того: без нього залогінений відвідувач може прочитати замовлення\nвсіх інших клієнтів, а це менша аудиторія для тих самих даних і все одно не та.",[10,400,401,404,405,408,409,412,413,416,417,420],{},[17,402,403],{},"В Edge Functions від Supabase спершу прочитайте конфігурацію, а вже потім\nщось пишіть."," Edge Functions перевіряють токен того, хто звертається,\nсамостійно: довідник конфігурації Supabase ставить ",[158,406,407],{},"verify_jwt"," у ",[158,410,411],{},"true"," за\nзамовчуванням, тож функція, яка відповідає незнайомцям, це функція, де хтось це\nвимкнув, або рядком у ",[158,414,415],{},"supabase\u002Fconfig.toml",", або деплоєм із\n",[158,418,419],{},"--no-verify-jwt",":",[370,422,425],{"className":423,"code":424,"language":375},[373],"[functions.orders]\nverify_jwt = false\n",[158,426,424],{"__ignoreMap":378},[10,428,429],{},"Якщо ваша функція має бути приватною, видаліть ці два рядки і задеплойте\nзаново. Лишайте їх тільки там, де ендпоінт справді мусить відповідати будь-кому,\nа це той випадок, який власна документація Supabase бере за приклад: вебхук\nплатежів. Усередині функції сучасний SDK дає вам клієнта, уже обмеженого тією\nлюдиною, яка звернулася:",[370,431,434],{"className":432,"code":433,"language":375},[373],"import { withSupabase } from 'npm:@supabase\u002Fserver'\n\nexport default {\n  fetch: withSupabase({ auth: 'user' }, async (_req, ctx) => {\n    const { data } = await ctx.supabase.from('orders').select()\n    return Response.json(data)\n  }),\n}\n",[158,435,433],{"__ignoreMap":378},[10,437,438,441,442,293],{},[158,439,440],{},"ctx.supabase"," виконується від імені того, хто звернувся, тож ваші правила\nбезпеки на рівні рядків і вирішують, що повернеться, а це той самий захист, на\nякий спирається решта вашого застосунку, і\n",[183,443,444],{"href":291},"те, що варто перевірити окремо",[446,447,449],"h3",{"id":448},"промпт-який-треба-вставити-у-ваш-білдер","Промпт, який треба вставити у ваш білдер",[10,451,452],{},"Якщо ви будуєте в Lovable, Bolt, Cursor, Replit чи v0, дайте йому ось це.\nЛишіть його англійською, якою б мовою ви це не читали, бо саме цією мовою ці\nінструменти міркують, і замініть дві частини у квадратних дужках на те, що\nкаже ваш власний звіт:",[370,454,457],{"className":455,"code":456,"language":375},[373],"A security scan of [my-app.com] found these API endpoints answer\nwithout any authentication: [\u002Fapi\u002Forders, \u002Fapi\u002Fusers].\n\nPlease look at each one and decide whether it is meant to be public.\nFor the ones that are not, require a valid session or API token and\nreturn 401 otherwise. Make sure each one returns only the rows that\nbelong to the person asking, not the whole table filtered in the UI.\nFor any that must stay open, make sure they return only non-sensitive\ndata and add rate limiting so they cannot be abused.\n\nTell me what you changed for each endpoint, and do not rename or\nremove the paths.\n",[158,458,456],{"__ignoreMap":378},[10,460,461],{},"Останнє речення стоїть там навмисно. Коли модель просять прибрати висновок,\nвона інколи обирає найкоротший шлях і переносить адресу, а це єдиний результат,\nякий під час наступного сканування має вигляд успіху й нічого не змінює.",[313,463,465],{"type":464},"warn",[10,466,467,470],{},[17,468,469],{},"Перескановуйте розлогіненим, а не залогіненим."," Коли виправлення вже\nрозгорнуте, перевірте його так, як описує розділ вище: приватне вікно браузера\nі URL. Перевірка залогіненим доводить, що ендпоінт досі працює для вас, а в\nцьому ніхто й не сумнівався. Вийдіть з облікового запису і прочитайте ще раз.",[22,472,474],{"id":473},"що-робити-просто-зараз","Що робити просто зараз",[476,477,478],"key-takeaways",{},[151,479,480,483,486,489,492],{},[154,481,482],{},"Відкрийте кожну позначену адресу в приватному вікні браузера і прочитайте, що повертається. Це той крок, якого звіт за вас не зробить.",[154,484,485],{},"Якщо у відповіді налаштування, а адресу ви ніколи не писали, вона належить вашому білдеру і виправляти нічого не треба. Пошукайте цей шлях у документації вашої платформи, перш ніж щось на нього витрачати.",[154,487,488],{},"Якщо у відповіді є ім'я, поштова адреса чи замовлення, вимагайте логін на цій адресі вже сьогодні й повертайте 401 кожному, хто його не має.",[154,490,491],{},"Не перейменовуйте шлях і не видаляйте посилання на нього. Висновок зникне, а адреса відповідатиме далі.",[154,493,494],{},"Спробуйте змінити id в URL у вашому власному застосунку. Адреса, яка віддає незнайомцю один запис, зазвичай віддає їх усі.",[10,496,497,498,293],{},"Адреси з цього переліку писала людина, яка тоді знала, що за ними стоїть, а\nзмінюється саме те, що за ними стоїть. Reeve Care проганяє це сканування вашим\nживим застосунком за розкладом і надсилає вам листа, коли результат\nпогіршується, а це рівно той випадок, якого розлогінений прохід вище зловити не\nможе: ",[183,499,501],{"href":500},"\u002Fpricing","що він стежить і скільки коштує",[10,503,504,505,509,510,514],{},"Якщо ви радше пройшли б усе за один раз, то\n",[183,506,508],{"href":507},"\u002Fchecklist","10-хвилинний чекліст безпеки"," охоплює це поряд з рештою того, що\nсвіжозапущений застосунок схильний лишати відкритим, а\n",[183,511,513],{"href":512},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","які ключі безпечні у вашому фронтенді","\nце той інший висновок, з яким люди зазвичай приходять.",{"title":378,"searchDepth":516,"depth":516,"links":517},3,[518,520,521,522,523,524,525,528],{"id":24,"depth":519,"text":25},2,{"id":46,"depth":519,"text":47},{"id":123,"depth":519,"text":124},{"id":190,"depth":519,"text":191},{"id":296,"depth":519,"text":297},{"id":324,"depth":519,"text":325},{"id":361,"depth":519,"text":362,"children":526},[527],{"id":448,"depth":516,"text":449},{"id":473,"depth":519,"text":474},"Основи безпеки","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fcover-1200x630.png","Два однакові віконця у стіні, з кожного визирає аркуш паперу. На одному аркуші ряд перемикачів, на другому стовпчик облич.","Ваше сканування позначило відкритий API-ендпоінт. Чи це важливо, залежить від того, що повернулося, і більшість знайдених належали платформі.",false,"md",[536,539,541,544,547],{"q":537,"a":538},"Що означає \"відкритий API-ендпоінт\" у моєму звіті?","Це означає, що ми прочитали код, який ваш застосунок надсилає у браузер, знайшли там адресу, з якої ваш застосунок бере дані, і попросили в неї дані без облікового запису і без логіна. Вона відповіла, і відповіддю був JSON. У цьому весь висновок. Він фіксує те, що сталося, і не судить, чи були дані приватними, бо ніщо поза вашим застосунком цього знати не може.",{"q":47,"a":540},"Ні. Багато адрес і мають відповідати будь-кому: опублікований прайс-лист, стаття, перелік увімкнених функцій. Проблема виникає там, де адреса віддає рядки, що належать людям, бо робить вона це для кожного, хто має URL. Прочитайте те, що повернулося, і запитайте себе, чи описує щось із цього людину.",{"q":542,"a":543},"Мій звіт позначає ендпоінт, якого я не писав. Що це?","Зазвичай це ендпоінт вашого білдера. Платформи, які дають вашому застосунку маленький власний сервер, кладуть у нього і кілька своїх адрес, а ті лежать у коді кожного застосунку цієї платформи. Найчіткіший приклад, який ми виміряли, це налаштування cookie від Base44 за адресою \u002Fapi\u002Fconsent\u002Fconfig, на які припадає 2 705 із 3 852 висновків нашого серпневого обходу 2026 року. Вони віддають налаштування, вони однакові в кожному застосунку Base44, і там немає нічого вашого.",{"q":545,"a":546},"Як перевірити, що віддають ендпоінти мого застосунку?","Відкрийте ваш застосунок у продакшені, натисніть F12, перейдіть на вкладку Мережа і перезавантажте сторінку. Запити, які повертаються як JSON, це адреси, з яких ваш застосунок бере дані. Скопіюйте кожен URL, відкрийте приватне вікно браузера, щоб бути розлогіненим, і вставляйте їх по одному. Читайте те, що приходить. Помилка або порожній список це нормально. Рядки з іменами, поштовими адресами чи сумами замовлень може прочитати будь-хто, у кого є та адреса.",{"q":548,"a":549},"Чи допоможе сховати шлях?","Ні. Перейменування адреси або вилучення посилання на неї з вашого коду заважає сканеру її знайти і лишає її відповідати рівно так само, як раніше. У кого URL уже був, у того він і лишився, і вона осідає в історіях браузерів, серверних логах і всьому, що обходило ваш сайт. Виправляють це на самій адресі: вимагати логін і відповідати незнайомцю кодом 401.","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fcard-800x500.png",[552,553,554,555,556,557,558],"відкритий api ендпоінт","api ендпоінт без автентифікації","api ендпоінт віддає дані без логіна","чи публічний мій api ендпоінт","незахищений api маршрут","api ендпоінт без входу","відкритий json ендпоінт",{},true,"Чи є відкритий API-ендпоінт проблемою безпеки?","\u002Fblog\u002Fopen-api-endpoint-exposed","2026-09-25",{"title":5,"description":532},"blog\u002Fopen-api-endpoint-exposed",[567,568,569],"Відкритий API-ендпоінт означає, що шлях, записаний у коді вашого застосунку, відповів на запит без логіна, і повернувся JSON.","Із тих, що ми знайшли у 30 926 застосунках, семеро з десяти поклала туди платформа, на якій застосунок опубліковано, і вони віддають налаштування.","Вирішує одне питання: чи описує щось у відповіді людину. Прайс-лист є публічним навмисно. Список ваших клієнтів таким не був ніколи.","4iGFIUq0hi1A4C69QTsvNP8wO5SO_Z_7UIeEJJBAqLU",[572,578,584,590,596,602,608,614,620,626,632,638,644,651,657,663,668,669,675,681,687,693,699,705,711,717,723,729,735,741,747,753,759,765,771,777,783,789,795,801,807,813,819,825,831,837,843,848,854,860,866,872,878,884,889,895,901,906,911,917],{"path":573,"title":574,"description":575,"published":576,"category":529,"image":577,"draft":533},"\u002Fblog\u002Fbase44-security-scan","Сканування безпеки Base44: те, що бачить лише воно","Сканування безпеки Base44 перевіряє сім видів проблем зсередини. Ось половина, яку читає тільки воно, і половина, на яку воно ніколи не дивиться.","2026-10-10","\u002Fblog\u002Fbase44-security-scan\u002Fcard-800x500.png",{"path":579,"title":580,"description":581,"published":582,"category":529,"image":583,"draft":533},"\u002Fblog\u002Fapi-key-leaked-what-to-do","Ваш API-ключ витік. Порядок дій","API-ключ витік, і ви не знаєте, що робити першим. Не кожен ключ у вашому фронтенді є витоком, а порядок важить більше за швидкість.","2026-10-09","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fcard-800x500.png",{"path":585,"title":586,"description":587,"published":588,"category":529,"image":589,"draft":533},"\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","\"Infinite recursion detected in policy\" без вимкнення RLS","\"Infinite recursion detected in policy for relation\" означає, що ваша policy запитала таблицю, яку вона захищає. Ось як розірвати коло.","2026-10-08","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fcard-800x500.png",{"path":591,"title":592,"description":593,"published":594,"category":529,"image":595,"draft":533},"\u002Fblog\u002Fno-api-key-found-in-request","\"No API key found in request\" у Supabase, і хибне виправлення","\"No API key found in request\" означає, що запит дійшов до Supabase без ключа. Більшість відповідей натомість вказують на правила вашої бази.","2026-10-07","\u002Fblog\u002Fno-api-key-found-in-request\u002Fcard-800x500.png",{"path":597,"title":598,"description":599,"published":600,"category":529,"image":601,"draft":533},"\u002Fblog\u002Fis-base44-safe","Чи безпечний Base44? Дані 5 442 застосунків","Чи безпечний Base44? Ми прогнали дев’ять перевірок на 5 442 робочих застосунках Base44. Майже всі отримали B з причин, яких власник ніколи не обирав.","2026-10-06","\u002Fblog\u002Fis-base44-safe\u002Fcard-800x500.png",{"path":603,"title":604,"description":605,"published":606,"category":529,"image":607,"draft":533},"\u002Fblog\u002Fmove-a-secret-to-an-edge-function","Сховати ключ API: перенесіть його в Supabase Edge Function","Сховати ключ API означає прибрати його з браузера, а Supabase Edge Function це найменше місце, куди його покласти. Два кроки поруч важать більше.","2026-10-05","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fcard-800x500.png",{"path":609,"title":610,"description":611,"published":612,"category":529,"image":613,"draft":533},"\u002Fblog\u002Fenv-file-exposed-on-your-server","Чи відкритий ваш файл .env? Дванадцять шляхів для перевірки","Чи відкритий ваш файл .env на вашому власному вебсервері? Дванадцять адрес скажуть це за хвилину, а влучання означає, що все в ньому вже публічне.","2026-10-04","\u002Fblog\u002Fenv-file-exposed-on-your-server\u002Fcard-800x500.png",{"path":615,"title":616,"description":617,"published":618,"category":529,"image":619,"draft":533},"\u002Fblog\u002Fis-v0-safe","Безпека v0: усі 1 790 просканованих застосунків v0 отримали A","Безпека v0 на 1 790 живих застосунках v0: усі отримали A. Лише 17 згадували базу даних, і саме це здебільшого вимірює оцінка A.","2026-10-03","\u002Fblog\u002Fis-v0-safe\u002Fcard-800x500.png",{"path":621,"title":622,"description":623,"published":624,"category":529,"image":625,"draft":533},"\u002Fblog\u002Fis-bolt-safe","Чи безпечний Bolt? Що показали 1 123 застосунки Bolt","Чи безпечний Bolt? Ми прогнали 1 123 живі застосунки Bolt через дев’ять перевірок. Хостинг був чистим. Знахідки: ключі й відкриті таблиці в самих застосунках.","2026-10-02","\u002Fblog\u002Fis-bolt-safe\u002Fcard-800x500.png",{"path":627,"title":628,"description":629,"published":630,"category":529,"image":631,"draft":533},"\u002Fblog\u002Fis-supabase-down-or-your-app","Supabase не працює чи проблема у вашому застосунку? Як розрізнити","Supabase не працює чи зламався ваш застосунок? Пауза, повна база й ваша власна помилка виглядають однаково. Чотири перевірки їх розрізняють.","2026-10-01","\u002Fblog\u002Fis-supabase-down-or-your-app\u002Fcard-800x500.png",{"path":633,"title":634,"description":635,"published":636,"category":529,"image":637,"draft":533},"\u002Fblog\u002Fdoes-supabase-encrypt-my-data","Чи шифрує Supabase мої дані? Так. Ось від чого це захищає","Чи шифрує Supabase дані? Так: AES-256 у стані спокою, TLS під час передавання, SOC 2 та ISO 27001. Що покриває кожне і який витік не зупиняє жодне.","2026-09-30","\u002Fblog\u002Fdoes-supabase-encrypt-my-data\u002Fcard-800x500.png",{"path":639,"title":640,"description":641,"published":642,"category":529,"image":643,"draft":533},"\u002Fblog\u002Fsupabase-free-plan-limits","Ліміти безкоштовного тарифу Supabase і що стається на кожному","Ліміти безкоштовного тарифу Supabase: 500 МБ бази, 5 ГБ egress і жодних резервних копій. Що стається на кожній межі і що змінює Pro за $25.","2026-09-29","\u002Fblog\u002Fsupabase-free-plan-limits\u002Fcard-800x500.png",{"path":645,"title":646,"description":647,"published":648,"category":649,"image":650,"draft":533},"\u002Fblog\u002Ftest-your-supabase-backup","Перевірте резервну копію Supabase до того, як вона знадобиться","Як перевірити резервну копію Supabase: відновити в тестовий проєкт, порахувати рядки, увійти й знайти рядок, якого бракує обрізаному файлу.","2026-09-28","Backups","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",{"path":652,"title":653,"description":654,"published":655,"category":649,"image":656,"draft":533},"\u002Fblog\u002Fsupabase-backup-github-action","Безкоштовна резервна копія Supabase через GitHub Action і підступ","Резервна копія Supabase через GitHub Action безкоштовна й годиться багатьом застосункам. Робочий процес, потрібний рядок підключення та egress.","2026-09-27","\u002Fblog\u002Fsupabase-backup-github-action\u002Fcard-800x500.png",{"path":658,"title":659,"description":660,"published":661,"category":649,"image":662,"draft":533},"\u002Fblog\u002Fdownload-your-supabase-backup","Чому ви не можете завантажити резервну копію Supabase","Завантажити резервну копію Supabase на сучасному проєкті не вийде: щоденна копія там фізична. Як це перевірити і як тримати власну копію.","2026-09-26","\u002Fblog\u002Fdownload-your-supabase-backup\u002Fcard-800x500.png",{"path":664,"title":665,"description":666,"published":661,"category":529,"image":667,"draft":533},"\u002Fblog\u002Fsupabase-permission-denied-for-table","Supabase \"permission denied for table\": бракує GRANT","З 30 жовтня нова таблиця в Supabase відповідає \"permission denied for table\", доки ви не дасте доступ. Лист показує лише половину виправлення.","\u002Fblog\u002Fsupabase-permission-denied-for-table\u002Fcard-800x500.png",{"path":562,"title":5,"description":532,"published":563,"category":529,"image":550,"draft":533},{"path":670,"title":671,"description":672,"published":673,"category":529,"image":674,"draft":533},"\u002Fblog\u002Flovable-security-scan","Сканування безпеки Lovable: чого воно не доведе","Сканування безпеки Lovable: що перевіряють Quick scan і Deep scan, коли запускається кожне, і єдине, чого не доведе жодне сканування зсередини.","2026-09-24","\u002Fblog\u002Flovable-security-scan\u002Fcard-800x500.png",{"path":676,"title":677,"description":678,"published":679,"category":649,"image":680,"draft":533},"\u002Fblog\u002Fsupabase-backup-auth-users","Чому у вашому дампі Supabase немає користувачів","Запустіть supabase db dump окремо і отримаєте форму вашої бази та жодного її рядка, без схеми auth, у якій живуть ваші користувачі.","2026-09-23","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":682,"title":683,"description":684,"published":685,"category":529,"image":686,"draft":533},"\u002Fblog\u002Fdomain-and-certificate-expiry","Домен закінчився, сайт лежить: що буде далі","Ваш домен закінчився і сайт лежить. Ось який годинник уже пішов, чому прострочений сертифікат це менша з двох бід, і як перевірити обидва.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":688,"title":689,"description":690,"published":691,"category":529,"image":692,"draft":533},"\u002Fblog\u002Fis-lovable-safe","Чи безпечний Lovable? Що показали 18 554 застосунки Lovable","Чи безпечний Lovable? Ми прогнали 18 554 живі застосунки Lovable через дев’ять перевірок. Платформа виявилася найчистішою з п’яти. Знахідки були в застосунках.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":694,"title":695,"description":696,"published":697,"category":529,"image":698,"draft":533},"\u002Fblog\u002Fvibe-coded-app-security-checklist","Чек-лист безпеки для vibe coding, у девʼяти перевірках","Чек-лист безпеки для vibe coding із девʼяти пунктів, кожен з яких будь-хто може перевірити у вашому живому застосунку ззовні, і кожен має тест на один рядок.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":700,"title":701,"description":702,"published":703,"category":529,"image":704,"draft":533},"\u002Fblog\u002Fstripe-secret-key-in-frontend","Секретний ключ Stripe у фронтенді може рухати гроші","Секретний ключ Stripe, відкритий у вашому фронтенді, може повертати кошти, списувати й читати кожну картку клієнта. А ключ pk_live_ там і має бути.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":706,"title":707,"description":708,"published":709,"category":529,"image":710,"draft":533},"\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":712,"title":713,"description":714,"published":715,"category":529,"image":716,"draft":533},"\u002Fblog\u002Fbase44-source-maps","Безпека Base44: що позначає скан і що з цього виправляти вам","Безпека Base44 на 5 438 просканованих застосунках: три знахідки майже на кожному належать платформі, source map є бейджем Base44, а ваша частина коротка.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":718,"title":719,"description":720,"published":721,"category":529,"image":722,"draft":533},"\u002Fblog\u002Fis-cursor-ai-safe","Чи безпечний Cursor AI? Редактор, код і опублікований застосунок","Чи безпечний Cursor AI? Три запитання в одному пошуку: що Cursor зберігає, у чому помиляється його код і чи відкритий застосунок, який ви опублікували.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":724,"title":725,"description":726,"published":727,"category":529,"image":728,"draft":533},"\u002Fblog\u002Fis-replit-safe","Чи безпечний Replit? Що ми знайшли в 3 042 живих застосунках Replit","Чи безпечний Replit? Ми прогнали 3 042 живі застосунки Replit через дев’ять зовнішніх перевірок. Знахідки були в опублікованому застосунку, а не в хостингу.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":730,"title":731,"description":732,"published":733,"category":649,"image":734,"draft":533},"\u002Fblog\u002Fsupabase-storage-backup","Supabase storage backup: у копії бази даних немає жодного файлу","Supabase storage backup це окрема робота. Копії бази даних зберігають список ваших файлів і жодного з них, тож після відновлення кожне завантаження зламане.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":736,"title":737,"description":738,"published":739,"category":649,"image":740,"draft":533},"\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":742,"title":743,"description":744,"published":745,"category":649,"image":746,"draft":533},"\u002Fblog\u002Fsupabase-project-paused-recover","Проєкт Supabase на паузі? Ваші дані нікуди не зникли","Supabase поставив ваш проєкт на паузу після тижня без активності. Нічого не видалено, кнопка Restore стоїть поруч із назвою, і у вас є рік, щоб натиснути.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":748,"title":749,"description":750,"published":751,"category":529,"image":752,"draft":533},"\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":754,"title":755,"description":756,"published":757,"category":529,"image":758,"draft":533},"\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":760,"title":761,"description":762,"published":763,"category":529,"image":764,"draft":533},"\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":766,"title":767,"description":768,"published":769,"category":529,"image":770,"draft":533},"\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":772,"title":773,"description":774,"published":775,"category":529,"image":776,"draft":533},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Сканери безпеки для vibe coding у порівнянні, наш теж","Найкращий сканер безпеки для vibe coding залежить від трьох питань, на які не відповідає жоден перелік функцій. Десять інструментів і ціни.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":778,"title":779,"description":780,"published":781,"category":529,"image":782,"draft":533},"\u002Fblog\u002Fsupabase-security-checker","Supabase security checker: п’ять перевірок, які зробите самі","Supabase security checker читає ваш опублікований застосунок, а не налаштування проєкту. Ось п’ять перевірок і як виконати кожну самостійно.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":784,"title":785,"description":786,"published":787,"category":529,"image":788,"draft":533},"\u002Fblog\u002Fvibe-coding-security-scanner","Сканер безпеки для vibe coding: чого не бачить скан URL","Сканер безпеки для vibe coding читає ваш робочий застосунок ззовні. Що це охоплює, чотири речі, яких він не бачить, і як читати результат.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":790,"title":791,"description":792,"published":793,"category":529,"image":794,"draft":533},"\u002Fblog\u002Fmissing-security-headers","Відсутні заголовки безпеки: коли це справді важливо","Відсутні заголовки безпеки трапляються в наших звітах найчастіше. Від чого вони захищають і коли це найменш терміновий рядок вашого звіту.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":796,"title":797,"description":798,"published":799,"category":529,"image":800,"draft":533},"\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":802,"title":803,"description":804,"published":805,"category":529,"image":806,"draft":533},"\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":808,"title":809,"description":810,"published":811,"category":649,"image":812,"draft":533},"\u002Fblog\u002Fsupabase-backup-tools-compared","Інструменти резервного копіювання Supabase, і наш серед них","Чотири види інструментів резервного копіювання Supabase, що копіює кожен і коли безкоштовна GitHub Action виграє в будь-якої оплати, нашої теж.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":814,"title":815,"description":816,"published":817,"category":529,"image":818,"draft":533},"\u002Fblog\u002Freplit-secrets-explained","Як користуватися секретами в Replit і що все одно публікується","Як користуватися секретами в Replit: додати, прочитати і усунути дві причини undefined. А ще ключі, які цей інструмент не здатен зберегти в таємниці.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":820,"title":821,"description":822,"published":823,"category":649,"image":824,"draft":533},"\u002Fblog\u002Fback-up-supabase-free-tier","Резервні копії на безкоштовному тарифі Supabase без терміналу","На безкоштовному тарифі Supabase резервних копій немає: копію робите ви. Як зробити її з панелі та що втрачає шлях через CSV.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":826,"title":827,"description":828,"published":829,"category":529,"image":830,"draft":533},"\u002Fblog\u002Fis-supabase-secure","Чи безпечний Supabase? Так. Ваш проєкт це інше питання","Чи безпечний Supabase? Платформа проходить аудити, шифрує дані й тримає пентести. Їхня документація каже, де це закінчується і починаються ваші налаштування.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":832,"title":833,"description":834,"published":835,"category":529,"image":836,"draft":533},"\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":838,"title":839,"description":840,"published":841,"category":529,"image":842,"draft":533},"\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":348,"title":844,"description":845,"published":846,"category":529,"image":847,"draft":533},"Чи є вайлдкард CORS ризиком для безпеки? Майже ніколи.","Чи є вайлдкард CORS ризиком для безпеки? Зазвичай це типове налаштування вашого білдера, і воно не видає нічого, що ваш сервер і так віддавав кожному.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":849,"title":850,"description":851,"published":852,"category":649,"image":853,"draft":533},"\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":855,"title":856,"description":857,"published":858,"category":649,"image":859,"draft":533},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","Як відновити резервну копію Supabase, і що ламається потім","Як відновити резервну копію Supabase з панелі або з файлу дампа, що саме замінює відновлення і чому ваш застосунок може лишитися зламаним після нього.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":861,"title":862,"description":863,"published":864,"category":529,"image":865,"draft":533},"\u002Fblog\u002Fsupabase-storage-bucket-public","Ваш бакет Supabase Storage публічний. Чи це проблема?","Публічний бакет Supabase Storage означає, що той, хто має URL файлу, може його відкрити. Він не означає, що хтось може переглянути список вмісту.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":867,"title":868,"description":869,"published":870,"category":529,"image":871,"draft":533},"\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":873,"title":874,"description":875,"published":876,"category":649,"image":877,"draft":533},"\u002Fblog\u002Fai-agent-deleted-my-database","ШІ-агент видалив мої дані в Supabase. Що можна відновити?","ШІ-агент видалив дані з вашої бази. Те, що ви зможете відновити, вирішилося раніше, а наступні хвилини вирішують, скільки з цього вціліє.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":879,"title":880,"description":881,"published":882,"category":529,"image":883,"draft":533},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","Чи може будь-хто прочитати вашу базу Supabase? 3 680 застосунків","Чи може будь-хто прочитати вашу базу даних Supabase без входу? Ми просканували 30 998 живих застосунків, зроблених ШІ-білдерами, і виміряли, як часто так.","2026-08-18","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",{"path":885,"title":886,"description":887,"published":882,"category":529,"image":888,"draft":533},"\u002Fblog\u002Fsource-maps-exposed-in-production","Відкриті source maps: ваш застосунок публікує свій вихідний код","Відкрита source map дає будь-кому прочитати оригінальний код вашого застосунку, разом із коментарями. Перевірка за 30 секунд, і що важить насправді.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":890,"title":891,"description":892,"published":893,"category":529,"image":894,"draft":533},"\u002Fblog\u002Fsupabase-new-api-keys","Нові API-ключі Supabase: який із них безпечний у застосунку?","Supabase замінив anon і service_role публічними та секретними ключами. Який із них має бути у вашому застосунку, а який не має бути ніколи?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":896,"title":897,"description":898,"published":899,"category":649,"image":900,"draft":533},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","Чи робить Supabase резервні копії моєї бази? Залежить від тарифу.","Чи робить Supabase резервні копії вашої бази даних? На платних тарифах щодня, на безкоштовному жодної. Як дізнатися, що у вас насправді є.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":291,"title":902,"description":903,"published":904,"category":529,"image":905,"draft":533},"Supabase Row Level Security увімкнено. Таблиця досі публічна.","Увімкнути Supabase Row Level Security не означає захистити таблицю. Захищають політики, а та, що полагодила застосунок, часто впускає всіх.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":907,"title":908,"description":909,"published":904,"category":649,"image":910,"draft":533},"\u002Fblog\u002Fversion-history-is-not-a-backup","Історія версій не є резервною копією. Вона не поверне таблицю.","Lovable і Bolt ведуть історію версій вашого коду. Ваша база даних працює як окремий сервіс, тож відкат назад не поверне ваші дані.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":912,"title":913,"description":914,"published":915,"category":649,"image":916,"draft":533},"\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":512,"title":918,"description":919,"published":915,"category":529,"image":920,"draft":533},"Які API-ключі безпечні у браузері, а які ні","Ваш ключ anon у Supabase створений, щоб бути публічним. Ключ service_role для цього не створений, і він ігнорує всі правила, які ви задали. Як їх розрізнити.","\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend\u002Fcard-800x500.png",1791618974003]