Vue.js framework prevents XSS vulnerabilities by automatically escaping HTML contents with the use of native API browsers like
innerText instead of innerHtml.
It’s still possible to explicity use innerHtml and similar APIs to render HTML. Accidentally rendering malicious HTML data will
introduce an XSS vulnerability in the application and enable a wide range of serious attacks like accessing/modifying sensitive information or
impersonating other users.
Ask Yourself Whether
The application needs to render HTML content which:
- could be user-controlled and not previously sanitized.
- is difficult to understand how it was constructed.
There is a risk if you answered yes to any of those questions.
Recommended Secure Coding Practices
- Avoid injecting HTML content with
v-html directive unless the content can be considered 100% safe, instead try to rely as much as
possible on built-in auto-escaping Vue.js features.
- Take care when using the
v-bind:href directive to set URLs which can contain malicious Javascript
(javascript:onClick(...)).
- Event directives like
:onmouseover are also prone to Javascript injection and should not be used with unsafe values.
Sensitive Code Example
When using Vue.js templates, the v-html directive enables HTML rendering without any sanitization:
<div v-html="htmlContent"></div> <!-- Noncompliant -->
When using a rendering function, the innerHTML attribute enables HTML rendering without any sanitization:
Vue.component('element', {
render: function (createElement) {
return createElement(
'div',
{
domProps: {
innerHTML: this.htmlContent, // Noncompliant
}
}
);
},
});
When using JSX, the domPropsInnerHTML attribute enables HTML rendering without any sanitization:
<div domPropsInnerHTML={this.htmlContent}></div> <!-- Noncompliant -->
Compliant Solution
When using Vue.js templates, putting the content as a child node of the element is safe:
<div>{{ htmlContent }}</div>
When using a rendering function, using the innerText attribute or putting the content as a child node of the element is safe:
Vue.component('element', {
render: function (createElement) {
return createElement(
'div',
{
domProps: {
innerText: this.htmlContent,
}
},
this.htmlContent // Child node
);
},
});
When using JSX, putting the content as a child node of the element is safe:
<div>{this.htmlContent}</div>
See