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 также могут представлять угрозу:
)
Для безопасной обработки изображений можно расширить проверку:
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-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 позволяет контролировать потенциальные угрозы на этапе рендеринга и минимизировать риск XSS-атак, сохраняя при этом гибкость библиотеки для реализации сложных Markdown-функций.