Настройка политик санитизации

Библиотеки Remark и Rehype используются для разбора, трансформации и генерации Markdown и HTML. Когда речь заходит о работе с внешними данными, критически важно правильно настраивать политики санитизации (очистки данных), чтобы предотвратить XSS-уязвимости и некорректное отображение контента.


Основы санитизации в Rehype

Rehype предоставляет возможность обработки HTML через дерево узлов HAST (HTML Abstract Syntax Tree). Санитизация сводится к фильтрации или изменению узлов и атрибутов перед выводом.

  • Hast представляет HTML как дерево объектов:

    {
      type: 'element',
      tagName: 'a',
      properties: { href: 'https://example.com' },
      children: [{ type: 'text', value: 'Ссылка' }]
    }
  • Санитизация обычно фокусируется на:

    • Разрешённых тегах (tagName)
    • Разрешённых атрибутах (properties)
    • Разрешённых схемах URL (например, http, https, mailto)

Использование сторонних пакетов, таких как rehype-sanitize, позволяет задавать настраиваемые схемы.


Пример базовой схемы

import rehypeSanitize from 'rehype-sanitize';

const schema = {
  tagNames: ['b', 'i', 'a', 'p'],
  attributes: {
    a: ['href', 'title'],
  },
  protocols: {
    href: ['http', 'https', 'mailto'],
  },
};

processor.use(rehypeSanitize, schema);

Особенности:

  • tagNames — список разрешённых HTML-тегов.
  • attributes — ключи тегов соответствуют списку разрешённых атрибутов.
  • protocols — ограничение схем URL, чтобы не допустить jav * ascript: и другие потенциально опасные значения.

Расширенные политики санитизации

Можно задавать более сложные правила через функции для динамического контроля:

const dynamicSchema = {
  attributes: {
    a: (node, name, value) => {
      if (value.startsWith('https://trusted.com')) return value;
      return null;
    },
  },
};

Такой подход позволяет фильтровать значения атрибутов в зависимости от контекста, например разрешать ссылки только на доверенные домены.


Интеграция с Remark

Remark работает с Markdown и генерирует AST MDAST. Для преобразования в HTML используют remark-rehype. После преобразования можно применить санитизацию Rehype:

import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkRehype from 'remark-rehype';
import rehypeSanitize from 'rehype-sanitize';
import rehypeStringify from 'rehype-stringify';

const processor = unified()
  .use(remarkParse)
  .use(remarkRehype)
  .use(rehypeSanitize, schema)
  .use(rehypeStringify);

const html = processor.processSync('# Пример [ссылки](https://example.com)').toString();

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

  • Санитизация применяется после конвертации в HTML, чтобы фильтровать реальные HTML-теги.
  • Можно комбинировать с другими плагинами, например, rehype-escape для экранирования неизвестных символов.

Управление атрибутами и стилями

Для предотвращения внедрения небезопасного CSS или JavaScript в атрибуты:

  • Исключаются style, on* (onclick, onmouseover и т.д.) по умолчанию.
  • Можно использовать пользовательские функции для контроля классов и атрибутов:
const customSchema = {
  attributes: {
    div: (node, name, value) => (value === 'allowed-class' ? value : null),
  },
};

Это гарантирует, что в HTML попадут только безопасные стили и классы.


Сложные сценарии

  1. Разрешение некоторых встроенных элементов Например, <iframe> для видео с YouTube:

    const schema = {
      tagNames: ['iframe'],
      attributes: { iframe: ['src', 'width', 'height', 'allow', 'frameborder'] },
      protocols: { src: ['https'] },
    };
  2. Комбинация нескольких плагинов Remark → Rehype → rehype-sanitize → rehype-autolink-headings → rehype-stringify. Важно, что санитизация выполняется перед плагинами, которые могут добавлять HTML, чтобы не допустить небезопасный код.


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

  • Использовать проверенные схемы (github-markdown, default из rehype-sanitize) для стандартного Markdown.
  • Не полагаться на ручную фильтрацию строк HTML, только AST и специализированные плагины.
  • Проверять URL-атрибуты и избегать jav * ascript: и data: схем для ссылок.
  • Санитизация должна быть частью конвейера обработки контента, а не отдельным шагом после генерации HTML.

Настройка политик санитизации в Remark и Rehype обеспечивает безопасное взаимодействие с внешним контентом, предотвращает XSS-атаки и позволяет гибко контролировать допустимые элементы HTML и атрибуты. Правильное применение схем и динамических правил делает обработку Markdown и HTML надежной и предсказуемой.