Довідник помилок / Refused to display in a frame (X-Frame-Options)

Помилка Refused to display in a frame (X-Frame-Options)

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

Перевірте свій сайт

>

Через що виникає

Найчастіше вбудовуваний сайт просто ставить X-Frame-Options: deny (вбудовувати не можна нікому) або sameorigin (можна лише сторінкам того самого домену), і це стандарт для банків, Google, більшості SaaS-панелей та багатьох конфігів безпеки WordPress чи nginx. Далі за поширеністю - Content-Security-Policy з директивою frame-ancestors, яка робить те саме і в усіх сучасних браузерах перекриває X-Frame-Options, коли присутні обидва заголовки, тому сайт може виглядати дозвільним в одному заголовку і все одно блокувати вас іншим. Часта помилка на своєму ж боці: ваш сервер, плагін безпеки чи реверс-проксі додає sameorigin на весь сайт, і власне вбудовування ламається щойно фрейм віддається з іншого піддомену, порту чи протоколу. Ще один типовий випадок - успадкований X-Frame-Options: allow-from https://example.com, який жоден сучасний браузер не підтримує, тож він або нічого не робить, або вважається невалідним, і вбудовування лишається заблокованим.

Як виправити

  1. Запустіть перевірку security-заголовків на цій сторінці саме для того URL, який ви вбудовуєте, а не для своєї сторінки, і подивіться на дві речі: значення X-Frame-Options і чи є frame-ancestors у списку директив Content-Security-Policy. Якщо frame-ancestors є, саме це правило застосовує браузер, а X-Frame-Options ігнорується; якщо його немає, вирішує X-Frame-Options, де deny блокує всіх, а sameorigin - усіх, крім самого цього сайту.
  2. Якщо перевірка показала frame-ancestors, відкрийте девтулзи браузера, вкладку Network, клацніть запит фрейма і прочитайте повне значення Content-Security-Policy у Response Headers, щоб побачити дозволений список. 'none' блокує всіх, 'self' дозволяє лише самому сайту, а явний перелік дозволяє рівно ці джерела з точним збігом протоколу і порту, тож https://app.example.com не покриває ні http://, ні інший порт, ні інший піддомен.
  3. Якщо вбудовуваний сайт ваш, послаблюйте політику свідомо, а не видаляйте її: надсилайте Content-Security-Policy: frame-ancestors 'self' https://your-app.example.com і перелічіть усі джерела, яким дозволено вбудовування, а потім узгодьте або приберіть X-Frame-Options, щоб заголовки не суперечили один одному. Якщо просто видалити обидва, ви знову відкриєте кожну сторінку цього сайту для клікджекінгу.
  4. Приберіть будь-який успадкований зі старих інструкцій X-Frame-Options: allow-from ... . Він працював лише в Internet Explorer і старих збірках Firefox, сучасні браузери його ігнорують або вважають заголовок невалідним, і єдиний спосіб дозволити конкретні джерела сьогодні - frame-ancestors.
  5. Задеплойте зміни, очистіть кеш CDN і сторінок, зробіть жорстке перезавантаження і знову запустіть перевірку для того самого URL: заголовки часто кешуються, а другий X-Frame-Options від проксі, плагіна безпеки чи add_header у nginx може стояти попереду вашої нової політики. У результаті має зʼявитися саме ваше значення, і лише після цього є сенс перевіряти сам iframe.
  6. Якщо сайт не ваш, прийміть, що обходу на боці клієнта не існує: ні атрибут sandbox, ні скрипт, ні проксі, що зрізає заголовок, не є нормальним рішенням, бо цей заголовок - рішення власника не бути вбудованим, а проксі-трюки ламають авторизацію і зазвичай порушують умови користування. Використайте офіційний код вбудовування, публічний API або oEmbed, покажіть посилання з превʼю-карткою чи попросіть власника додати ваше джерело до його frame-ancestors.

Схожі помилки