Санитизация данных

Санитизация данных — ключевой аспект при работе с веб-компонентами на базе SkateJS, поскольку обеспечивает защиту от XSS-атак, некорректного отображения данных и нарушений логики приложения. В SkateJS санитизация тесно связана с обработкой свойств (props) компонентов, их слотов и атрибутов, которые могут быть динамическими.


Работа с props и их типизация

В SkateJS все свойства компонента объявляются через объект props при его определении:

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

class MyComponent extends Component {
  static props = {
    text: props.string,
    count: props.number
  };
}
define('my-component', MyComponent);

Ключевые моменты:

  • props.string и props.number автоматически приводят значения к нужному типу.
  • Для пользовательского ввода важно использовать типы string и boolean осторожно, так как строка может содержать потенциально опасный HTML.

Санитизация строковых данных

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

Пример безопасного отображения текста:

import { h } from 'preact';

class SafeComponent extends Component {
  static props = {
    userInput: props.string
  };

  renderCallback() {
    // textContent обеспечивает автоматическую экранизацию HTML
    return h('div', { textContent: this.userInput });
  }
}
define('safe-component', SafeComponent);

Важно: использование innerHTML напрямую опасно, если данные не проходят фильтрацию. Для безопасного вставления HTML применяются библиотеки вроде DOMPurify:

import DOMPurify from 'dompurify';

renderCallback() {
  const cleanHTML = DOMPurify.sanitize(this.userInput);
  return h('div', { dangerouslySetInnerHTML: { __html: cleanHTML } });
}

Обработка событий и атрибутов

Атрибуты HTML могут быть источником небезопасных данных. SkateJS автоматически приводит атрибуты к типам, указанным в props, однако для строк важно дополнительно очищать их:

class AttrComponent extends Component {
  static props = {
    url: props.string
  };

  renderCallback() {
    const safeURL = this.url.replace(/jav * ascript:/gi, '');
    return h('a', { href: safeURL }, 'Ссылка');
  }
}

Принцип: удаление или экранирование потенциально опасных протоколов (jav * ascript:, data:) предотвращает выполнение вредоносного кода.


Санитизация в слоты и динамические вставки

Слоты позволяют вставлять произвольный DOM внутрь компонента. SkateJS сам по себе не фильтрует содержимое слотов, поэтому ответственность за безопасность лежит на компоненте:

class SlotComponent extends Component {
  renderCallback() {
    return h('div', null, this.children);
  }
}

Рекомендация: если предполагается использование пользовательских данных в слотах, их следует обрабатывать перед вставкой:

import DOMPurify from 'dompurify';

const safeContent = DOMPurify.sanitize(userHTML);
h('div', { dangerouslySetInnerHTML: { __html: safeContent } });

Создание кастомных санитайзеров

Иногда стандартных методов недостаточно. SkateJS позволяет определять кастомные валидаторы и санитайзеры для props:

function sanitizeText(value) {
  return value.replace(/<script.*?>.*?<\/script>/gi, '');
}

class CustomSanitizeComponent extends Component {
  static props = {
    unsafeText: {
      ...props.string,
      set(value) {
        return sanitizeText(value);
      }
    }
  };
}

Преимущества такого подхода:

  • Централизованная обработка данных.
  • Возможность гибкой фильтрации по контексту (HTML, URL, JSON).
  • Совместимость с реактивной моделью SkateJS: при изменении props данные автоматически проходят санитизацию.

Практические советы по безопасности

  1. Не использовать innerHTML без фильтрации. Всегда обрабатывать динамический HTML через DOMPurify или собственные функции.
  2. Экранировать данные при вставке в текстовые узлы. Для JSX и h() достаточно textContent.
  3. Очищать URL-атрибуты и протоколы. Любые href, src и action должны проверяться.
  4. Использовать типизацию props для автоматической проверки значений. Типизация снижает риск некорректного ввода.
  5. Санитизировать данные на этапе установки props. Это предотвращает распространение небезопасного контента по компоненту.

Интеграция с формами и пользовательским вводом

SkateJS часто используется для создания интерактивных форм. Санитизация на этом уровне включает:

  • Ограничение допустимых символов (pattern, maxlength).
  • Автоматическое приведение типов (number, boolean).
  • Очистку данных перед отправкой на сервер:
class FormComponent extends Component {
  static props = {
    email: props.string,
    comment: props.string
  };

  submitHandler() {
    const safeComment = DOMPurify.sanitize(this.comment);
    sendToServer({ email: this.email, comment: safeComment });
  }
}

Таким образом, SkateJS позволяет интегрировать санитизацию в каждый слой жизненного цикла компонента, начиная от props и атрибутов до слотов и пользовательских событий.