Перейти до вмісту

Основи безпеки

Чи є вайлдкард CORS ризиком для безпеки? Майже ніколи.

Чи є вайлдкард CORS ризиком для безпеки? Зазвичай це типове налаштування вашого білдера, і воно не видає нічого, що ваш сервер і так віддавав кожному.

Vlad Tkachenko8 хв читання
Шестеро різних відвідувачів дістаються одного сервера, і та сама відповідь повертається до кожного з них.

Коротко

  • Вайлдкард CORS стає ризиком для безпеки лише тоді, коли за ним відповідає щось приватне. Сам по собі він дозволяє читати те, що будь-хто й так міг завантажити.
  • Цей заголовок є вказівкою для браузера вашого відвідувача, і приходить він після того, як відповідь уже надіслано. Поза браузером його не читає ніхто, тож звуження заголовка лишає відкриту адресу так само відкритою.
  • Цілого вечора вартий інший випадок: сервер повертає луною той сайт, який саме питає, та ще й дозволяє облікові дані. Ось тоді чужа сторінка читає дані від імені вашого авторизованого користувача.

Ваше сканування повернулося з рядком, який читається як сигнал тривоги: ваш API відкритий для будь-якого сайту. Або хтось технічний подивився, що віддає ваш сервер, і сказав вам, що у вашому застосунку є вайлдкард CORS, тобто символ *, який, вочевидь, означає всіх.

Ось та частина, яку посібник за посібником переказують хибно: вайлдкард майже ніколи не є тим, що відкрило ваш API. Це вказівка, яку ваш сервер додає до своїх відповідей, адресована браузерам людей, що сидять на інших сайтах, і приходить вона тоді, коли відповідь уже пішла. Звуження заголовка не дає сторінці чужого сайту прочитати ваші дані. Проти того, хто читає їх узагалі без браузера, воно не робить нічого.

Чи є вайлдкард CORS ризиком для безпеки?

Сам по собі майже ніколи. Він стає ним тієї миті, коли за ним відповідає щось приватне.

Вайлдкард це значення * у заголовку відповіді на ім'я Access-Control-Allow-Origin, і воно означає, що код будь-якого сайту може прочитати саме цю відповідь. Звучить як твердження про те, хто може дістатися до ваших даних. Насправді це твердження про те, кому дозволено прочитати те, що ваш сервер уже надіслав.

Адреса, яку перевіряє сканування, це та, з якої віддається ваш застосунок. У більшості білдерів ця адреса роздає ваші сторінки, ваші зображення та ваш скомпільований код, і все це за задумом іде до кожного відвідувача. Вайлдкард на них дає дозвіл читати файли, які будь-хто вже міг завантажити, просто відкривши ваш сайт.

Тож знахідка є питанням, а не вироком, і питання полягає в тому, що стоїть за заголовком. Якщо відповідь це ваша головна сторінка, не сталося нічого. Якщо відповідь це список ваших клієнтів, той список уже був доступний кожному, хто мав адресу.

Що насправді робить Access-Control-Allow-Origin

Він каже браузеру вашого відвідувача, чи дозволено сторінці на екрані зазирнути у відповідь, яку ваш сервер уже надіслав.

Порядок і є всією суттю, і він протилежний до того, як його уявляє собі майже кожен. Сторінка на якомусь чужому сайті виконує шматок коду, що просить у вашого застосунку дані. Запит іде. Ваш сервер його отримує, виконує те, що має виконати, і повертає відповідь повністю. Аж потім браузер читає заголовок тієї відповіді й вирішує, чи передавати вміст сторінці, яка його просила. Посібник MDN про CORS вкладає це в один рядок: сервер має дати згоду через Access-Control-Allow-Origin, щоб поділитися відповіддю зі скриптом.

Ваші дані залишили будівлю в обох випадках. Заголовок вирішує лише те, чи побачить їх один конкретний шматок коду, що виконується в браузері однієї конкретної людини.

