Фильтрация тегов

Библиотека Markdown-it предоставляет мощный механизм для работы с Markdown, включая возможность фильтрации и контроля тегов. Важнейшей задачей при работе с Markdown является обеспечение безопасности и чистоты HTML, особенно при обработке пользовательского ввода. Фильтрация тегов позволяет ограничить набор HTML-элементов, которые могут появляться в сгенерированном контенте, предотвращая XSS-уязвимости и некорректное оформление.


Настройка HTML-разметки

По умолчанию Markdown-it может рендерить HTML, включённый в Markdown. Этот режим управляется опцией html:

const MarkdownIt = require('markdown-it');
const md = new MarkdownIt({ html: true });

Если html установлено в false, все встроенные HTML-теги будут экранироваться:

const md = new MarkdownIt({ html: false });
md.render('<script>alert("XSS")</script>');
// Вывод: &lt;script&gt;alert("XSS")&lt;/script&gt;

Это базовая защита от нежелательных тегов, но для тонкой фильтрации требуется дополнительная логика.


Использование правил рендеринга (renderer rules)

Markdown-it использует систему рендереров, позволяющую перехватывать и модифицировать отдельные элементы:

md.renderer.rules.html_block = (tokens, idx) => {
  const content = tokens[idx].content;
  // Разрешаем только <b> и <i>
  if (/^<(b|i)>.*<\/\1>$/.test(content)) {
    return content;
  }
  return '';
};

Здесь tokens[idx].content содержит HTML-блок. С помощью регулярных выражений или других проверок можно разрешать только определённые теги, а остальные — игнорировать или заменять.


Плагины для фильтрации тегов

Для комплексной фильтрации часто используют плагины или внешние библиотеки. Например, sanitize-html интегрируется с Markdown-it для безопасного рендеринга:

const sanitizeHtml = require('sanitize-html');

md.renderer.rules.html_block = (tokens, idx) => {
  return sanitizeHtml(tokens[idx].content, {
    allowedTags: ['b', 'i', 'strong', 'em', 'a'],
    allowedAttributes: { a: ['href', 'title'] }
  });
};

Такой подход позволяет разделять ответственность: Markdown-it отвечает за разбор Markdown, а sanitize-html — за безопасное разрешение HTML-тегов и атрибутов.


Фильтрация через кастомные inline-токены

Помимо HTML-блоков, можно фильтровать inline-теги, используя html_inline:

md.renderer.rules.html_inline = (tokens, idx) => {
  const content = tokens[idx].content;
  if (content.startsWith('<img')) return '';
  return content;
};

Этот метод полезен для удаления отдельных HTML-элементов внутри текста, например <img> или <iframe>.


Использование атрибутов Markdown-it

Markdown-it позволяет добавлять и фильтровать атрибуты тегов через плагины, такие как markdown-it-attrs. Пример фильтрации:

const mdAttrs = require('markdown-it-attrs');
md.use(mdAttrs);

md.renderer.rules.html_block = (tokens, idx) => {
  let content = tokens[idx].content;
  // Удаляем все style-атрибуты
  content = content.replace(/ style=".*?"/g, '');
  return content;
};

Это позволяет сохранить семантические элементы, но убрать потенциально опасные или некорректные атрибуты.


Сценарии фильтрации

  • Разрешить только базовые теги форматирования: <b>, <i>, <strong>, <em>.
  • Блокировать скрипты и iframe: предотвращение XSS.
  • Контроль изображений: разрешать <img> только с безопасными URL или ограничивать размеры.
  • Ограничение атрибутов ссылок: <a href> только с http/https протоколами.
  • Удаление inline стилей: предотвращение неконсистентного оформления и инъекций CSS.

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

  1. Всегда отключать HTML по умолчанию, если контент приходит от пользователей.
  2. Использовать проверенные плагины для фильтрации, вместо написания сложных регулярных выражений.
  3. Разделять обработку Markdown и безопасность HTML, чтобы логика была чистой и поддерживаемой.
  4. Тестировать фильтры на XSS-уязвимости и нестандартные комбинации тегов.
  5. Использовать рендереры Markdown-it для тонкой настройки отображения каждого HTML-тега.

Фильтрация тегов в Markdown-it — это комбинация опций рендерера, правил токенов и внешних библиотек. Такой подход обеспечивает баланс между гибкостью форматирования и безопасностью в веб-приложениях.