Санитизация пользовательского ввода

При работе с библиотекой Shopify Draggable критически важно правильно обрабатывать пользовательский ввод, особенно когда речь идёт о динамическом изменении DOM и взаимодействии с элементами страницы. Санитизация данных предотвращает XSS-атаки, некорректное отображение и потенциальные сбои в работе скриптов.


Причины необходимости санитизации

  1. Защита от XSS (Cross-Site Scripting) Любой пользовательский ввод, вставляемый в DOM без проверки, может содержать вредоносные скрипты. В Draggable это особенно опасно при добавлении элементов через drag-and-drop или кастомные тултипы.

  2. Корректное взаимодействие с DOM Некорректные или неожиданные символы в текстовом контенте элементов могут ломать обработку событий, например drag:start, drag:move, drag:stop.

  3. Поддержка производительности Удаление лишних тегов и спецсимволов снижает нагрузку на рендеринг и упрощает работу с элементами коллекций.


Основные методы санитизации

1. Экранирование HTML-символов Любые <, >, &, " и ' должны быть заменены на HTML-сущности:

function escapeHTML(str) {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#039;');
}

Применение в Draggable:

const draggableElement = document.querySelector('.draggable-item');
const userInput = "<script>alert('XSS');</script>";
draggableElement.innerHTML = escapeHTML(userInput);

2. Удаление опасных тегов Если разрешён HTML, необходимо фильтровать теги, которые могут выполнять скрипты:

function sanitizeHTML(str) {
  const temp = document.createElement('div');
  temp.innerHTML = str;
  const scripts = temp.querySelectorAll('script, style, iframe');
  scripts.forEach(node => node.remove());
  return temp.innerHTML;
}

Это важно при динамическом создании элементов в Draggable:

draggableElement.innerHTML = sanitizeHTML(userInput);

3. Использование текстового контента вместо HTML Для большинства случаев drag-and-drop достаточно вставлять данные через textContent:

draggableElement.textContent = userInput;

Преимущество: полное предотвращение XSS и ненужных тегов.


Интеграция с событиями Draggable

Draggable предоставляет события, где пользовательский ввод может быть вставлен:

  • drag:start – начало перетаскивания
  • drag:move – перемещение
  • drag:stop – завершение перетаскивания

Важно фильтровать данные при обработке этих событий:

const container = document.querySelector('.container');

const draggable = new Draggable(container, {
  draggable: '.draggable-item'
});

draggable.on('drag:start', (event) => {
  const safeContent = escapeHTML(event.source.dataset.userInput);
  event.source.textContent = safeContent;
});

Такой подход защищает от вставки скриптов в момент старта перетаскивания.


Практика безопасного добавления новых элементов

При добавлении новых draggable-элементов с пользовательским вводом:

function createDraggableItem(input) {
  const item = document.createElement('div');
  item.classList.add('draggable-item');
  item.textContent = escapeHTML(input);
  return item;
}

container.appendChild(createDraggableItem('<b>Test</b>'));

Использование textContent или предварительная санитизация предотвращает попадание непроверенного HTML в DOM.


Проверка и фильтрация данных

Для сложных форматов (например, JSON или структурированный текст) рекомендуется:

  1. Валидировать по схеме – строго соответствовать ожидаемому формату.
  2. Ограничивать длину строки – предотвращает переполнение DOM.
  3. Удалять потенциально опасные символы\u0000, управляющие символы, нестандартные Unicode-символы.

Пример фильтрации:

function sanitizeInput(input) {
  let sanitized = input.trim();
  sanitized = sanitized.substring(0, 100); // ограничение длины
  sanitized = escapeHTML(sanitized);
  return sanitized;
}

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

  • Всегда обрабатывать ввод до вставки в DOM.
  • Использовать textContent вместо innerHTML, если HTML не нужен.
  • Для HTML — фильтровать теги и атрибуты.
  • Проверять данные в событиях Draggable перед изменением элементов.
  • Ограничивать длину и тип вводимых данных.

Эти методы минимизируют риск XSS и обеспечивают стабильную работу Shopify Draggable в проектах с пользовательским контентом.