Content Security Policy

Content Security Policy (CSP) — это механизм безопасности, который позволяет ограничивать источники контента, загружаемого и исполняемого на веб-странице. Для библиотек, работающих с динамическим DOM, таких как Tippy.js, CSP может создавать сложности, так как тултипы генерируются через JavaScript и часто содержат динамический HTML.

Влияние CSP на работу Tippy.js

Tippy.js создаёт тултипы путём добавления элементов в DOM и их стилизации через JavaScript. Основные моменты, на которые CSP влияет:

  1. Inline-скрипты и обработчики событий Tippy.js использует inline-функции для инициализации и управления тултипами. CSP с директивой script-src 'self' запрещает inline-скрипты, что может блокировать работу Tippy.js без дополнительных настроек.

  2. Inline-стили Tippy.js применяет стили через style атрибуты элементов. CSP с директивой style-src 'self' и без 'unsafe-inline' заблокирует динамическое добавление стилей, что приведёт к некорректному отображению тултипов.

  3. Подключение внешних ресурсов Если тултип содержит контент, загружаемый с внешних URL (например, изображение или iframe), CSP с директивой img-src или frame-src может блокировать их загрузку.

Настройка CSP для корректной работы Tippy.js

Для корректного функционирования тултипов необходимо учитывать следующие директивы CSP:

  • script-src Чтобы разрешить выполнение inline-скриптов, можно использовать 'unsafe-inline' или генерацию скриптов через внешние файлы:

    Content-Security-Policy: script-src 'self' 'unsafe-inline';

    Оптимальный вариант — вынести весь код инициализации Tippy.js в отдельный JS-файл.

  • style-src Динамические inline-стили требуют либо 'unsafe-inline', либо использование хэшей для конкретных стилей:

    Content-Security-Policy: style-src 'self' 'unsafe-inline';

    В Tippy.js стили для тултипов генерируются автоматически, поэтому 'unsafe-inline' чаще всего необходим.

  • img-src, font-src, connect-src Если тултипы содержат изображения, иконки или загружают данные через fetch/AJAX, CSP должен разрешать соответствующие источники:

    Content-Security-Policy: img-src 'self' https://example.com; font-src 'self'; connect-src 'self' https://api.example.com;

Особенности работы с Tippy.js и CSP

  1. Popper.js как зависимость Tippy.js использует Popper.js для позиционирования тултипов. Popper.js создаёт дополнительные элементы DOM и вычисляет позиции через JavaScript. CSP не блокирует эти операции напрямую, но ограничение стилей и скриптов может вызвать визуальные ошибки.

  2. Динамический HTML контент Tippy.js позволяет вставлять HTML-контент через опцию content. При включённой CSP необходимо быть внимательным: если контент включает inline-скрипты или стиль, они могут быть заблокированы.

  3. Использование шаблонов Вместо динамического HTML можно использовать заранее подготовленные DOM-элементы:

    const reference = document.querySelector('#button');
    const template = document.querySelector('#tooltip-template');
    
    tippy(reference, {
      content: template.innerHTML,
      allowHTML: true
    });

    Такой подход уменьшает риск блокировки CSP.

  4. Хэши и nonce для inline-кода CSP поддерживает использование хэшей и nonce для разрешения конкретных скриптов и стилей. Для Tippy.js это особенно актуально при генерации тултипов с HTML-контентом, включающим inline-стили:

    Content-Security-Policy: script-src 'self' 'sha256-<hash>';
    style-src 'self' 'sha256-<hash>';

Практические рекомендации

  • Вынести весь JS-код инициализации Tippy.js во внешние файлы. Это минимизирует необходимость 'unsafe-inline'.
  • Использовать DOM-шаблоны для HTML-контента тултипов, избегая inline-скриптов внутри них.
  • Проверять загрузку внешних ресурсов в тултипах и соответствие CSP-директив.
  • Тестировать тултипы в строгом режиме CSP. Использовать DevTools для выявления блокировок скриптов и стилей.
  • При необходимости включать 'unsafe-inline' для стилей — это часто единственный способ сохранить корректное отображение динамических тултипов без полной переработки Tippy.js под CSP.

Заключение по технической части

Tippy.js — мощная библиотека для динамических тултипов, но её полная функциональность зависит от возможности вставки inline-стилей и скриптов. CSP может ограничивать эти возможности, поэтому правильная настройка директив и перенос скриптов в отдельные файлы являются ключевыми для безопасной и корректной работы тултипов.

Использование DOM-шаблонов, внешних скриптов и правильных CSP-директив обеспечивает баланс между безопасностью и функциональностью Tippy.js на современных веб-сайтах.