Параметр sanitize и безопасность

Библиотека Marked предоставляет мощные инструменты для преобразования Markdown в HTML. Одним из критически важных аспектов при работе с динамическим контентом является безопасность. Markdown, полученный из ненадёжных источников, может содержать вредоносный код, например XSS-скрипты. Для управления безопасностью используется параметр sanitize и связанные с ним методы фильтрации.


Назначение параметра sanitize

Параметр sanitize предназначен для удаления потенциально опасного HTML-кода при преобразовании Markdown в HTML. Если установлен sanitize: true, библиотека автоматически очищает все HTML-теги, оставляя только безопасные Markdown-теги.

Пример использования:

const marked = require('marked');

const markdown = '<img src="x" oner ror="alert(\'XSS\')"> Hello';
const html = marked(markdown, { sanitize: true });

console.log(html);
// Вывод: "Hello"

В этом примере встроенный HTML-тег <img> с атрибутом onerror был полностью удалён.

Важно: В новых версиях Marked параметр sanitize считается устаревшим. Вместо него рекомендуется использовать renderer и внешние библиотеки для очистки HTML, такие как DOMPurify.


Renderer и безопасность

Marked позволяет настраивать renderer, чтобы контролировать генерацию HTML на уровне каждого элемента. Это дает гибкость для безопасного рендеринга, например, фильтрации ссылок или изображений:

const renderer = new marked.Renderer();

renderer.link = function(href, title, text) {
    const safeHref = href.startsWith('http') ? href : '#';
    return `<a href="${safeHref}" title="${title || ''}">${text}</a>`;
};

const html = marked('[Click me](jav * ascript:alert(1))', { renderer });
console.log(html);
// Вывод: <a href="#">Click me</a>

Здесь все ссылки с небезопасными схемами (jav * ascript:) заменяются на безопасные.


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

Так как параметр sanitize устарел, безопаснее всего использовать проверенные библиотеки, например:

  1. DOMPurify — очищает HTML от XSS, сохраняя разрешённые теги и атрибуты.
  2. sanitize-html — позволяет задавать правила для конкретных тегов и атрибутов.

Пример с DOMPurify:

const DOMPurify = require('dompurify')(window);

const dirtyHtml = marked('<script>alert(1)</script>Safe text');
const cleanHtml = DOMPurify.sanitize(dirtyHtml);

console.log(cleanHtml);
// Вывод: "Safe text"

Безопасная работа с пользовательским Markdown

Для защиты приложения важно соблюдать следующие правила:

  • Не доверять пользовательскому HTML. Любой HTML, вставленный из Markdown, нужно фильтровать.
  • Использовать кастомный renderer для контроля ссылок, изображений и медиа.
  • Использовать сторонние библиотеки для очистки вместо устаревшего sanitize.
  • Регулярно обновлять библиотеку Marked и библиотеки для очистки HTML, чтобы иметь актуальные патчи безопасности.

Примеры уязвимостей при неправильной обработке

  1. XSS через изображение:
![alt](x" oner ror="alert(1))

Без очистки приведет к выполнению скрипта в браузере.

  1. JavaScript-ссылки:
[Click me](jav * ascript:alert('XSS'))

Непроверенные ссылки могут открывать возможности для атаки.

  1. HTML-инъекции:
<div oncl ick="alert('XSS')">Click</div>

Любой HTML должен фильтроваться перед рендерингом.


Настройка Marked для максимальной безопасности

const renderer = new marked.Renderer();

renderer.image = (href, title, text) => {
    const safeHref = href.startsWith('https://') ? href : '';
    return `<img src="${safeHref}" alt="${text}" title="${title || ''}">`;
};

renderer.link = (href, title, text) => {
    const safeHref = href.startsWith('http') ? href : '#';
    return `<a href="${safeHref}" title="${title || ''}">${text}</a>`;
};

const dirtyMarkdown = '[Malicious](jav * ascript:alert(1)) ![Image](x" oner ror="alert(1))';
const safeHtml = DOMPurify.sanitize(marked(dirtyMarkdown, { renderer }));

console.log(safeHtml);
// Вывод: безопасный HTML без выполнения скриптов

Ключевые выводы по безопасности

  • Параметр sanitize в Marked устарел и не должен использоваться в новых проектах.
  • Для безопасного рендеринга Markdown необходимо сочетать кастомный renderer и очистку HTML внешними библиотеками.
  • Всегда фильтровать ссылки, изображения и атрибуты, которые могут содержать вредоносный код.
  • Регулярные обновления библиотек помогают предотвращать новые угрозы XSS и HTML-инъекций.

Безопасная обработка Markdown — не опция, а обязательное требование для любого проекта, работающего с пользовательским контентом.