Обидва відвідувачі отримують відповідь, бо сервер надсилає її ще до того, як щось перевірять. Бар'єр у верхній смузі це браузер, а в нижній смузі браузера немає взагалі.

Браузер це єдине в цій історії, що читає заголовок. Скрипт на сервері, інструмент командного рядка, скрапер, мобільний застосунок: жоден із них до нього не заглядає, бо писали його для браузера, а браузера тут немає. Вони надсилають той самий запит, отримують ту саму відповідь і читають кожен її байт.

Звуження CORS не робить відкриту адресу приватною

Бо CORS живе всередині браузерів, а той, хто пригощається вашими даними, не має причин ним користуватися.

Це та частина, яка коштує людям пообіддя. Вони бачать знахідку про вайлдкард, звужують заголовок до власного домену, розгортають наново, скануються наново, а адреса, що роздавала рядки клієнтів, роздає рядки клієнтів і далі. Вона робила це завжди. Єдиний відвідувач, якого це коли-небудь спинило, це чужа вебсторінка.

Що хтось намагається зробитиВайлдкард *Лише ваш доменБудь-яке походження, повернене луною, з обліковими даними
Відкрити адресу у вкладці браузераПрацюєПрацюєПрацює
Прочитати її скриптом або з терміналаПрацюєПрацюєПрацює
Сторінка чужого сайту читає їїПрацюєЗаблокованоПрацює
Чужий сайт читає її як ваш авторизований користувачЗаблокованоЗаблокованоПрацює

Прочитайте останній рядок двічі, бо саме тут загальна порада розсипається. Звичайний вайлдкард не може бути використаний, щоб прочитати дані вашого авторизованого відвідувача. Браузери відмовляють такому поєднанню навідріз, і посібник MDN про CORS каже це прямо: якщо запит несе куку, а відповідь повертається з Access-Control-Allow-Origin: *, браузер блокує доступ до відповіді й показує помилку CORS у консолі. Тож саме вайлдкард, хоч як дивно, і робить цю конкретну атаку неможливою.

Стовпчик, який справді віддає дані авторизованого користувача, це третій, і для цього серверу треба вписати адресу самого відвідувача у власну відповідь.

Налаштування CORS, яке справді небезпечне

Сервер, що читає заголовок Origin із запиту, вписує те саме значення у власну відповідь і надсилає поруч Access-Control-Allow-Credentials: true.

Ніхто не береться за це навмисно. Воно з'являється наприкінці пообіддя, згаяного на спроби змусити вайлдкард працювати з авторизованими запитами, і на відкриття, що він ніколи не працюватиме. Повернути луною те походження, яке питало, здається виходом: кожен сайт, який має бути дозволений, дозволений, помилки в консолі припиняються, функція виходить у світ. Насправді сервер каже цим, що вирішує сам відвідувач, а до таких належить і сторінка, якої ще ніхто не написав.

Ось що це дозволяє. Ваша клієнтка увійшла у ваш застосунок, і в її браузері лежить кука сесії. В іншій вкладці вона відкриває сайт, що не має до вас жодного стосунку. Код того сайту просить у вашого API її обліковий запис. Її браузер додає куку, бо додавати куки це те, що браузери роблять. Ваш сервер читає Origin, про яке ніколи не чув, ставить його у відповідь як дозвіл і додає, що з обліковими даними все гаразд. Браузер перевіряє, знаходить збіг і передає дані вашої клієнтки сторінці, про яку вона не знала, що та їх читає.

Відвідувач сам подає ім'я, а сервер вписує це ім'я у перепустку. Хто питає, той і в списку, і саме цим цей випадок відрізняється від вайлдкарда.

У нашому скануванні за серпень 2026 таке трапилося в 61 з 30 926 застосунків, де перевірка змогла отримати відповідь. З трьох знахідок CORS це єдина, що дотягується до даних за входом у систему.

Як часто трапляється вайлдкард і хто це вирішує

