flawopen.com/XSS in JavaScript/DOMPurify and innerHTML
Достаточно ли DOMPurify для защиты innerHTML?
DOMPurify — надёжный очиститель HTML по списку разрешений, если результат без изменений сразу передаётся HTML-sink. Представьте проверку посылки на входе: если её потом перепакуют или внесут через другой вход, первая проверка уже не описывает содержимое. Для обычного текста используйте textContent, чтобы вообще не разбирать HTML.
// Очищено при сохранении старой версией/политикой. saveToDb(DOMPurify.sanitize(input)); // Позже сохранённой строке доверяют без проверки. el.innerHTML = fetchedFromDb;
// Для HTML используйте актуальную библиотеку // прямо перед вставкой в HTML-контекст. el.innerHTML = DOMPurify.sanitize(untrustedHtml, { USE_PROFILES: { html: true }, }); // Обычный текст не нужно разбирать как HTML. textNode.textContent = untrustedText;
Почему очистка только при сохранении слабее
Очистка при сохранении сама по себе не опасна, но создаёт границу устаревших данных: renderer может доверять старому результату после исправления очистителя, смены политики или обходного пути. Повторно очищайте данные при выводе актуальной версией и политикой точного sink. Не меняйте очищенную разметку и не передавайте её другой библиотеке до вставки: постобработка может отменить результат очистки.
Важны конфигурация и контекст вывода
DOMPurify по умолчанию разрешает HTML, SVG и MathML. Если нужен только HTML, сузьте профиль через USE_PROFILES: { html: true }. Не расширяйте список тегов и атрибутов без проверки. DOMPurify не очищает CSS и не блокирует все внешние запросы; используйте результат только в HTML-контексте, не в JavaScript, атрибуте, XML, SVG или CSS.
Trusted Types и серверный рендеринг
Если поддерживается, включите Trusted Types через Content Security Policy, чтобы отклонять строки в HTML-sink без одобренной политики. DOMPurify может возвращать TrustedHTML; это предотвращает случайные присваивания в sink, но не исправляет плохую конфигурацию или постобработку. На сервере DOMPurify зависит от DOM-реализации: обновляйте jsdom и не используйте с ним happy-dom для критичной к безопасности очистки.
Производственный чек-лист
- ✓Используйте textContent для обычного текста. Применяйте DOMPurify, только если продукту нужно отображать ограниченный HTML.
- ✓Очищайте данные у конечного HTML-sink актуальной версией DOMPurify и проверенным минимальным списком разрешений; не меняйте результат после этого.
- ✓Оставляйте HTML в HTML-контексте. Не используйте результат в JavaScript, CSS, атрибуте, XML, SVG или другом контексте парсера.
- ✓Проверяйте совместно постоянный setConfig(), hooks, ADD_TAGS/ADD_ATTR, серверные DOM-версии и политики/CSP Trusted Types.
Поиск HTML-sink в коде
rg -n -g '*.{js,ts,jsx,tsx}' '(innerHTML|outerHTML|insertAdjacentHTML|document\.write|dangerouslySetInnerHTML)' .Источники и ссылки
- DOMPurify — README и конфигурация
- DOMPurify — цели безопасности и модель угроз
- OWASP — защита от DOM-based XSS
- OWASP — безопасность JavaScript и TypeScript
- FlawOpen — XSS в JavaScript