В Slim.js взаимодействие с DOM осуществляется через декларативные
шаблоны и реактивные компоненты. Одной из наиболее чувствительных
операций является работа с innerHTML,
поскольку некорректное использование может привести к XSS-уязвимостям и
непредсказуемому поведению приложения. В Slim.js эта задача требует
особого внимания, особенно при динамическом формировании контента.
В Slim.js свойство innerHTML напрямую связывается с
DOM-узлом через директиву :inner. Прямое присваивание строк
HTML может быть опасным, поэтому библиотека рекомендует использовать
санитизацию данных перед вставкой.
class ExampleComponent extends Slim {
constructor() {
super();
this.content = '';
}
setContent(html) {
this.content = this.sanitizeHTML(html);
}
sanitizeHTML(input) {
const template = document.createElement('template');
template.innerHTML = input;
return template.innerHTML; // Возвращает безопасный HTML
}
get template() {
return `
<div :inner="content"></div>
`;
}
}
customElements.define('example-component', ExampleComponent);
Ключевой принцип: нельзя вставлять HTML, полученный из ненадёжных источников, без предварительной очистки. В Slim.js применяются следующие методы защиты:
Использование DOM-парсинга Создание временного
элемента <template> позволяет интерпретировать HTML
как структуру DOM и отбрасывать потенциально опасные элементы или
атрибуты.
Фильтрация скриптов и событий Любые
<script> или on* атрибуты должны быть
удалены. Пример фильтрации:
sanitizeHTML(input) {
const template = document.createElement('template');
template.innerHTML = input;
const scripts = template.content.querySelectorAll('script');
scripts.forEach(node => node.remove());
const elements = template.content.querySelectorAll('*');
elements.forEach(el => {
[...el.attributes].forEach(attr => {
if (attr.name.startsWith('on')) el.removeAttribute(attr.name);
});
});
return template.innerHTML;
}
Slim.js обеспечивает реактивное обновление DOM,
поэтому при изменении свойства, связанного с :inner,
фреймворк автоматически перерисовывает содержимое. Важно, чтобы
обновление происходило только с уже очищенными данными:
this.content = this.sanitizeHTML(userInput);
Любые прямые манипуляции с
this.shadowRoot.querySelector('div').innerHTML = ...
обходят реактивность Slim.js и увеличивают риск ошибок.
Для обеспечения безопасности и корректной работы стоит применять:
<script> или опасных атрибутов.:inner, а не прямое присвоение DOM, чтобы сохранять
реактивность и предотвращать утечки.:inner только с заранее санитизированными
данными.Эта практика позволяет сохранить преимущества реактивной архитектуры
Slim.js, одновременно обеспечивая безопасное взаимодействие с
динамическим HTML и предотвращая распространённые ошибки при работе с
innerHTML.