Если вы используете v-html
для визуализации комментариев, то всегда есть возможность XSS.Строгая санация HTML может снизить риск, но вы никогда не знаете.
Единственный надежный способ предотвратить XSS - это никогда использовать v-html
или innerHTML
.Это означает, что вам придется анализировать HTML (используя DOMParser ) и визуализировать комментарии вручную.
Для чего-то подобного вам будет проще, если вы напишите render render вручную, чтобы иметь полный контроль над тем, как будет отображаться содержимое комментария, - только те HTML-теги, которые вы выбрали.Белый список вместо черного списка.
Не отображать пользовательские атрибуты HTML.
Очистка HTML на сервере не требуется, поскольку в браузере HTML никогда не будет отображаться как есть., но вы все равно можете продезинфицировать его, если хотите заранее обрезать жир.
Вот базовый пример:
Vue.component('comment-content', {
functional: true,
props: {
html: {},
allowedElements: {
default: () => ['p', 'i', 'b', 'ul', 'li'],
},
},
render(h, ctx) {
const { html, allowedElements } = ctx.props;
const renderNode = node => {
switch (node.nodeType) {
case Node.TEXT_NODE: return renderTextNode(node);
case Node.ELEMENT_NODE: return renderElementNode(node);
}
};
const renderTextNode = node => {
return node.nodeValue;
};
const renderElementNode = node => {
const tag = node.tagName.toLowerCase();
if (allowedElements.includes(tag)) {
const children = [...node.childNodes].map(node => renderNode(node));
return h(tag, children);
}
};
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
return [...doc.body.childNodes].map(node => renderNode(node));
},
});
new Vue({
el: '#app',
data: {
html: `
<p>Paragraph</p>
<ul>
<li>One <script>alert('Hacked')<\/script></li>
<li onmouseover="alert('Hacked')">Two</li>
<li style="color: red">Three <b>bold</b> <i>italic</i></li>
<li>Four <img src="javascript:alert('Hacked')"></li>
</ul>
<section>This element isn't allowed</section>
<p>Last paragraph</p>
`,
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<comment-content :html="html"></comment-content>
</div>