---
title: "Безопасное встраивание ссылок в Blok"
description: "Что Blok проверяет, когда встраивает ссылку, и какие заголовки CSP, COOP и Permissions-Policy должно слать ваше приложение."
source: https://blokeditor.com/ru/docs/embed-safety/
lastmod: 2026-11-05
---

Фреймворк JavaScript

Расширение и система Безопасное встраивание

# Безопасное встраивание любых ссылок

Что Blok проверяет, когда встраивает ссылку, и какие заголовки должно слать ваше приложение.

Обновлено 5 нояб. 2026 г. [Редактировать на GitHub](https://github.com/JackUait/blok/blob/main/docs/src/components/api/EmbedSafetyContent.tsx)

## Что проверяет Blok

Blok встраивает только ссылки, которым доверяет, и даёт каждому фрейму как можно меньше прав.

- Провайдеры из реестра, например YouTube и Figma, получают sandbox провайдера и `referrerpolicy="strict-origin-when-cross-origin"`.
- Общему эмбеду нужен `linkPaste.allowGenericEmbed` или подходящая запись в `allowedEmbedOrigins`.
  - Его источник должен быть абсолютным URL `https://`. Формы вроде `https:/x` или `https:x.com` отклоняются, потому что браузер прочитал бы их относительно вашей страницы.
  - Blok сохраняет каноническую форму, поэтому `https://Example.com` сохраняется как `https://example.com/`.
  - Он получает `sandbox="allow-scripts allow-forms allow-popups"`, без списка `allow`, без referrer и с `credentialless` (только Chrome).
  - По умолчанию он загружается только после клика читателя.
- Общий эмбед никогда не встраивает ваш собственный сайт. Хост страницы, `hostAliases`, их поддомены и родительские домены получают карточку ссылки.
- `blockedEmbedOrigins` сильнее обеих настроек разрешения.
- Headless-рендер встраивает только эмбеды из реестра. После `transformUrl` src фрейма должен остаться абсолютным https, иначе рендер выводит ссылку.

Инструмент файла встраивает только PDF по `blob:`, с новым типом `application/pdf`. Удалённый PDF по http(s) вместо этого получает ссылку «Открыть в новой вкладке».

Без загрузчика каждый `blob:` URL, который создаёт Blok, получает безопасный тип. Любой тип вне короткого списка безопасных становится `text/plain`, в том числе HTML, XML, zip, файлы Office и файлы без типа. Изображение SVG вообще не становится blob. Настоящий тип файла читайте из `mimeType` блока.

Без загрузчика изображение SVG сохраняется как URL `data:image/svg+xml`. Открытый в отдельной вкладке blob с SVG выполняет свой скрипт от имени вашего сайта, а data: URL нет.

- Blok показывает URL `data:image/svg+xml` только как источник изображения: в `<img>` в редакторе и в headless-рендере.
- Ссылки, скачивание, фреймы и CSS по-прежнему его отклоняют.
- SVG больше 256 КБ вместо этого становится blob с типом `text/plain`, поэтому изображение не показывается. Для больших SVG задайте загрузчик.

Страница внутри фрейма эмбеда не может сама забрать фокус клавиатуры.

- Если фокус уходит во фрейм без клика, касания или Tab от читателя, Blok возвращает фокус и курсор на место.
- После касания защита отключается, поэтому касание поля внутри эмбеда по-прежнему работает.
- В Firefox фрейм, который забирает фокус, пока страница ещё загружается, всё ещё может получить несколько нажатий клавиш до клика читателя.

Сохранённый размер фрейма остаётся в границах. Его высота лежит в пределах от 0,1 до 4 ширин. Ширина или высота, которая не является положительным числом, заменяется размером по умолчанию 580×320.

`blocksToHtml` и `blocksToMarkdown` доверяют сохранённому эмбеду только в меру его URL.

- Эмбед, экспортированный как ссылка, берёт сохранённое имя сервиса как текст, только если исходный URL подходит этому провайдеру из реестра. Иначе текстом становится URL.
- В `blocksToHtml` плеер сохраняет более свободный sandbox плеера, только если `transformUrl` оставляет origin провайдера. Иначе он получает sandbox общего эмбеда.

Всё остальное в этом руководстве делает ваше приложение. Blok это библиотека, поэтому он не может слать заголовки для ваших страниц.

## Ограничьте фреймы через CSP

Шлите `Content-Security-Policy` с директивой `frame-src`. Браузер проверяет её для каждого фрейма на странице, поэтому она работает, даже если в проверке Blok есть ошибка.

- Чтобы пускать любой https-сайт, как `allowGenericEmbed`, укажите `frame-src https:`.
- Чтобы пускать только некоторые сайты, перечислите их. Сверьте список с `allowedEmbedOrigins` и провайдерами реестра, которыми пользуетесь.
- Встроенный просмотр PDF встраивает `blob:` URL и читает его через `fetch`. Строгой политике может понадобиться `blob:` в `frame-src` и `connect-src`. Мы это не измеряли.

## Не пускайте свои страницы во фреймы

Шлите `frame-ancestors 'self'` или `frame-ancestors 'none'` на своих страницах, например настроек и доступа. Тогда чужой сайт не сможет встроить их и обманом заставить читателя кликнуть.

В общем эмбеде Blok отказывается встраивать ваш хост, его псевдонимы, их поддомены и родительские домены. Соседний поддомен он не ловит, например `cdn.example.com` рядом с `app.example.com`. Для этого нужен список публичных суффиксов. Перечислите такие хосты в `hostAliases` или `blockedEmbedOrigins`.

Списки хостов и проверка своего сайта ловят ещё две редкие формы адреса.

- Адрес IPv4, записанный как IPv6, например `[::ffff:10.0.0.1]`, совпадает с записями IPv4 в `allowedEmbedOrigins`, `blockedEmbedOrigins` и `hostAliases`. Проверка своего сайта тоже его узнаёт.
- Если редактор работает в документе без имени хоста, например `blob:`, `about:srcdoc` или `about:blank`, Blok берёт хост из origin документа.

## Разорвите связь с всплывающими окнами через COOP

Встроенная страница может открыть всплывающее окно. `allow-popups-to-escape-sandbox` сохраняют только видео- и аудиоплееры из реестра, например YouTube, Vimeo и Spotify. Кнопке YouTube «Watch on YouTube» нужна вкладка без sandbox.

Эмбеды кода, документов и соцсетей, например CodePen, Figma, Google Docs и посты, его не получают. Общий эмбед тоже. Их окна сохраняют sandbox фрейма, поэтому некоторые страницы провайдеров могут в них не загрузиться.

Окно, вышедшее из sandbox, это обычная страница встроенного сайта. В Firefox оно смогло увести вкладку редактора на другой адрес через `window.opener.top`. Chrome и WebKit это запретили.

Шлите `Cross-Origin-Opener-Policy: same-origin` на странице с редактором. Он по-прежнему нужен для плееров, чьи окна выходят из sandbox. Тогда у окна не было `window.opener`, и вкладка оставалась на месте во всех трёх браузерах. `same-origin-allow-popups` не помог: в Firefox окно всё равно увело вкладку.

`same-origin` может сломать и окна, которые ваше приложение открывает на других сайтах и с которыми говорит через `window.opener`, например окно входа. Проверьте такие сценарии перед включением.

## Ограничьте опасные возможности

Общий эмбед не получает списка `allow`, поэтому у него нет камеры, микрофона, геолокации и платежей. Эмбед из реестра получает только `encrypted-media`, `fullscreen` и `picture-in-picture`.

Чтобы ограничить всю страницу, шлите заголовок `Permissions-Policy`. Каждой возможности, которой ваше приложение не пользуется, дайте пустой список:

- `camera=(), microphone=(), geolocation=(), payment=(), usb=()`

По данным о совместимости браузеров этот заголовок соблюдает только Chrome. Firefox и Safari его не знают, поэтому главным рычагом остаётся атрибут `allow`. Мы это не измеряли.

## Отдавайте файлы пользователей с другого сайта

Загруженный HTML- или SVG-файл выполняет скрипт от имени сайта, который его отдаёт. На хосте вашего приложения он ведёт себя как одна из ваших страниц. Отдавайте загрузки с отдельного хоста, например с собственного адреса бакета S3.

Отдельный сайт надёжнее поддомена вашего приложения, потому что для кук `SameSite` браузеры считают поддомены одним сайтом. Если берёте поддомен, перечислите его в `hostAliases` или `blockedEmbedOrigins`, чтобы он никогда не получил общий эмбед.

У `blob:` URL тоже origin вашей страницы. Blok меняет тип у blob, которые создаёт сам, но `blob:` URL из вашего загрузчика сохраняет тот тип, который вы дали. Оставляйте только безопасные типы: изображения, видео mp4 и webm, обычное аудио, PDF и простой текст. Всё остальное, включая zip, Office и octet-stream, переводите в `text/plain` до вызова `URL.createObjectURL`.

SVG в `blob:` URL тоже не оставляйте, даже для `<img>`. Читатель может открыть изображение в отдельной вкладке, и тогда SVG выполняется от имени вашего сайта. Отдавайте SVG с отдельного сайта или берите URL `data:image/svg+xml`, как делает Blok.

## Проверьте ссылку до встраивания

Многие сайты запрещают встраивать себя, и читатель видит пустой фрейм. Ваш бэкенд может узнать это заранее. Передайте `linkPaste.checkEmbed` или задайте `server`, и Blok вызовет `GET /frame-check` сервера.

- `blocked` или `insecure` вставляет вместо эмбеда закладку с коротким уведомлением.
- `allowed`, `unknown`, ошибка или отсутствие ответа за 3 секунды вставляет эмбед.

Вердикт это подсказка для интерфейса, а не проверка безопасности. Он не отменяет ни одного другого правила. Браузер всё равно соблюдает `X-Frame-Options` и `frame-ancestors` встроенного сайта.

## Что мы измерили

Результаты про окна и PDF выше получены 3 ноября 2026 года на локальном тестовом сервере. Браузеры: Chrome 156 и собственные сборки Playwright для Firefox 146 и WebKit 26. Эти две сборки изменены, поэтому обычные Firefox и Safari могут вести себя иначе.

- Фрейм с sandbox без `allow-popups-to-escape-sandbox` открывал окна, которые сохраняли sandbox. Они не смогли увести вкладку редактора ни в одном браузере.
- С этим токеном окно в Firefox увело вкладку редактора. `same-origin-allow-popups` это не остановил. С `same-origin` у окна не было `window.opener` во всех трёх браузерах.
- HTML-страница во фрейме без sandbox выполнила свой скрипт и смогла увести вкладку редактора. Адрес на `.pdf` ничего не доказывает, решает `Content-Type` сервера.
- Blob с типом `text/html`, открытый в новой вкладке, работал от имени создавшей его страницы, даже с `rel="noopener"`.
- Blob с типом `image/svg+xml`, открытый в новой вкладке, выполнил свой скрипт от имени создавшей его страницы и прочитал её хранилище. Тот же SVG как data: URL показался в `<img>` во всех трёх браузерах. Во вкладке он не открылся или работал с origin `null` и без хранилища.
- Chrome блокирует свой просмотрщик PDF в любом фрейме с sandbox, включая `sandbox=""`. Поэтому удалённые PDF открываются в новой вкладке.
