Безопасная обработка протоколов

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

Проверка протоколов в ссылках

По умолчанию Markdown-it поддерживает стандартный синтаксис ссылок:

[текст ссылки](url)

При рендеринге URL может содержать опасные протоколы, например jav * ascript:, которые позволяют выполнить произвольный код в браузере. Для безопасной обработки необходимо фильтровать протоколы.

Пример безопасной проверки протоколов:

const MarkdownIt = require('markdown-it');

const md = new MarkdownIt({
  linkify: true
});

function sanitizeLink(url) {
  const allowedProtocols = ['http:', 'https:', 'mailto:'];
  try {
    const parsed = new URL(url, 'http://example.com');
    if (!allowedProtocols.includes(parsed.protocol)) {
      return '';
    }
    return url;
  } catch (err) {
    return '';
  }
}

md.renderer.rules.link_open = (tokens, idx, options, env, self) => {
  const token = tokens[idx];
  const hrefIndex = token.attrIndex('href');

  if (hrefIndex >= 0) {
    const href = token.attrs[hrefIndex][1];
    token.attrs[hrefIndex][1] = sanitizeLink(href);
  }

  return self.renderToken(tokens, idx, options);
};

const result = md.render('[Click me](jav * ascript:alert(1))');
console.log(result);

В данном примере все ссылки, использующие недопустимые протоколы, будут очищены, предотвращая возможность выполнения вредоносного JavaScript.

Фильтрация изображений

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

![alt](jav * ascript:alert(1))

Для безопасной обработки изображений можно расширить проверку:

md.renderer.rules.image = (tokens, idx, options, env, self) => {
  const token = tokens[idx];
  const srcIndex = token.attrIndex('src');

  if (srcIndex >= 0) {
    const src = token.attrs[srcIndex][1];
    token.attrs[srcIndex][1] = sanitizeLink(src);
  }

  return self.renderToken(tokens, idx, options);
};

Использование плагинов для безопасного Markdown

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

const linkAttributes = require('markdown-it-link-attributes');

md.use(linkAttributes, {
  matcher(href) {
    return !href.startsWith('jav * ascript:');
  },
  attrs: {
    rel: 'noopener',
    target: '_blank'
  }
});

Такой подход позволяет не только блокировать опасные ссылки, но и добавлять атрибуты безопасности для внешних ссылок (rel="noopener", target="_blank"), что предотвращает ряд атак через открытие новых окон.

Обработка кастомных протоколов

Иногда необходима поддержка специфичных протоколов, например tel: или ftp:. В таких случаях нужно явно указать список разрешённых протоколов:

const allowedProtocols = ['http:', 'https:', 'mailto:', 'tel:', 'ftp:'];

function sanitizeLink(url) {
  try {
    const parsed = new URL(url, 'http://example.com');
    return allowedProtocols.includes(parsed.protocol) ? url : '';
  } catch {
    return '';
  }
}

Этот метод обеспечивает контроль над каждым URL, предотвращая внедрение нежелательных схем.

Резюме по безопасности протоколов

  • Фильтрация протоколов — обязательная мера для всех ссылок и изображений.
  • Использование URL для парсинга — надёжный способ определить реальный протокол и корректность URL.
  • Плагины Markdown-it — удобный способ добавления атрибутов безопасности и контроля ссылок.
  • Разрешённый список протоколов — ключевой элемент защиты, который должен быть явно определён и поддерживаться в коде.

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