Здебільшого вирішує ваш білдер. У тому самому скануванні 5 727 із тих 30 926 застосунків надсилали вайлдкард, і найкращий одиничний показник того, чи робить це ваш, це платформа, яка його опублікувала.

Перевірка CORS зафіксувала щонайменше одну знахідку в 5 418 із 5 419 застосунків Base44, де отримала відповідь, і у 8 із 18 518 застосунків Lovable. Replit опинився між ними з 1 129 із 3 037. Такий широкий розкид і є тим, як типове налаштування хостингу виглядає ззовні: майже суцільне на одній платформі, майже відсутнє на іншій, через тисячі застосунків, власники яких ніколи нічого між собою не узгоджували.

Три окремі знахідки складають перевірку CORS на всіх 30 926 застосунках: вайлдкард у 5 727 з них, адреса, що відповідає даними без входу, у 3 852, і повернене луною походження у 61. Разом виходить більше, ніж сама перевірка, бо чимало застосунків мають дві з трьох. Кожна цифра тут походить із нашого сканування 30 998 живих vibe-coded застосунків, яке публікує кожну разом із базою, на якій її виміряли.

Те, на що ви можете вплинути, ділиться так само. Вайлдкард надсилає той, хто віддає ваш застосунок, а для vibe-coded застосунку це зазвичай білдер. Що повертається, коли незнайомець просить дані в однієї з ваших адрес, вирішили всередині вашого застосунку, ви або білдер, що пише код від вашого імені.

Як перевірити власний застосунок

Дивитися треба на дві речі, і друга вирішує, чи має все це взагалі значення.

Чи надсилає ваш застосунок вайлдкард? Відкрийте свій застосунок у мережі, натисніть F12, щоб викликати інструменти розробника в браузері, натисніть Network і перезавантажте сторінку. Клацніть перший запит у списку й прочитайте панель Response Headers. Рядок access-control-allow-origin: * і є знахідкою. Якщо такого рядка немає зовсім, ваш сервер не ділиться нічим через межі походження ні з ким.

Що відповідає за ним? Лишайтеся у вкладці Network і перезавантажте свій застосунок, поки ви в системі, стежачи за запитами, що повертаються як JSON. Це й є адреси, з яких ваш застосунок бере дані. Скопіюйте кожне посилання, відкрийте вікно приватного перегляду, щоб бути невходженим, і вставляйте їх по одному. Усе, що повертається зі справжніми рядками замість помилки чи порожнього списку, доступне для читання кожному в інтернеті, хто має те посилання. Це правда сьогодні, хоч би що казав ваш заголовок CORS, і лишається правдою після того, як ви його звузите.

Наше безкоштовне сканування виконує другу перевірку за вас: читає код вашого застосунку в пошуках адрес, які він викликає, звертається до кожної без входу і повідомляє ті, що відповіли даними. Це триває приблизно 20 секунд і не потребує облікового запису: скануйте свій застосунок.

Якщо ваш застосунок говорить із Supabase просто з браузера, є третє місце, куди варто заглянути, бо правила на кожній таблиці вирішують, кому які рядки читати, і увімкнути їх не те саме, що бути захищеним.

Що робити просто зараз

Що робити

  • Сприймайте знахідку про вайлдкард як питання про те, що стоїть за заголовком. На адресі, з якої віддається ваш застосунок, він зазвичай дозволяє читати файли, які кожен відвідувач завантажує й так.
  • Вийдіть із системи й відкрийте кожну адресу даних, яку викликає ваш застосунок. Усе, що повертає справжні рядки браузеру без входу, є публічним для всіх, хоч би що казав заголовок.
  • Виправляйте відкриту адресу на самій адресі: вимагайте входу і відповідайте незнайомцеві кодом 401. Звуження заголовка CORS лишає її доступною для всього, крім чужих вебсторінок.
  • Якщо ваш сервер повертає луною те походження, яке питало, і надсилає Access-Control-Allow-Credentials: true, замініть це сьогодні списком власних доменів. Це єдиний випадок тут, коли чужий сайт читає дані від імені вашого авторизованого користувача.
  • Якщо заголовок надходить від хостингу вашого білдера і змінити його ви не можете, витратьте цей час на адреси. Саме там лежать ваші дані.

