Плагин $sanitize — безопасный рендер HTML
Плагин предоставляет функцию $sanitize(html, options?) для безопасной очистки и рендера HTML‑контента на клиенте.
Внутри используется DOMPurify через пакет isomorphic-dompurify. Плагин подключается как Nuxt‑провайдер и доступен из компонентов,
а также через вспомогательный компонент <SafeHtml />.
- Файлы:
- app/plugins/dompurify.ts — реализация и базовая конфигурация DOMPurify, хуки
- app/types/dompurify.d.ts — типы для Nuxt
$sanitize- app/components/base/SafeHtml.vue — обёртка для шаблонов (
v-htmlс предварительной очисткой)
Быстрый старт
1) В шаблоне через компонент SafeHtml
<!-- Строка с потенциально небезопасным HTML -->
<SafeHtml :html="'<p>Пример <strong>жирного</strong> текста и <a href=\"javascript:alert(1)\">ссылки</a>.</p>'" />
2) В коде напрямую через $sanitize
const { $sanitize } = useNuxtApp()
const raw = '<p>Текст с <img src="x" onerror="alert(1)"> подозрительными атрибутами.</p>'
const safe = $sanitize(raw)
// затем можно отрисовать: <div v-html="safe" />
Конфигурация по умолчанию
Определена в app/plugins/dompurify.ts и объединяется с пользовательскими опциями, которые вы передаёте вторым параметром.
Ключевые моменты базовой конфигурации:
- USE_PROFILES: { html: true }
- Разрешённые URI‑схемы: только безопасные (https, http, mailto, tel, ftp, data:image/* base64)
- ADD_ATTR: class, id, style, target, rel, title, data-*; медиа атрибуты (src, srcset, sizes, alt, width, height), ссылки (href, download, name), iframe/video (allow, allowfullscreen, frameborder, referrerpolicy, loading)
- ADD_TAGS: iframe, video, source, picture, figure, figcaption, table и связанные элементы
- ADD_URI_SAFE_ATTR: 'src', 'href', 'srcset'
Особые хуки DOMPurify:
- uponSanitizeElement — фильтрует
<iframe>:- запрещает
srcdoc - оставляет только HTTPS
- белый список источников: YouTube/Youtube‑nocookie/Vimeo в формате embed
- запрещает
- afterSanitizeAttributes — обогащает
<a>и<iframe>:- для ссылок убирает
javascript:иdata:text/html, проставляет target="_blank" и rel="noopener noreferrer nofollow" - для iframe добавляет безопасные атрибуты: loading="lazy", referrerpolicy="no-referrer", allow, а также рекомендует sandbox
- для ссылок убирает
Пользовательские опции
Функция $sanitize(html, options?) принимает опциональный объект DOMPurify Config и сливает его с базовой конфигурацией плагина.
Примеры:
const { $sanitize } = useNuxtApp()
// 1) Жёстче — запретить все iframe на этой вставке
const html1 = $sanitize(rawHtml, { FORBID_TAGS: ['iframe'] })
// 2) Разрешить дополнительные теги/атрибуты только для одного вызова
const html2 = $sanitize(rawHtml, {
ADD_TAGS: ['mark'],
ADD_ATTR: ['aria-label']
})
// 3) Разрешить data: картинки в base64 (по умолчанию уже разрешены в плагине)
const html3 = $sanitize(rawHtml, {
ALLOWED_URI_REGEXP: /^(?:(?:https?|mailto|tel|ftp|data:image\/(?:png|gif|jpeg|webp);base64),?)/i
})
Важно: переданные опции перекрывают базовые только в пределах одного вызова. Хуки безопасности (например, запрет srcdoc у
<iframe>) всё равно отработают.
Компонент SafeHtml
Упрощает рендер HTML в шаблонах:
- Пропсы:
- html?: string — исходная строка HTML
- options?: DOMPurify Config — кастомные опции для данного рендера
- Использование:
<SafeHtml :html="content" :options="{ FORBID_TAGS: ['iframe'] }" />
Исходник (фрагмент):
// app/components/base/SafeHtml.vue
import type { Config } from 'isomorphic-dompurify'
interface Props {
html?: string
options?: Config
}
const props = defineProps<Props>()
const { $sanitize } = useNuxtApp()
const safeHtml = computed(() => $sanitize(props.html ?? '', props.options))
Безопасность и рекомендации
- Никогда не вставляйте HTML из недоверенных источников напрямую через
v-html— всегда используйте$sanitize/SafeHtml. - Не полагайтесь только на клиентский санитайз: сервер также должен фильтровать/экранировать пользовательский ввод.
- Старайтесь не использовать
styleи инлайн‑скрипты — они либо вырежутся, либо могут ухудшить доступность. - Для
<iframe>используйте только проверенные источники и форматы embed; при необходимости сузьте белый список через собственный хук или FORBID_TAGS.
Частые вопросы
- Можно ли отключить target/_blank у ссылок? — Да, передайте свой
afterSanitizeAttributesхук в опциях или удалите атрибуты пост‑обработкой результата (не рекомендуется). - Как добавить своего провайдера видео? — Измените массив
allowedOriginsв хукеuponSanitizeElement(файл плагина) или в опциях пропишите собственныйALLOWED_URI_REGEXPи удалите iframe черезFORBID_TAGS, если не совпадает. - Работает ли на сервере? — Плагин ориентирован на клиентский рендер. Для SSR и безопасности на уровне бэкенда используйте серверные библиотеки санитайза.