Shepherd.js — это библиотека для создания интерактивных пошаговых туров по веб-приложениям. Несмотря на то, что она в основном отвечает за визуальное сопровождение интерфейса, при использовании пользовательских данных в описаниях шагов или элементах интерфейса важно учитывать уязвимости XSS (Cross-Site Scripting) и другие риски, связанные с внедрением неподготовленного ввода.
Каждый шаг в Shepherd.js определяется объектом, который может
содержать свойства title, text,
buttons и attachTo. Свойство text
часто используется для отображения пользовательских данных. Важно
понимать, что Shepherd.js не экранирует HTML в text
по умолчанию. Прямое вставление данных пользователя может
привести к выполнению вредоносного кода.
Пример небезопасного кода:
const userInput = "<img src=x oner ror=alert('XSS')>";
const tour = new Shepherd.Tour({
defaultStepOptions: { scrollTo: true }
});
tour.addStep({
title: 'Пример',
text: userInput
});
tour.start();
В этом случае браузер выполнит JavaScript, встроенный в строку
userInput.
Для безопасного отображения данных рекомендуется:
<, >,
&, ", ') на
HTML-сущности:function escapeHTML(str) {
return str
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
const safeText = escapeHTML(userInput);
tour.addStep({
title: 'Пример',
text: safeText
});
text как текст, а не HTML
Shepherd.js позволяет передавать строки в text как
строку без HTML-разметки, если не включать свойство
innerHTML. Любой ввод автоматически будет интерпретирован
как текст.Кнопки в шагах Shepherd.js могут содержать кастомные обработчики. При использовании пользовательских данных важно:
eval или new Function.text и
action.Пример безопасной кнопки:
tour.addStep({
title: 'Кнопка',
text: 'Нажмите кнопку для действия',
buttons: [
{
text: 'Подтвердить',
action: tour.next
}
]
});
Если необходимо динамически формировать кнопки на основе ввода пользователя, лучше использовать заранее определённые функции для действий, а не создавать код из строки.
attachTo и выбором элементов DOMСвойство attachTo позволяет привязать шаг к элементу
DOM. При использовании пользовательского ввода в качестве селектора
важно проверять, что селектор соответствует ожидаемому
формату:
const userSelector = "#user-input";
if (document.querySelector(userSelector)) {
tour.addStep({
title: 'Привязка к элементу',
text: 'Этот шаг привязан к безопасному элементу',
attachTo: {
element: userSelector,
on: 'bottom'
}
});
}
Использование неконтролируемого селектора может привести к ошибкам или попыткам обхода безопасности.
Shepherd.js позволяет использовать разметку HTML в text
через опцию allowHtml. Если включена поддержка HTML,
безопасность должна обеспечиваться строго:
onerror, onclick.Пример безопасного HTML-контента:
import DOMPurify from 'dompurify';
const unsafeHtml = "<b>Привет</b><img src=x oner ror=alert('XSS')>";
const cleanHtml = DOMPurify.sanitize(unsafeHtml);
tour.addStep({
title: 'HTML контент',
text: cleanHtml,
allowHtml: true
});
Если шаги Shepherd.js используются для сбора информации о поведении пользователей, данные, отправляемые на сервер, также должны проходить валидацию и экранирование на стороне сервера. Никогда не доверять клиентскому коду, даже если он использует экранирование на фронтенде.
text или title.Эти практики помогают предотвратить XSS-уязвимости и обеспечить безопасное использование Shepherd.js даже при работе с динамическим пользовательским контентом.