[{"data":1,"prerenderedAt":712},["ShallowReactive",2],{"blog-uk-openai-api-key-exposed-in-frontend":3,"blog-index-uk":470},{"id":4,"title":5,"body":6,"category":427,"cover":428,"coverAlt":429,"description":430,"draft":431,"extension":432,"faq":433,"image":449,"keywords":450,"meta":456,"navigation":457,"ogTitle":458,"path":459,"published":460,"seo":461,"stem":462,"tldr":463,"updated":468,"__hash__":469},"blog_uk\u002Fblog\u002Fopenai-api-key-exposed-in-frontend.md","Ваш ключ API OpenAI відкритий у фронтенді. Замініть його.",{"type":7,"value":8,"toc":413},"minimark",[9,18,26,35,40,43,54,57,60,64,67,82,96,99,103,106,114,117,123,130,133,139,150,153,157,160,163,166,169,173,176,179,184,187,213,216,219,223,241,244,247,252,347,350,366,370,396],[10,11,12,13,17],"p",{},"Відкрийте свій застосунок у браузері, подивіться вихідний код сторінки й\nпошукайте в ньому ",[14,15,16],"code",{},"sk-proj-",". Якщо повернувся довгий рядок, ваш ключ API OpenAI\nвідкритий у вашому фронтенді, і кожен відвідувач, який у вас коли-небудь був, міг\nйого скопіювати.",[10,19,20,21,25],{},"Ось та частина, яку більшість порад на цю тему подає неправильно: ",[22,23,24],"strong",{},"ключ OpenAI\nне є ключем Google з іншим префіксом, і ніщо з того, що ви можете виставити в\nпанелі, не робить його безпечним там, де він лежить."," Ключу Google Maps місце\nна вашій сторінці, і одне безкоштовне налаштування його захищає. У ключа OpenAI\nрівноцінного налаштування немає ніде, і саме тому єдина чесна перша вказівка це\nзамінити його.",[10,27,28,29,34],{},"Між 12 і 14 серпня 2026 року ми прогнали дев’ять зовнішніх перевірок по 30 998\nживих застосунках, зроблених у Lovable, Bolt, v0, Replit і Base44. Ключ OpenAI\nтрапився в 33 із них. Усі 33 повернулися з оцінкою D або F, бо один критичний\nзнахідок обмежує оцінку незалежно від того, що застосунок зробив правильно в\nусьому іншому. Повні цифри є в\n",[30,31,33],"a",{"href":32},"\u002Fresearch\u002Fvibe-coded-app-security-2026","нашому звіті сканування",".",[36,37,39],"h2",{"id":38},"чи-є-проблемою-ключ-api-openai-відкритий-у-фронтенді","Чи є проблемою ключ API OpenAI, відкритий у фронтенді?",[10,41,42],{},"Так. Це той випадок, коли тривога має рацію.",[10,44,45,46,49,50,53],{},"Ключ OpenAI є ",[22,47,48],{},"токеном на пред’явника",", і саме слово несе все пояснення: хто\nйого пред’являє, той може ним користуватися. Він подорожує в заголовку, який\nчитається як ",[14,51,52],{},"Authorization: Bearer sk-proj-…",", і сервери OpenAI не питають\nнічого більше. Ні який сайт його надіслав. Ні з якої країни він прийшов, ані чи\nвідправник це ви.",[10,55,56],{},"Думайте про залізничний квиток, а не про паспорт. Провідник не перевіряє, чиє\nім’я стоїть на квитку, бо володіти ним і є вся кваліфікація. Саме це робить\nквиток вартим крадіжки, а паспорт здебільшого ні.",[10,58,59],{},"Отже, ключ, надрукований у вашому застосунку, це квиток, який ви вручили кожному\nвідвідувачеві. Більшість із них ніколи не подивиться. Ті, хто дивиться,\nзазвичай узагалі не люди: автоматичні скрапери обходять публічні сторінки й\nзбирають рядки у формі ключа, і їм не треба знати, хто ви, щоб знайти ваш.",[36,61,63],{"id":62},"чому-змінна-середовища-його-не-сховала","Чому змінна середовища його не сховала",[10,65,66],{},"Бо фронтендна збірка вкомпільовує змінні середовища у файл, який відвантажує.",[10,68,69,70,73,74,77,78,81],{},"Це той крок, після якого люди впевнені, що ключ у безпеці. Ви винесли його з\nкоду у файл ",[14,71,72],{},".env",", назвали ",[14,75,76],{},"VITE_OPENAI_API_KEY"," або\n",[14,79,80],{},"NEXT_PUBLIC_OPENAI_API_KEY",", і тепер код називає змінну там, де раніше стояв\nключ. У відвантаженому застосунку не змінилося нічого. Інструмент збірки замінив\nцю змінну її значенням на виході, і значення лежить у тому JavaScript, який\nзавантажує ваш відвідувач.",[10,83,84,85,88,89,91,92,95],{},"Документація Vite каже це прямо: змінні з префіксом ",[14,86,87],{},"VITE_"," після бандлінгу\nвідкриті у вихідному коді на боці клієнта, і чутливій інформації на кшталт\nключів API не місце в такій змінній, бо значення запаковуються у ваш вихідний\nкод. Префікси ",[14,90,87],{}," і ",[14,93,94],{},"NEXT_PUBLIC_"," не є сейфом. Вони є заявою про те, що ви\nрозумієте: ця змінна публічна.",[10,97,98],{},"Одну справжню річ змінна середовища для вас усе ж зробила: вона втримала ключ\nпоза вашим репозиторієм, де на нього натрапив би кожен, хто читає ваш код. Ваші\nвідвідувачі ваш код не читають ніколи. Вони читають файл, який зробила з нього\nваша збірка.",[36,100,102],{"id":101},"чому-його-не-можна-обмежити-так-як-обмежують-ключ-google","Чому його не можна обмежити так, як обмежують ключ Google",[10,104,105],{},"Бо OpenAI не пропонує обмеження такого роду.",[10,107,108,109,113],{},"Якщо ви читали про ключ API Google у фронтенді, ви натрапили на п’ятихвилинне\nрішення: відкрийте ключ у консолі Google Cloud, поставте обмеження за\nHTTP-реферером, і надрукований на вашій сторінці ключ працює на вашому сайті й\nповертає помилку скрізь інде.\n",[30,110,112],{"href":111},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","Ця порада правильна для ключа Google",",\nі вона не переноситься.",[10,115,116],{},"У ключа OpenAI немає поля для «лише з yourapp.com». Ні списку дозволених\nдоменів, ні перевірки реферера, ні обмеження за IP, яке пережило б браузер. Те,\nщо OpenAI дає натомість, сидить на обліковому записі позаду ключа: до якого\nпроєкту він належить, скільки цей проєкт може витратити за місяць і чи ключ ще\nіснує. Це обмежує, скільки може коштувати вкрадений ключ. Сам ключ і далі працює\nзвідусіль, доки ви його не видалите.",[118,119],"diagram",{"alt":120,"caption":121,"src":122},"Дві смуги. У верхній смузі ключ Google виходить із двох різних сайтів і зустрічає суцільний бар’єр: запит із yourapp.com проходить його й досягає Google, а запит із other.example зупинено й позначено хрестиком. У нижній смузі ключ OpenAI виходить із тих самих двох сайтів, жодного бар’єра не намальовано взагалі, і обидва запити досягають api.openai.com.","Верхня смуга це те рішення, про яке людям розповідають. У нижній малювати нічого, бо в OpenAI немає налаштування такої форми.","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fno-gate-to-set-1600x820.png",[36,124,126,127],{"id":125},"що-насправді-робить-dangerouslyallowbrowser","Що насправді робить ",[14,128,129],{},"dangerouslyAllowBrowser",[10,131,132],{},"Вимикає запобіжник, а її назва є документацією.",[10,134,135,136,138],{},"Офіційна JavaScript-бібліотека OpenAI за замовчуванням відмовляється працювати в\nбраузері. README каже, що підтримка браузера є\n\"disabled by default to avoid exposing your secret API credentials\", а ввімкнення\n",[14,137,129],{}," \"can be dangerous because it exposes your secret API\ncredentials in the client-side code\".",[10,140,141,142,145,146,149],{},"Якщо ваш застосунок викликає OpenAI з браузера, ця опція десь у вашому коді\nстоїть у ",[14,143,144],{},"true",", бо без неї бібліотека не стартує. Хтось набрав слово\n",[14,147,148],{},"dangerously",", щоб позбутися повідомлення про помилку. Саме так цей знахідок\nзазвичай і з’являється, а бібліотека сказала вам про це першою.",[10,151,152],{},"У опції є справжні застосування, і всі вони вузькі: внутрішній інструмент, де ви\nзнаєте кожного користувача, тимчасовий ключ для розробки, ключ, обмежений\nнастільки щільно, що витратити його нічого не коштує. Публічний застосунок у\nвідкритому інтернеті не є жодним із них.",[36,154,156],{"id":155},"чого-коштує-те-що-хтось-знайшов-ваш-ключ","Чого коштує те, що хтось знайшов ваш ключ",[10,158,159],{},"Рахунку, і застосунку, який перестає працювати.",[10,161,162],{},"Рахунок це та частина, якої люди чекають. Запити когось іншого списуються з\nвашого облікового запису, а виклики моделі не є дешевими за мірками побічного\nпроєкту. Зазвичай власник помічає це за рахунком, більшим за минулий місяць, без\nпричини, на яку він міг би вказати.",[10,164,165],{},"Простій це та частина, якої вони не чекають. У вашого облікового запису є ліміти\nчастоти, і трафік незнайомця їх витрачає. Ваш власний застосунок починає\nповертати помилки в ті години, коли хтось інший зайнятий, і це читається як баг,\nа не як крадіжка, тож люди витрачають день на дебаг не того.",[10,167,168],{},"Є третя стаття витрат, і вона залежить від того, наскільки широким був ключ.\nКлюч API автентифікує кожен виклик, який може зробити проєкт, до якого він\nналежить, тож широко наділений ключ дістає до всього іншого, що там зберігається:\nзавантажених в обліковий запис файлів, донавчених моделей, побудованих вами\nасистентів. Перевірте, до чого ключ насправді міг дістати, перш ніж вирішувати,\nщо йшлося лише про гроші.",[36,170,172],{"id":171},"як-викликати-openai-зі-свого-застосунку-не-відвантажуючи-ключ","Як викликати OpenAI зі свого застосунку, не відвантажуючи ключ",[10,174,175],{},"Поставте щось своє між вашим відвідувачем і OpenAI.",[10,177,178],{},"Форма скрізь однакова. Ваш застосунок звертається до невеликого ендпоінта, який\nналежить вам. Цей ендпоінт тримає ключ, звертається до OpenAI й повертає\nвідповідь. Браузер ключа не бачить ніколи, бо ключ ніколи не залишає ваш сервер.",[118,180],{"alt":181,"caption":182,"src":183},"Два рядки. У верхньому рядку панель браузера тримає значення ключа червоним, і лінія йде звідти прямо до api.openai.com. У нижньому рядку панель браузера не тримає жодного ключа, лінія йде до прямокутника сервера, який тримає ключ бірюзовим, а друга лінія продовжується від сервера до api.openai.com.","В обох рядках той самий запит. Змінюється лише те, з якого боку вашого власного сервера стоїть ключ.","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fwho-holds-the-key-1600x720.png",[10,185,186],{},"Де живе цей ендпоінт, залежить від того, чим ви будували:",[188,189,190,197,207],"ul",{},[191,192,193,196],"li",{},[22,194,195],{},"Supabase у вашому стеку",": Edge Function, з ключем, збереженим як secret у панелі Supabase.",[191,198,199,202,203,206],{},[22,200,201],{},"Розгорнуто на Vercel або Netlify",": serverless-функція під ",[14,204,205],{},"\u002Fapi",", з ключем у серверних змінних середовища проєкту.",[191,208,209,212],{},[22,210,211],{},"Lovable, Bolt або Replit",": у кожного є власне сховище секретів. Правило не змінюється, і пастка теж: сховище з написом «секрети» однаково віддає значення браузеру, якщо код, який його читає, виконується там.",[10,214,215],{},"Дві речі варто зробити, поки ви там. Дайте своєму ендпоінту ліміт частоти, бо\nендпоінт, який звертається до OpenAI для кожного, хто попросить, це той самий\nрахунок повільнішою дорогою. І поставте місячний ліміт витрат на проєкт OpenAI,\nтой єдиний важіль, що підводить дно під найгірший випадок.",[10,217,218],{},"Якщо ваш застосунок використовує Realtime API від OpenAI для голосу, браузеру\nсправді потрібні облікові дані, і OpenAI документує, як їх йому дати: ваш сервер\nкарбує короткоживучий client secret і передає сторінці саме його. Квиток і далі\nіснує, він спливає за хвилини, і випустив його ваш власний сервер.",[36,220,222],{"id":221},"як-безкоштовно-знайти-кожен-ключ-який-відвантажує-ваш-застосунок","Як безкоштовно знайти кожен ключ, який відвантажує ваш застосунок",[10,224,225,226,228,229,232,233,236,237,240],{},"Почніть руками, бо це коштує п’ять хвилин і не потребує нічого встановлювати.\nПодивіться вихідний код свого живого сайту й пошукайте в ньому ",[14,227,16],{}," для\nключа OpenAI, ",[14,230,231],{},"sk-ant-"," для ключа Anthropic, ",[14,234,235],{},"AIza"," для Google і ",[14,238,239],{},"eyJ"," для\nтокена Supabase.",[10,242,243],{},"Повз таку перевірку проходить той JavaScript, який сторінка довантажує потім, а\nу vibe-coded застосунку це майже все. Наш сканер відкриває ваш застосунок у\nсправжньому браузері, чекає, доки прийдуть бандли, і читає їх замість HTML. Він\nтакож розшифровує кожен токен Supabase і повідомляє записану всередині роль, тож\nключ, якому місце на вашій сторінці, повертається позначеним як правильний, а не\nпохованим у стіні червоного.",[10,245,246],{},"Перевірка ключів є однією з дев’яти, а інші вісім є причиною того, чому оцінка\nкаже вам більше, ніж пошук:",[118,248],{"alt":249,"caption":250,"src":251},"Знак Reeve над рядом із дев’яти контурних піктограм, по одній на перевірку: ключ, циліндр бази даних, документ, навісний замок, коробка з кришкою, пара дужок коду, глобус, розетка сертифіката й календар.","Дев’ять перевірок сканування, які лише читають, у порядку списку нижче. Кожну з них читають ззовні, так само як бачить ваш застосунок незнайомець.","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fnine-checks-1600x420.png",[253,254,255,268],"table",{},[256,257,258],"thead",{},[259,260,261,265],"tr",{},[262,263,264],"th",{},"На що дивиться сканування",[262,266,267],{},"На яке питання воно відповідає",[269,270,271,280,288,299,307,315,323,331,339],"tbody",{},[259,272,273,277],{},[274,275,276],"td",{},"Секретні ключі у вашому коді",[274,278,279],{},"Чи є платний або адмінський ключ API, який може прочитати будь-хто?",[259,281,282,285],{},[274,283,284],{},"Правила бази даних",[274,286,287],{},"Чи може незнайомець без входу читати рядки ваших користувачів?",[259,289,290,293],{},[274,291,292],{},"Приватні файли",[274,294,295,296,298],{},"Чи можна завантажити файли ",[14,297,72],{}," або дампи бази за URL?",[259,300,301,304],{},[274,302,303],{},"Заголовки безпеки",[274,305,306],{},"Чи ввімкнені захисти на боці браузера?",[259,308,309,312],{},[274,310,311],{},"Бакети сховища",[274,313,314],{},"Чи може будь-хто перелічити файли, завантажені вашими користувачами?",[259,316,317,320],{},[274,318,319],{},"Source maps",[274,321,322],{},"Чи опублікований ваш оригінальний код поруч із застосунком?",[259,324,325,328],{},[274,326,327],{},"Відкриті API та CORS",[274,329,330],{},"Чи відповідають ваші ендпоінти будь-якому сайту, що запитає?",[259,332,333,336],{},[274,334,335],{},"Строк дії сертифіката",[274,337,338],{},"Чи чинний HTTPS і чи не спливає він просто зараз?",[259,340,341,344],{},[274,342,343],{},"Продовження домену",[274,345,346],{},"Чи продовжено ім’я до того, як його зможе забрати хтось інший?",[10,348,349],{},"Ви отримуєте оцінку, бал і підрахунки на екрані приблизно за 20 секунд, без\nоблікового запису. Дайте адресу електронної пошти, і разом із нею прийде\nдокладний список та написане під ваш білдер виправлення, яке можна вставити\nодразу.",[10,351,352,353,356,357,361,362,34],{},"Три речі, яких він не робитиме, і саме вони є причинами, чому його безпечно\nнацілювати на живий застосунок: він ніколи не входить в акаунт, ніколи нічого не\nпише і ніколи не зберігає знайдений ключ. Відкритий секрет зберігається як\nзамаскована підказка виду ",[14,354,355],{},"sk-proj-…a1b2",", а справжнє значення відкидається.\n",[30,358,360],{"href":359},"\u002F#scan","Проскануйте свій застосунок"," або спершу прочитайте,\n",[30,363,365],{"href":364},"\u002Fsecurity-scanner","на що дивиться кожна з дев’яти перевірок",[36,367,369],{"id":368},"що-зробити-просто-зараз","Що зробити просто зараз",[371,372,373],"key-takeaways",{},[188,374,375,378,381,384,387],{},[191,376,377],{},"Спершу замініть ключ, у панелі OpenAI в розділі API keys. Видалення його з коду не закриває нічого, бо старе значення лишається у вашій історії версій і в кожній кешованій копії сторінки.",[191,379,380],{},"Поставте місячний ліміт витрат на проєкт, до якого належить ключ. Це той єдиний важіль, що обмежує, у скільки може обійтися ця чи будь-яка наступна помилка.",[191,382,383],{},"Перенесіть виклик за власний ендпоінт і дайте цьому ендпоінту власний ліміт частоти. Браузер ніколи не має тримати ключ, що витрачає гроші.",[191,385,386],{},"Перегляньте сторінку використання за ті дні, коли ключ був живий. Заміна спиняє те, що станеться далі, і нічого не каже про те, що вже сталося.",[191,388,389,390,392,393,395],{},"Тримайте префікс ",[14,391,87],{}," або ",[14,394,94],{}," подалі від усього, що вам було б неприємно віддати на прочитання незнайомцеві. Ці префікси означають «публічний», і ваш інструмент збірки розуміє їх буквально.",[10,397,398,399,403,404,408,409,34],{},"Якщо вам зручніше пройти це за один раз,\n",[30,400,402],{"href":401},"\u002Fchecklist","10-хвилинний чекліст безпеки"," покриває це разом з іншими речами,\nякі варто закрити у щойно запущеному застосунку. А на ширше питання про те, яким\nключам узагалі місце в браузері, у нас є\n",[30,405,407],{"href":406},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","посібник, що відрізняє публічні ключі від секретних","\nі\n",[30,410,412],{"href":411},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","перепис того, що насправді відвантажили 30 998 застосунків",{"title":414,"searchDepth":415,"depth":415,"links":416},"",3,[417,419,420,421,423,424,425,426],{"id":38,"depth":418,"text":39},2,{"id":62,"depth":418,"text":63},{"id":101,"depth":418,"text":102},{"id":125,"depth":418,"text":422},"Що насправді робить dangerouslyAllowBrowser",{"id":155,"depth":418,"text":156},{"id":171,"depth":418,"text":172},{"id":221,"depth":418,"text":222},{"id":368,"depth":418,"text":369},"Основи безпеки","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcover-1200x630.png","Значення у формі ключа всередині сторінки коду застосунку, намальоване настільки довгим, що виходить за праву межу панелі, яка його тримає.","Ключ API OpenAI, відкритий у фронтенді, не можна прив'язати до домену. Замініть його сьогодні, перенесіть виклик на свій сервер і обмежте витрати.",false,"md",[434,437,440,443,446],{"q":435,"a":436},"Хтось знайшов мій ключ OpenAI у застосунку. Що робити першим?","Замінити його. Відкрийте панель OpenAI у розділі API keys, створіть новий ключ, покладіть новий на свій сервер і видаліть старий. Видалити його з коду це не те саме, бо старе значення лишається у вашій історії версій і в кожній кешованій копії сторінки. Далі поставте ліміт витрат на проєкт і перегляньте сторінку використання за ті дні, коли ключ був живий.",{"q":438,"a":439},"Чи можу я обмежити ключ OpenAI своїм доменом, як обмежую ключ Google?","Ні. Ключ API Google приймає обмеження за HTTP-реферером, яке змушує його працювати на вашому сайті й відмовляти всюди інде, і саме тому ключ Google на вашій сторінці зазвичай нешкідливий. OpenAI не пропонує нічого рівноцінного. Для ключа API немає ані списку дозволених доменів, ані перевірки реферера, тож єдині важелі у вас є над обліковим записом позаду нього: до якого проєкту належить ключ, скільки цей проєкт може витратити і чи ключ узагалі ще існує.",{"q":441,"a":442},"У бібліотеці OpenAI є опція dangerouslyAllowBrowser. Чи робить вона ключ безпечним?","Ні, і назва є попередженням. OpenAI постачає підтримку браузера вимкненою, а власний README каже, що опція небезпечна, бо відкриває ваші секретні дані API в коді на боці клієнта. Її ввімкнення не змінює того, що може прочитати браузер; воно лише не дає бібліотеці відмовитися стартувати. Вузькі випадки, для яких вона задумана, це внутрішні інструменти з відомими користувачами та короткоживучі ключі для розробки, а не публічний застосунок.",{"q":444,"a":445},"Скільки хтось може витратити з ключем, який знайшов?","Стільки, скільки дозволяє ваш обліковий запис, і саме тому ліміт витрат важить більше за розмір рахунку, який ви вже бачили. Вкрадений ключ черпає з тих самих лімітів частоти, що й ваш застосунок, тож першим симптомом часто є зовсім не рахунок: ваш власний застосунок починає падати, поки хтось інший працює. Поставте місячний ліміт витрат на проєкт, і ви матимете стелю над усім цим.",{"q":447,"a":448},"Я користувався ключем лише для швидкої демонстрації. Це все одно має значення?","Так. Ключ лишається живим, доки хтось його не відкличе, і він не знає, що мав бути тимчасовим. Автоматичні скрапери безперервно збирають із публічних сторінок рядки у формі ключа, тож вік демонстрації працює проти вас, а не на вас. Видалити ключ забирає менше часу, ніж рішення про те, чи варто було його видаляти.","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcard-800x500.png",[451,452,453,454,129,455],"ключ api openai відкритий у фронтенді","сховати ключ api openai у react","безпечно викликати openai із фронтенду","безпека ключа api openai","ключ api openai витік",{},true,"Ключ API OpenAI відкритий у вашому фронтенді?","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","2026-09-03",{"title":5,"description":430},"blog\u002Fopenai-api-key-exposed-in-frontend",[464,465,466,467],"Ключ API OpenAI, відкритий у вашому фронтенді, є тим випадком, коли тривога має рацію. Жодне налаштування не робить такий ключ безпечним у браузері.","Це токен на пред’явника, тож достатньо просто мати його. Немає обмеження за доменом, яке прив’язало б його до вашого сайту, як воно є для ключа Google.","Замініть його сьогодні в панелі OpenAI, перенесіть виклик за власний ендпоінт і поставте ліміт витрат на проєкт.","Ми знайшли такий ключ у 33 із 30 998 просканованих застосунків. Рідко, і всі 33 вийшли з оцінкою D або F.","2026-09-21","2J-QTNIq7lACDyPrB-4KgcS-45x2-MB4gxvgUNigaXg",[471,478,484,489,495,501,507,513,519,525,531,537,543,549,555,561,567,573,579,585,591,592,597,603,609,615,621,627,633,639,645,651,657,662,668,674,679,685,691,697,702,708],{"path":472,"title":473,"description":474,"published":475,"category":476,"image":477,"draft":431},"\u002Fblog\u002Fsupabase-backup-auth-users","Чому у вашому дампі Supabase немає користувачів","Запустіть supabase db dump окремо і отримаєте форму вашої бази та жодного її рядка, без схеми auth, у якій живуть ваші користувачі.","2026-09-23","Backups","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":479,"title":480,"description":481,"published":482,"category":427,"image":483,"draft":431},"\u002Fblog\u002Fdomain-and-certificate-expiry","Домен закінчився, сайт лежить: що буде далі","Ваш домен закінчився і сайт лежить. Ось який годинник уже пішов, чому прострочений сертифікат це менша з двох бід, і як перевірити обидва.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":485,"title":486,"description":487,"published":468,"category":427,"image":488,"draft":431},"\u002Fblog\u002Fis-lovable-safe","Чи безпечний Lovable? Що показали 18 554 застосунки Lovable","Чи безпечний Lovable? Ми прогнали 18 554 живі застосунки Lovable через дев’ять перевірок. Платформа виявилася найчистішою з п’яти. Знахідки були в застосунках.","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":490,"title":491,"description":492,"published":493,"category":427,"image":494,"draft":431},"\u002Fblog\u002Fvibe-coded-app-security-checklist","Чек-лист безпеки для vibe coding, у девʼяти перевірках","Чек-лист безпеки для vibe coding із девʼяти пунктів, кожен з яких будь-хто може перевірити у вашому живому застосунку ззовні, і кожен має тест на один рядок.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":496,"title":497,"description":498,"published":499,"category":427,"image":500,"draft":431},"\u002Fblog\u002Fstripe-secret-key-in-frontend","Секретний ключ Stripe у фронтенді може рухати гроші","Секретний ключ Stripe, відкритий у вашому фронтенді, може повертати кошти, списувати й читати кожну картку клієнта. А ключ pk_live_ там і має бути.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":502,"title":503,"description":504,"published":505,"category":427,"image":506,"draft":431},"\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":508,"title":509,"description":510,"published":511,"category":427,"image":512,"draft":431},"\u002Fblog\u002Fbase44-source-maps","Безпека Base44: що позначає скан і що з цього виправляти вам","Безпека Base44 на 5 438 просканованих застосунках: три знахідки майже на кожному належать платформі, source map є бейджем Base44, а ваша частина коротка.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":514,"title":515,"description":516,"published":517,"category":427,"image":518,"draft":431},"\u002Fblog\u002Fis-cursor-ai-safe","Чи безпечний Cursor AI? Редактор, код і опублікований застосунок","Чи безпечний Cursor AI? Три запитання в одному пошуку: що Cursor зберігає, у чому помиляється його код і чи відкритий застосунок, який ви опублікували.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":520,"title":521,"description":522,"published":523,"category":427,"image":524,"draft":431},"\u002Fblog\u002Fis-replit-safe","Чи безпечний Replit? Що ми знайшли в 3 042 живих застосунках Replit","Чи безпечний Replit? Ми прогнали 3 042 живі застосунки Replit через дев’ять зовнішніх перевірок. Знахідки були в опублікованому застосунку, а не в хостингу.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":526,"title":527,"description":528,"published":529,"category":476,"image":530,"draft":431},"\u002Fblog\u002Fsupabase-storage-backup","Supabase storage backup: у копії бази даних немає жодного файлу","Supabase storage backup це окрема робота. Копії бази даних зберігають список ваших файлів і жодного з них, тож після відновлення кожне завантаження зламане.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":532,"title":533,"description":534,"published":535,"category":476,"image":536,"draft":431},"\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":538,"title":539,"description":540,"published":541,"category":476,"image":542,"draft":431},"\u002Fblog\u002Fsupabase-project-paused-recover","Проєкт Supabase на паузі? Ваші дані нікуди не зникли","Supabase поставив ваш проєкт на паузу після тижня без активності. Нічого не видалено, кнопка Restore стоїть поруч із назвою, і у вас є рік, щоб натиснути.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":544,"title":545,"description":546,"published":547,"category":427,"image":548,"draft":431},"\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":550,"title":551,"description":552,"published":553,"category":427,"image":554,"draft":431},"\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":556,"title":557,"description":558,"published":559,"category":427,"image":560,"draft":431},"\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":562,"title":563,"description":564,"published":565,"category":427,"image":566,"draft":431},"\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":568,"title":569,"description":570,"published":571,"category":427,"image":572,"draft":431},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Сканери безпеки для vibe coding у порівнянні, наш теж","Найкращий сканер безпеки для vibe coding залежить від трьох питань, на які не відповідає жоден перелік функцій. Десять інструментів і ціни.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":574,"title":575,"description":576,"published":577,"category":427,"image":578,"draft":431},"\u002Fblog\u002Fsupabase-security-checker","Supabase security checker: п’ять перевірок, які зробите самі","Supabase security checker читає ваш опублікований застосунок, а не налаштування проєкту. Ось п’ять перевірок і як виконати кожну самостійно.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":580,"title":581,"description":582,"published":583,"category":427,"image":584,"draft":431},"\u002Fblog\u002Fvibe-coding-security-scanner","Сканер безпеки для vibe coding: чого не бачить скан URL","Сканер безпеки для vibe coding читає ваш робочий застосунок ззовні. Що це охоплює, чотири речі, яких він не бачить, і як читати результат.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":586,"title":587,"description":588,"published":589,"category":427,"image":590,"draft":431},"\u002Fblog\u002Fmissing-security-headers","Відсутні заголовки безпеки: коли це справді важливо","Відсутні заголовки безпеки трапляються в наших звітах найчастіше. Від чого вони захищають і коли це найменш терміновий рядок вашого звіту.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":459,"title":5,"description":430,"published":460,"category":427,"image":449,"draft":431},{"path":411,"title":593,"description":594,"published":595,"category":427,"image":596,"draft":431},"Ключ 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":598,"title":599,"description":600,"published":601,"category":476,"image":602,"draft":431},"\u002Fblog\u002Fsupabase-backup-tools-compared","Інструменти резервного копіювання Supabase, і наш серед них","Чотири види інструментів резервного копіювання Supabase, що копіює кожен і коли безкоштовна GitHub Action виграє в будь-якої оплати, нашої теж.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":604,"title":605,"description":606,"published":607,"category":427,"image":608,"draft":431},"\u002Fblog\u002Freplit-secrets-explained","Як користуватися секретами в Replit і що все одно публікується","Як користуватися секретами в Replit: додати, прочитати і усунути дві причини undefined. А ще ключі, які цей інструмент не здатен зберегти в таємниці.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":610,"title":611,"description":612,"published":613,"category":476,"image":614,"draft":431},"\u002Fblog\u002Fback-up-supabase-free-tier","Резервні копії на безкоштовному тарифі Supabase без терміналу","На безкоштовному тарифі Supabase резервних копій немає: копію робите ви. Як зробити її з панелі та що втрачає шлях через CSV.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":616,"title":617,"description":618,"published":619,"category":427,"image":620,"draft":431},"\u002Fblog\u002Fis-supabase-secure","Чи безпечний Supabase? Так. Ваш проєкт це інше питання","Чи безпечний Supabase? Платформа проходить аудити, шифрує дані й тримає пентести. Їхня документація каже, де це закінчується і починаються ваші налаштування.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":622,"title":623,"description":624,"published":625,"category":427,"image":626,"draft":431},"\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":628,"title":629,"description":630,"published":631,"category":427,"image":632,"draft":431},"\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":634,"title":635,"description":636,"published":637,"category":427,"image":638,"draft":431},"\u002Fblog\u002Fcors-wildcard-security-risk","Чи є вайлдкард CORS ризиком для безпеки? Майже ніколи.","Чи є вайлдкард CORS ризиком для безпеки? Зазвичай це типове налаштування вашого білдера, і воно не видає нічого, що ваш сервер і так віддавав кожному.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":640,"title":641,"description":642,"published":643,"category":476,"image":644,"draft":431},"\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":646,"title":647,"description":648,"published":649,"category":476,"image":650,"draft":431},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","Як відновити резервну копію Supabase, і що ламається потім","Як відновити резервну копію Supabase з панелі або з файлу дампа, що саме замінює відновлення і чому ваш застосунок може лишитися зламаним після нього.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":652,"title":653,"description":654,"published":655,"category":427,"image":656,"draft":431},"\u002Fblog\u002Fsupabase-storage-bucket-public","Ваш бакет Supabase Storage публічний. Чи це проблема?","Публічний бакет Supabase Storage означає, що той, хто має URL файлу, може його відкрити. Він не означає, що хтось може переглянути список вмісту.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":111,"title":658,"description":659,"published":660,"category":427,"image":661,"draft":431},"Чи є проблемою ключ API Google у вашому браузері?","Ключ API Google у відкритому коді сторінки наш сканер знаходить найчастіше, і зазвичай усе гаразд. Вирішує це одне безкоштовне налаштування.","2026-08-22","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":663,"title":664,"description":665,"published":666,"category":476,"image":667,"draft":431},"\u002Fblog\u002Fai-agent-deleted-my-database","ШІ-агент видалив мої дані в Supabase. Що можна відновити?","ШІ-агент видалив дані з вашої бази. Те, що ви зможете відновити, вирішилося раніше, а наступні хвилини вирішують, скільки з цього вціліє.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":669,"title":670,"description":671,"published":672,"category":427,"image":673,"draft":431},"\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":675,"title":676,"description":677,"published":672,"category":427,"image":678,"draft":431},"\u002Fblog\u002Fsource-maps-exposed-in-production","Відкриті source maps: ваш застосунок публікує свій вихідний код","Відкрита source map дає будь-кому прочитати оригінальний код вашого застосунку, разом із коментарями. Перевірка за 30 секунд, і що важить насправді.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":680,"title":681,"description":682,"published":683,"category":427,"image":684,"draft":431},"\u002Fblog\u002Fsupabase-new-api-keys","Нові API-ключі Supabase: який із них безпечний у застосунку?","Supabase замінив anon і service_role публічними та секретними ключами. Який із них має бути у вашому застосунку, а який не має бути ніколи?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":686,"title":687,"description":688,"published":689,"category":476,"image":690,"draft":431},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","Чи робить Supabase резервні копії моєї бази? Залежить від тарифу.","Чи робить Supabase резервні копії вашої бази даних? На платних тарифах щодня, на безкоштовному жодної. Як дізнатися, що у вас насправді є.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":692,"title":693,"description":694,"published":695,"category":427,"image":696,"draft":431},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","Supabase Row Level Security увімкнено. Таблиця досі публічна.","Увімкнути Supabase Row Level Security не означає захистити таблицю. Захищають політики, а та, що полагодила застосунок, часто впускає всіх.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":698,"title":699,"description":700,"published":695,"category":476,"image":701,"draft":431},"\u002Fblog\u002Fversion-history-is-not-a-backup","Історія версій не є резервною копією. Вона не поверне таблицю.","Lovable і Bolt ведуть історію версій вашого коду. Ваша база даних працює як окремий сервіс, тож відкат назад не поверне ваші дані.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":703,"title":704,"description":705,"published":706,"category":476,"image":707,"draft":431},"\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":406,"title":709,"description":710,"published":706,"category":427,"image":711,"draft":431},"Які API-ключі безпечні у браузері, а які ні","Ваш ключ anon у Supabase створений, щоб бути публічним. Ключ service_role для цього не створений, і він ігнорує всі правила, які ви задали. Як їх розрізнити.","\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend\u002Fcard-800x500.png",1790150956951]