XSS риски

Popper.js в первую очередь предназначен для управления всплывающими элементами, такими как тултипы, выпадающие меню, подсказки и модальные окна. Основная задача библиотеки — динамически позиционировать элементы относительно целевых объектов на странице, учитывая размеры, прокрутку и видимость. Однако при этом возникают потенциальные уязвимости, связанные с XSS (Cross-Site Scripting), особенно если содержимое всплывающих элементов формируется динамически из пользовательского ввода.

Источники XSS в контексте Popper.js

  1. Динамический HTML в контенте тултипов Популярная практика — создавать тултипы с помощью свойства innerHTML:
const tooltip = document.createElement('div');
tooltip.innerHTML = userInput; // userInput приходит с сервера
new Popper(referenceElement, tooltip, {
  placement: 'top'
});

Если userInput не фильтруется, злоумышленник может вставить <script> или другие вредоносные элементы, которые выполнятся при отображении тултипа.

  1. Использование шаблонных строк с данными пользователя Даже если контент строится через шаблоны, неэкранированные значения могут привести к XSS:
tooltip.innerHTML = `<strong>${userInput}</strong>`;

Любой HTML, переданный в userInput, будет вставлен напрямую в DOM.

  1. Данные из URL или локального хранилища Передача данных через query-параметры, hash или localStorage без проверки может стать источником внедрения скриптов.

Механизмы защиты

  1. Экранирование HTML Вся пользовательская строка должна быть безопасно обработана перед вставкой в innerHTML. Простое преобразование специальных символов:
function escapeHTML(str) {
  const div = document.createElement('div');
  div.appendChild(document.createTextNode(str));
  return div.innerHTML;
}

tooltip.innerHTML = escapeHTML(userInput);
  1. Использование текстового контента вместо HTML Методы textContent и innerText полностью предотвращают исполнение HTML:
tooltip.textContent = userInput;
  1. Применение шаблонов через безопасные библиотеки Библиотеки вроде DOMPurify или Handlebars автоматически фильтруют ввод и позволяют безопасно вставлять HTML.

  2. Контроль источников данных Любые данные от пользователя, сервера или внешних API должны проверяться и фильтроваться до вставки в Popper-элементы. Особенно это касается динамических тултипов и меню.

Особенности Popper.js, влияющие на XSS

  • Popper.js не обрабатывает контент, он лишь позиционирует элементы. Следовательно, защита от XSS полностью лежит на разработчике.
  • Позиционирование через Popper может маскировать вредоносный код: даже если скрипт не виден сразу, он активируется при появлении тултипа.
  • Поддержка appendTo и кастомных контейнеров позволяет создавать всплывающие элементы вне основного DOM, что усложняет внедрение фильтров при неправильной архитектуре.

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

  • Всегда использовать textContent для динамического текста, если нет строгой необходимости в HTML.
  • Очистка HTML через библиотеки обязательна, если тултип или выпадающее меню содержит форматированный текст.
  • Минимизировать динамическую вставку HTML: статические шаблоны или заранее проверенные данные снижают риск.
  • Ограничение прав скриптов в DOM: CSP (Content Security Policy) помогает блокировать выполнение неподтвержденного кода.
  • Тестирование на XSS: инструменты автоматического сканирования и ручное внедрение вредоносных payload’ов позволяют выявить уязвимости.

Пример безопасного создания тултипа

import { createPopper } from '@popperjs/core';
import DOMPurify from 'dompurify';

const tooltip = document.createElement('div');
tooltip.classList.add('tooltip');

// Безопасная вставка HTML
tooltip.innerHTML = DOMPurify.sanitize(userInput);

const popperInstance = createPopper(referenceElement, tooltip, {
  placement: 'right',
  modifiers: [
    {
      name: 'offset',
      options: { offset: [0, 8] },
    },
  ],
});

Использование DOMPurify.sanitize предотвращает выполнение скриптов, при этом сохраняя допустимый форматированный контент.

Вывод

XSS в Popper.js не является багом самой библиотеки — это следствие неправильной работы с DOM. Любой динамический контент требует тщательной очистки и контроля источников данных. Комбинация textContent или безопасного HTML через sanitizers, строгий контроль пользовательских данных и применение CSP формируют надежный барьер против внедрения скриптов в всплывающие элементы.