Vue: Sanitize v-html

Created on 9 Aug 2017  路  10Comments  路  Source: vuejs/vue

What problem does this feature solve?

I'm currently working on making a blog using the WordPress REST API as the back end. The API returns the article with HTML markup in it. I'm taking that JSON response and using v-html to render it into my Vue app. I understand there are cross-site scripting security risks here.

What does the proposed API look like?

It would be great if v-html automatically sanitized the string to remove any <script> tags. For those needing script tags, for whatever reason, maybe v-html-unsafe can accomplish that.

I was recently made aware Angular 4 is doing this and think Vue.js would greatly benefit from this feature.

https://angular.io/guide/security#!#xss

feature request

Most helpful comment

I agree with @rpkilby - shipping a built-in sanitizer would add extra bundle weight for a rare use case (when most use cases of v-html are for trusted content); it is also trivial to add sanitize-html by setting Vue.prototype.$sanitize = sanitizeHTML and then do v-html="$sanitize(html)".

All 10 comments

That would be a breaking change, what can be done instead is adding a ~.safe~ .sanitize modifier that strips off the <script> tags.

This can be easily handled in a computed property or with a utility function

Just to clarify, are you saying that changing the default behavior of v-html would be the breaking change?

I guess ideally it would be nice if v-html was sanitized by default, but your suggestion using a .safe modifier sounds great too. So would that look like v-html.safe="data"?

Hi. Just my two cents, but I would be -1 on this. It seems unnecessary for Vue to maintain its own html sanitizer, given that there are other libraries that already do this well. I'd argue that there are more appropriate places to perform sanitization and that also allow for better developer control. A few ideas:

  • Sanitize the HTML before persisting it to the database or before returning the JSON response.
  • Sanitize the HTML in a Vue computed property. This would be useful if you're unable to modify the WordPress backend. You might try calling this library in the property.

Also, worth mentioning that the docs have appropriate warnings in both the guide and reference sections.

@rpkilby sanitize-html seems great and will work for me and my use case. I still think it would be nice if Vue did this automatically as an added security measure, but I absolutely hear your concerns.

Thanks for your input and that link.

I don't think it's a good idea for Vue to add a built-in html-sanitizer either.
How about introducing a new config (e.g. Vue.config.htmlSanitizer = (html) => safeHtml ) as a compromised way?

I agree with @rpkilby - shipping a built-in sanitizer would add extra bundle weight for a rare use case (when most use cases of v-html are for trusted content); it is also trivial to add sanitize-html by setting Vue.prototype.$sanitize = sanitizeHTML and then do v-html="$sanitize(html)".

@yyx990803 I know this is an older thread but setting Vue.prototype.$sanitize = sanitizeHTML it throws Uncaught ReferenceError: sanitizeHTML is not defined`. I know sanitizeHTML is defined as I've previously imported it and used it (before Vue is called)

@Braunson
Vue.prototype.$sanitize = sanitizeHTML Work fine for me (I am using Vue build SPA with Vuex and vue-router)
Version: "vue": "^2.5.17"

Here is how I do it:

Command line

npm install sanitize-html

src/main.js

import sanitizeHTML from 'sanitize-html';
Vue.prototype.$sanitize = sanitizeHTML

src/pages/Topic.vue

div(v-html='$sanitize(topic.content_html)')

One Problem: by default sanitize-html would remove <img>

How to fix this: (https://github.com/punkave/sanitize-html#readme)

clean = sanitizeHtml(dirty, {
  allowedTags: sanitizeHtml.defaults.allowedTags.concat([ 'img' ])
});

I agree with @rpkilby - shipping a built-in sanitizer would add extra bundle weight for a rare use case (when most use cases of v-html are for trusted content); it is also trivial to add sanitize-html by setting Vue.prototype.$sanitize = sanitizeHTML and then do v-html="$sanitize(html)".

Im wondered that most popular libraries to sanitize HTML string are extremely huge (each one is bigger that my whole Vue.js app bundle)...
https://www.npmjs.com/package/sanitize-html
https://www.npmjs.com/package/dompurify
https://www.npmjs.com/package/xss
https://www.npmjs.com/package/string-strip-html

I have created simple & fast solution without regex, but I know that it is more secure to use popular well-tested libs. But I would like to know your opinion to this solution https://jsfiddle.net/n10L6a5u/ It is Vue.js plugin for custom directive v-html-safe which removes just insecure XSS things like attributes starting "on" (e.g.: onload, onerror, ...) and also attribute values starting "javascript:" (e.g. href="javascript:alert(1)"). Do you see some potential issues there?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

paceband picture paceband  路  3Comments

wufeng87 picture wufeng87  路  3Comments

6pm picture 6pm  路  3Comments

julianxhokaxhiu picture julianxhokaxhiu  路  3Comments

bfis picture bfis  路  3Comments