Sanitize html vuejs

As part of my goal to learn more about Vue (and, honestly, find things to blog about), I came across this interesting StackOverflow post: How to Sanitize HTML Received from an API Call in Vue.js. I did a quick Google search and came across a nice little library that makes this easy - vue-sanitize. I thought it would be nice to give it a try (especially since I was suggesting it as a solution) so I whipped up a quick demo.

Before I start though, it’s good to remember how Vue treats HTML in data in general. Consider the following data:

message:`
My <strong>milkshake</strong> brings all the boys to the yard<br/>
And <i>they're</i> like, it's better than yours
`

Enter fullscreen mode Exit fullscreen mode

This is a string with three HTML tags in it. Nothing scary, but let’s see what happens if you try to output it:

<template>
  <div>
    {{ message }}
  </div>
</template>

Enter fullscreen mode Exit fullscreen mode

This will return:

My <strong>milkshake</strong> brings all the boys to the yard<br/> 
And <i>they're</i> like, it's better than yours 

Enter fullscreen mode Exit fullscreen mode

As you can see, the HTML is escaped. Not ideal, right? If you know you can trust the data, you can use the v-html directive:

<template>
  <div>
    <span v-html="message"></span>
  </div>
</template>

Enter fullscreen mode Exit fullscreen mode

This will return what you expect. Cool! But… it’s very black and white. You either escape all HTML or allow all HTML. What if you want something in between? This is where vue-sanitize comes in. Not only will it allow you to use a whitelist of “safe” HTML tags, it will remove disallowed tags rather than escaping them.

Using it is pretty simple and covered in the docs. Add the NPM package, and once done, you can then add it to your Vue.js code. From what I can see there’s no support for “script tag Vue”, so you’ll need to have a proper Vue application.

Outside of that, there’s only one main API, this.$sanitize(someVariable). This will return a string with unsafe HTML tags removed. You still need to use v-html to render the safe HTML of course.

The docs don’t mention the defaults, but as the library wraps another library, sanitize-html, you can check their docs for the defaults:

Sanitize html vuejs

Let me demonstrate an example before I show how you can customize the defaults. First, my main.js, which just loads in the library.

import Vue from "vue";
import App from "./App.vue";

import VueSanitize from "vue-sanitize";

Vue.use(VueSanitize);

Vue.config.productionTip = false;

new Vue({
  render: h => h(App)
}).$mount("#app");

Enter fullscreen mode Exit fullscreen mode

And now my test:

<template>
  <div>
    Escaped: {{ message }}
    <p/>
    <span v-html="message"></span>
    <hr/>
    <span v-html="cleanMessage"></span>
  </div>
</template>

<script>

export default {
  name: "App",
  data() {
    return {
      message:`
        My <strong>milkshake</strong> brings all the boys to the yard<br/>
        And <i>they're</i> like, it's better than yours
      `
    }    
  },
  computed:{
    cleanMessage() {
      return this.$sanitize(this.message);
    }
  }
};
</script>

Enter fullscreen mode Exit fullscreen mode

So I begin with two simple tests related to what I said before - the default behavior in Vue and the use of v-html. I don’t use the sanitize code until

<template>
  <div>
    {{ message }}
  </div>
</template>

1. I’ve got that bound to a computed value that returns the sanitized version. The output is:

Sanitize html vuejs

In this case, there’s no difference between the built-in version and the sanitize version. I only used three simple HTML tags. Let’s see what happens when we change the defaults.

In order to change the defaults, you create your own object containing the defaults you would like. The main sanitize-html site has some good examples on how to slightly modify the built in defaults. For my testing, I wanted to allow everything the defaults allowed, except for the

<template>
  <div>
    {{ message }}
  </div>
</template>

2 tag. This is how I did it.

import Vue from "vue";
import App from "./App.vue";

import VueSanitize from "vue-sanitize";

let defaults = VueSanitize.defaults;

defaults.allowedTags = defaults.allowedTags.filter(t => {
  return t !== 'strong';
});

Vue.use(VueSanitize,defaults);

Vue.config.productionTip = false;

new Vue({
  render: h => h(App)
}).$mount("#app");

Enter fullscreen mode Exit fullscreen mode

Basically - loop through the array of

<template>
  <div>
    {{ message }}
  </div>
</template>

3 and remove when the tag name is
<template>
  <div>
    {{ message }}
  </div>
</template>

4. It’s easier if you just want to define a short list of tags you want - just pass an array of strings.

The result is as you expect:

Sanitize html vuejs

Notice though that the

<template>
  <div>
    {{ message }}
  </div>
</template>

2 tag wasn’t escaped, it was removed. That’s much better than escaping it (typically). I could see this being really useful for allowing all the format tags but removing
<template>
  <div>
    {{ message }}
  </div>
</template>

6 for example. (And
<template>
  <div>
    {{ message }}
  </div>
</template>

7 and probably other’s I’ve forgotten.)

Anyway, I hope this is helpful. I’ve got a CodeSandbox with this running and you can play with it below.

Does Vue sanitize HTML?

Vue's default v-text is HTML-insensitive, while v-html doesn't perform sanitization by default.

Is V

Dynamically rendering arbitrary HTML on your website can be very dangerous because it can easily lead to XSS vulnerabilities. Only use HTML interpolation on trusted content and never on user-provided content.

How to include HTML in Vue?

The simplest way to get started with Vue is to grab the development version script for it and add it to the head tag of your HTML file. Then you can start Vue code inside the HTML file inside of script tags. And have the Vue code connect up with an existing element on your HTML page.

How to sanitize string in JavaScript?

The default Sanitizer() configuration strips out XSS-relevant input by default, including <script> tags, custom elements, and comments. The sanitizer configuration may be customized using Sanitizer() constructor options. Note: To sanitize strings, instead use Element. setHTML() or Sanitizer.