Библиотеки Remark и Rehype используются для разбора, трансформации и генерации Markdown и HTML. Когда речь заходит о работе с внешними данными, критически важно правильно настраивать политики санитизации (очистки данных), чтобы предотвратить XSS-уязвимости и некорректное отображение контента.
Rehype предоставляет возможность обработки HTML через дерево узлов HAST (HTML Abstract Syntax Tree). Санитизация сводится к фильтрации или изменению узлов и атрибутов перед выводом.
Hast представляет HTML как дерево объектов:
{
type: 'element',
tagName: 'a',
properties: { href: 'https://example.com' },
children: [{ type: 'text', value: 'Ссылка' }]
}Санитизация обычно фокусируется на:
tagName)properties)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 работает с 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();
Ключевые моменты:
rehype-escape для экранирования неизвестных символов.Для предотвращения внедрения небезопасного CSS или JavaScript в атрибуты:
style, on* (onclick,
onmouseover и т.д.) по умолчанию.const customSchema = {
attributes: {
div: (node, name, value) => (value === 'allowed-class' ? value : null),
},
};
Это гарантирует, что в HTML попадут только безопасные стили и классы.
Разрешение некоторых встроенных элементов
Например, <iframe> для видео с YouTube:
const schema = {
tagNames: ['iframe'],
attributes: { iframe: ['src', 'width', 'height', 'allow', 'frameborder'] },
protocols: { src: ['https'] },
};Комбинация нескольких плагинов Remark → Rehype → rehype-sanitize → rehype-autolink-headings → rehype-stringify. Важно, что санитизация выполняется перед плагинами, которые могут добавлять HTML, чтобы не допустить небезопасный код.
github-markdown, default из rehype-sanitize)
для стандартного Markdown.jav * ascript: и
data: схем для ссылок.Настройка политик санитизации в Remark и Rehype обеспечивает безопасное взаимодействие с внешним контентом, предотвращает XSS-атаки и позволяет гибко контролировать допустимые элементы HTML и атрибуты. Правильное применение схем и динамических правил делает обработку Markdown и HTML надежной и предсказуемой.