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

Коротко
- Відсутні заголовки безпеки це найпоширеніший висновок узагалі, і сам собою він майже нічого не каже про те, чи може хтось дістатися ваших даних.
- Ми просканували 30 998 робочих застосунків. У двох із трьох, яким бракувало заголовків, більше не було нічого поганого взагалі.
- Виправити їх усе одно варто, і черга на це настає після речей, які вирішують, хто може читати вашу базу даних.
- На деяких доменах білдерів ви не можете задати їх самі, і залишити все як є цілком розумна відповідь.
Ваш скан повертається, і майже всі рядки зелені. Один бурштиновий: бракує кількох заголовків безпеки браузера. Це єдине кольорове на сторінці, тож виглядає як те, чим треба зайнятися першим.
Ось та частина, яку більшість порад на цю тему подає неправильно. Відсутні заголовки безпеки це висновок, який ми друкуємо найчастіше, і сам собою він майже нічого вам не каже про те, чи може хтось дістатися ваших даних. Ставитися до нього як до злому означає або кинутися виправляти його попереду речей, які справді вирішують, хто читає вашу базу даних, або звикнути, що бурштинові рядки це шум, а це гірше.
Між 12 і 14 серпня 2026 року ми прогнали ті самі дев’ять зовнішніх перевірок на 30 998 робочих застосунках, зроблених у Lovable, Bolt, v0, Replit і Base44. Серед застосунків, від яких ця перевірка отримала відповідь, 30 756 із 30 981 бракувало щонайменше одного заголовка. Повні числа є в нашому звіті про сканування.
Чи є відсутні заголовки безпеки проблемою?
Це справжня прогалина і майже завжди найменш терміновий рядок вашого звіту.
Заголовок безпеки це коротка вказівка, яку ваш сервер додає до кожної сторінки, що надсилає, і адресована вона браузеру відвідувача, а не самому відвідувачу. Не дозволяй іншому сайту вставляти цю сторінку в рамку. Не вгадуй, що це за тип файлу. Не передавай мою повну адресу, коли хтось клікає кудись назовні. Це записки помічникові, який робить те, що йому каже будь-який сайт.
Решта вашого звіту про замки. Чи ввімкнено Row Level Security, чи лежить секретний ключ у вашому коді, чи показує сховище свій вміст: саме це вирішує, хто взагалі дістанеться ваших даних. Записки й замки хочеться мати обидва, і записка, якої ви ніколи не написали, не є причиною, через яку люди втрачають базу даних.
Наша оцінка ставиться до цього так само. Відсутній заголовок знімає п’ять балів зі ста й не ставить жодної стелі, тож застосунок, чий єдиний висновок саме цей, виходить із 95 і оцінкою A.
Що ми знайшли в 30 998 застосунках
Відсутні заголовки траплялися майже скрізь і майже не рухалися разом з рештою звіту.
25 821 із цих застосунків отримали відповідь від усіх дев’яти перевірок, і саме в цій групі «більше нічого поганого» щось означає. Серед них 25 606 бракувало щонайменше одного заголовка, а 215 мали всі п’ять.
Із 25 606 застосунків, яким бракувало щонайменше одного заголовка, у 17 043 більше не було нічого поганого взагалі. Двоє з трьох. Це була єдина проблема в їхньому звіті.
Тепер прочитайте інший рядок, і це та частина, яка нас здивувала. Із 215 застосунків, що мали всі п’ять заголовків, у 145 було щось інше не так. Це вища частка справжніх проблем, ніж серед застосунків без заголовків, а не нижча.
Ми не вимірювали, чому, і чесне прочитання тут вузьке: хоч би що ці сканування знайшли ще, висновок про заголовки цього не передбачив. Застосунок із бездоганним набором заголовків у наших даних не був безпечнішим застосунком. Найімовірніше пояснення таке: якщо заголовки взагалі задано, значить, хтось налаштував справжній хостинг, а це зазвичай означає більший застосунок, у якому більше місця для помилки. Але це здогад, і ми його не перевіряли.
Якщо хочете побачити, які з цих рядків видає ваш власний застосунок, скан безкоштовний, триває близько 20 секунд і не потребує облікового запису: просканувати застосунок.
Що насправді робить кожен заголовок
Кожен вимикає поведінку браузера, яка типово ввімкнена.
| Заголовок | Що він каже браузеру | Що дозволяє його відсутність |
|---|---|---|
Content-Security-Policy | З яких місць ця сторінка може завантажувати код і стилі | Впроваджений скрипт може надіслати дані куди завгодно |
Strict-Transport-Security | Повертайся завжди через HTTPS, ніколи через звичайний HTTP | Візит у ненадійній мережі можна опустити до звичайного HTTP |
X-Frame-Options | Не дозволяй іншому сайту показувати цю сторінку в рамці | Вашу сторінку можна непомітно завантажити всередині чужої |
X-Content-Type-Options | Довіряй типу файлу, який я дав, і не вгадуй його за вмістом | Завантажений кимось файл може віддаватися як зовсім інший тип файлу |
Referrer-Policy | Скільки з цієї адреси передавати, коли відвідувач клікає кудись назовні | Повні URL, разом із усім, що в них є, потрапляють на чужі сервери |
Два з них перетинаються, і сканер це враховує. Content-Security-Policy, яка
містить frame-ancestors, виконує ту саму роботу, що й X-Frame-Options, тож
наша перевірка зараховує будь-який з двох і не вимагає обох.
Коли відсутній заголовок і є всією проблемою
Коли у вашому застосунку є на що варто натиснути, поки людина в системі.
Це випадок клікджекінгу, і він єдиний працює без жодної іншої помилки. Хтось завантажує ваш застосунок у невидиму рамку на сторінці, яку контролює, і кладе власні кнопки поверх ваших, тож відвідувач, який уже увійшов, натискає те, що має вигляд його сторінки, і влучає у ваш елемент керування: кнопку, що видаляє обліковий запис, підтверджує переказ або змінює адресу пошти.
Відвідувач у системі, тож дія несе його сесію. Ніщо у вашій базі даних не мусить бути налаштоване неправильно. Спрацьовує це тому, що браузеру ніколи не сказали відмовляти.
У Referrer-Policy є менша версія тієї самої форми. Якщо якась ваша сторінка
під сесією несе в URL щось ідентифікаційне й посилається на хостинг зображень
або скрипт аналітики, уся адреса подорожує разом із кліком. Той, хто тримає той
інший сервер, бачить, де був ваш користувач.
Решта три умовні. Вони важать, коли щось інше вже пішло не так, і їхня робота
тримати це малим. Content-Security-Policy обмежує, що впроваджений скрипт може
зробити зі своїм доступом. X-Content-Type-Options важить, якщо сторонні можуть
завантажувати вам файли. Strict-Transport-Security прикриває того, хто
користується вашим застосунком у мережі, яку не контролює.
Чи потрібні мені заголовки безпеки?
Так. Вони дешеві, і черга на них настає після висновків, які вирішують, хто може читати вашу базу даних.
Порядок, що випливає з вимірювання вище: спершу все критичне або високе у вашому звіті, заголовки потім. Якщо у вашому звіті стоїть лише цей рядок, як це було в 17 043 просканованих нами застосунків, тоді заголовки очолюють ваш список самі собою.
Два з п’яти нічого не коштують. X-Content-Type-Options: nosniff і
Referrer-Policy: strict-origin-when-cross-origin це по одному рядку, у них
немає неправильного значення на вибір і вони не здатні зламати робочий
застосунок. X-Frame-Options: DENY теж один рядок, і на нього варто глянути
раніше, якщо ви навмисно вбудовуєте власний застосунок деінде.
Content-Security-Policy це той, що вимагає справжньої роботи. Перша спроба
зазвичай блокує щось потрібне вашій же сторінці, а симптом це функція, яка
мовчки перестає працювати. Викотіть її як
Content-Security-Policy-Report-Only, яка каже, що вона заблокувала б, нічого
не блокуючи, і прочитайте тиждень звітів, перш ніж вмикати.
Як їх додати
У тому, що насправді віддає ваш застосунок в інтернет, а це часто не те місце, де ви його будуєте.
Більшість білдерів розгортає на хостинг, якому належить відповідь, тож
налаштування живе там. У Vercel це headers у vercel.json. У Netlify та
Cloudflare Pages це файл _headers у корені того, що ви публікуєте. За проксі
Cloudflare це Transform Rule. Якщо ви тримаєте власний сервер, це ваша
конфігурація nginx або Caddy.
Що варто знати про заголовки, коли їх уже задано: вони зникають без того, щоб хтось їх чіпав. Перехід на власний домен, проксі попереду, зміна хостингу, зміна конфігурації фреймворка: додані вами заголовки живуть в одному з цих місць, і будь-який із цих кроків може лишити їх позаду. Ніщо вам про це не скаже. Сторінка працює далі, а налаштування вже немає.
Саме для такого існує Reeve Monitor. Він переганяє повну перевірку щогодини на не більше ніж трьох застосунках, стежить за доступністю кожні 60 секунд і повідомляє вам, коли результат змінюється, замість чекати, поки ви подивитеся. Monitor лише стежить, тож якщо ви хочете ще й копію своєї бази даних там, куди ваш білдер не дістане, це Care, і він охоплює Supabase.
Що зробити просто зараз
Що робити
- Спершу прочитайте решту звіту. Якщо там щось позначено критичним або високим, робота саме там, а заголовки почекають.
- Додайте сьогодні
X-Content-Type-Options: nosniffіReferrer-Policy: strict-origin-when-cross-origin. По одному рядку, нічого вирішувати, нічого ламати. - Додайте
X-Frame-Options: DENY, якщо люди входять у ваш застосунок і можуть одним кліком зробити щось вагоме. - Лишіть
Content-Security-Policyнаостанок і запустіть у режимі report-only, щоб дізнатися, що вона ламає, раніше за ваших відвідувачів. - Якщо ви на піддомені білдера без налаштування заголовків, лишіть цей висновок у спокої. Він поки не ваш.
- Перевірте їх ще раз після зміни домену, додавання проксі чи переїзду на інший хостинг. Саме тоді вони зникають.
Заголовки варті спокійного пообіддя, коли решта звіту вже чиста. Якщо ви радше пройдете весь список по порядку, 10-хвилинний чекліст безпеки охоплює те, що варто вимкнути у щойно запущеному застосунку, а висновки, які справді вирішують, хто читає вашу базу даних, це те, що треба прибрати першим.
Поширені запитання
Скан каже, що бракує заголовків безпеки. Мій застосунок зламали?
Ні. Відсутній заголовок це налаштування, яке ніколи не вмикали, і він не є доказом, що щось сталося. У цьому висновку немає нікого, хто дістався ваших даних чи вашого облікового запису. Він описує вказівку, яку ваш сайт міг би давати браузерам відвідувачів і зараз не дає.
Який заголовок безпеки додати першим?
X-Content-Type-Options і Referrer-Policy, бо обидва це один рядок, у жодного немає неправильного значення на вибір і жоден не здатен зламати робочий застосунок. Далі X-Frame-Options, якщо люди входять у ваш застосунок. Далі Strict-Transport-Security. Content-Security-Policy останнім, бо це єдиний із п’яти, який вимагає справжнього обдумування, і єдиний, який може не дати виконуватися вашим власним скриптам.
Я на стандартному домені свого білдера, і налаштування заголовків там немає. Що тепер?
Залиште їх. Коли ваш застосунок віддається з піддомену платформи, заголовки відповіді це вибір платформи, а не ваш, і немає файлу, який ви могли б додати, щоб їх змінити. Підключіть власний домен, якщо хочете цим керувати, бо саме домен дає змогу поставити перед застосунком свій хостинг або проксі. А доти витрачайте зусилля на висновки, які виправляти саме вам.
Чи може Content-Security-Policy зламати мій застосунок?
Може, і це звичайний результат першої спроби. Політика, яка не дозволяє вбудовані скрипти, зупинить вбудовані скрипти, зокрема й ті, що згенерував ваш білдер, і сторінка залишиться порожньою або втратить функцію, а помилка буде видна лише в консолі браузера. Почніть із Content-Security-Policy-Report-Only, яка повідомляє, що вона заблокувала б, і не блокує нічого, і тиждень читайте ці звіти, перш ніж вмикати її по-справжньому.
Чи допоможуть заголовки безпеки, якщо мою базу даних може читати будь-хто?
Ні. Заголовки це вказівки браузерам, які відвідують ваш сайт, а той, хто читає вашу базу даних напряму, не користується браузером і не заходить на ваш сайт. Цей запит іде просто до вашого постачальника бази даних і ніколи не торкається ваших сторінок, тож жоден заголовок на них до нього не застосовується. Це вирішує Row Level Security.