Звичка, яку варто тримати, це прохід без входу по власних адресах даних, бо кожна нова функція додає ще одну, а на екрані нічого не змінюється, коли якась із них починає відповідати. Reeve Care запускає це саме сканування проти вашого застосунку в мережі за розкладом і пише вам, коли результат гіршає: за чим воно стежить і скільки коштує.

Якщо ви радше розберетеся з усім за один раз, 10-хвилинний контрольний список безпеки охоплює це поряд із рештою того, що свіжозапущений застосунок схильний лишати відкритим, а які ключі безпечні у вашому фронтенді це друга половина питання, з яким люди зазвичай приходять.

Поширені запитання

Сканування каже, що мій API відкритий для будь-якого сайту. Чи треба це виправляти?

Спершу подивіться, що відповідає за ним. Вайлдкард на адресі, з якої віддається ваш застосунок, зазвичай дозволяє читати ваші сторінки, зображення та скомпільований код, а все це кожен відвідувач завантажує й так. Виправляти треба тоді, коли адреса за цим заголовком віддає справжні дані тому, хто не увійшов у систему, і виправляти саме на тій адресі, вимагаючи входу.

Чи стане мій API приватним, якщо звузити CORS до власного домену?

Ні. CORS це правило, яке браузери застосовують самі до себе, тож воно стосується лише коду, що виконується на чужій вебсторінці. Скрипт, команда в терміналі чи скрапер надішлють той самий запит і прочитають ту саму відповідь, бо жоден із них не дивиться на заголовок. Якщо адреса віддає ваші дані без входу, вона робить це для всіх, хоч би що казав заголовок.

Чи може чужий сайт прочитати дані моїх авторизованих користувачів через вайлдкард?

Через звичайний вайлдкард ні. Браузери відмовляють такому поєднанню: посібник MDN про CORS зазначає, що коли запит несе куку, а відповідь повертається з Access-Control-Allow-Origin у значенні вайлдкарда, браузер блокує доступ до відповіді й записує помилку CORS. Працює натомість інший варіант: сервер повертає луною те походження, яке питало, разом із Access-Control-Allow-Credentials у значенні true.

Як змінити заголовок CORS у застосунку на Lovable чи Base44?

Часто ніяк, бо заголовок надсилає хостинг, на який публікує ваш білдер, і діє він для кожного застосунку на тій платформі. Це варто знати, перш ніж витрачати на нього тиждень. Що ви завжди можете змінити, так це те, що ваші власні адреси віддають на запит без входу, і саме туди виправлення й належить.

Сканування також позначило відкриті адреси API. Чи це те саме?

Це інше, і серйозніше з двох. Вайлдкард описує, кому дозволено читати відповідь. Відкрита адреса означає, що відповідь містила ваші дані й прийшла без того, щоб хтось увійшов у систему. Друге однаково правдиве для браузера, для скрипта і для незнайомця з посиланням, і звуження заголовка CORS не змінює в цьому нічого.

Автор

Vlad Tkachenko

Засновник Reeve

Я щодня дивлюся на застосунки, зібрані в Lovable, Bolt, v0, Cursor і Replit, і на короткий список помилок, які трапляються в них знову і знову.

Більше про автора

Читати далі

Не впевнені, як справи у вашому застосунку?

Запустіть безкоштовне сканування й отримайте зрозумілу оцінку від A до F приблизно за 20 секунд. Без облікового запису й без картки.

Сканувати безкоштовно

Автоматична зовнішня перевірка, а не повний аудит. Відсутність знахідок не є гарантією безпеки.