Безопасная работа с HTML

SkateJS — это легковесная библиотека для создания веб-компонентов с использованием нативного Custom Elements API. Одной из ключевых задач при работе с компонентами является безопасное управление HTML-контентом, особенно если данные поступают из внешних источников. Неправильное использование innerHTML или аналогичных методов может привести к XSS-уязвимостям и нарушению целостности приложения.

Создание компонента и шаблонов

В SkateJS компоненты создаются через функцию define. Основной элемент, отвечающий за рендеринг, — это метод render. Он может возвращать строки HTML или использовать JSX-подобный синтаксис, если включен соответствующий трансформер.

import { define, Component, h } from 'skatejs';

class SafeComponent extends Component {
  static get props() {
    return {
      content: String
    };
  }

  render() {
    return h('div', {}, this.content);
  }
}

define('safe-component', SafeComponent);

В приведённом примере используется метод h для создания виртуального DOM. Это безопаснее, чем напрямую вставлять строки HTML через innerHTML, так как SkateJS сам экранирует потенциально опасные символы.

Работа с небезопасным HTML

Если необходимо вставлять динамический HTML, полученный из внешнего источника, нельзя просто использовать innerHTML. SkateJS предоставляет возможность контролировать рендеринг через функции и свойства, что снижает риск XSS.

class UnsafeComponent extends Component {
  static get props() {
    return {
      rawHtml: String
    };
  }

  render() {
    const safeHtml = document.createElement('div');
    safeHtml.textContent = this.rawHtml; // экранирование символов
    return h('div', {}, safeHtml.innerHTML);
  }
}

define('unsafe-component', UnsafeComponent);

В этом примере HTML сначала помещается в textContent, что автоматически экранирует все потенциально опасные элементы. После этого безопасно вставляется в рендеринг компонента.

Атрибуты и свойства компонентов

SkateJS различает свойства (props) и атрибуты (attributes). Использование свойств предпочтительнее при работе с динамическим контентом, так как они могут быть объектами или строками и обрабатываются библиотекой более безопасно.

class ContentComponent extends Component {
  static get props() {
    return {
      title: String,
      description: String
    };
  }

  render() {
    return h('section', {},
      h('h1', {}, this.title),
      h('p', {}, this.description)
    );
  }
}

define('content-component', ContentComponent);

Передача данных через свойства позволяет избегать прямого связывания с HTML-атрибутами, где легко можно допустить уязвимости.

Использование слотов для контента

SkateJS поддерживает слоты, которые позволяют безопасно инкапсулировать HTML и передавать контент из родительских компонентов без прямого вмешательства в шаблон:

class SlotComponent extends Component {
  render() {
    return h('div', {},
      h('slot') // здесь будет безопасно отображён любой дочерний контент
    );
  }
}

define('slot-component', SlotComponent);

Слоты автоматически учитывают границы компонента и позволяют вставлять HTML, сохраняя стиль изоляции.

Рекомендации по безопасному рендерингу

  1. Использовать h вместо строк HTML. Любой текст автоматически экранируется.
  2. Экранировать данные перед вставкой через textContent или специальные функции.
  3. Отдавать предпочтение свойствам (props) перед атрибутами для динамического контента.
  4. Использовать слоты для вставки внешнего HTML, чтобы избежать прямого рендеринга.
  5. Избегать innerHTML и других методов прямой вставки HTML без предварительной обработки данных.

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

SkateJS позволяет комбинировать текст и HTML безопасно, если применять h и функции рендеринга:

class MixedContentComponent extends Component {
  static get props() {
    return {
      header: String,
      body: String
    };
  }

  render() {
    return h('div', {},
      h('h2', {}, this.header),
      h('p', {}, this.body)
    );
  }
}

define('mixed-content', MixedContentComponent);

Даже если header или body содержат потенциально опасные символы, SkateJS корректно экранирует их при рендеринге. Это позволяет безопасно работать с внешними данными, не рискуя внедрением скриптов или нарушением структуры страницы.


Хотя SkateJS минимизирует риски XSS, ответственность за обработку данных остаётся на разработчике. Применение этих принципов позволяет создавать веб-компоненты, которые безопасно управляют HTML и могут работать с внешними источниками информации без уязвимостей.