2

I am trying to use the DOMPurify package in my NuxtJS app for parsing HTML into clean and safe strings for rendering in the UI. When rendering the page where the package is used, I get the following error:

dompurify__WEBPACK_IMPORTED_MODULE_1___default.a.sanitize is not a function

Any advice on how I can fix this? I have this code available in a codesandbox here: https://codesandbox.io/s/reverent-bardeen-kh4wg?file=/pages/index.vue:0-2868

I have imported the package in my single file component like so:

<template>
  ......cut unnecessary code for this example...
        <textarea
          id="title_input"
          v-model.trim="formValues.title"
          class="form-control form-control-lg border-0 fw-bold lh-1 fs-1 mb-3"
          placeholder="New post title here..."
          maxlength="80"
          rows="2"
          minlength="6"
          autocomplete="off"
          required
          aria-describedby="titleHelpBlock"
        ></textarea>
        <textarea
          id="content_input"
          v-model.trim="formValues.content"
          class="form-control border-0 h-100"
          rows="3"
          minlength="30"
          maxlength="1000"
          autocomplete="off"
          placeholder="Write your post here..."
          required
          aria-describedby="contentHelpBlock"
        ></textarea>
      
  .....
</template>

<script>
import { debounce } from "lodash";
import DOMPurify from "dompurify";
import marked from "marked";
export default {
  name: "UploadForm",
  data() {
    return {
      formValues: {
        title: "New post title here...",
        content: "Write your post here...",
      },
    };
  },
  computed: {
    compiledMarkdown() {
      // only need the HTML profile, not SVG andMathML stuff
      const clean = DOMPurify.sanitize(this.formValues.title, {
        USE_PROFILES: { html: true },
      });
      return marked(clean);
    },
  },
  methods: {
    update: debounce(function (e) {
      this.input = e.target.value;
    }, 300),
    updateTitle: debounce(function (e) {
      this.formValues.title = e.target.value;
    }, 300),
    updateContent: debounce(function (e) {
      this.formValues.content = e.target.value;
    }, 300),
  },
};
</script>
kissu
  • 40,416
  • 14
  • 65
  • 133
redshift
  • 4,815
  • 13
  • 75
  • 138
  • I never used the `dompurify` one directly. Meanwhile, the Vue wrapper works super great: https://www.npmjs.com/package/vue-dompurify-html Give it a try and let us know if it's better. – kissu Sep 06 '21 at 10:06
  • OK! Ill get back to you – redshift Sep 06 '21 at 10:07
  • Same issue! `VueDOMPurifyHTML is not defined` . Updated my codesandbox. Am I not accessing the plugin correclty? – redshift Sep 06 '21 at 10:32
  • Seems to be fine now. I thought I needed to add `VueDOMPurifyHTML` to computed but removing that seems to fix it. I just need to use it in `v-dompurify-html` directive. – redshift Sep 06 '21 at 11:17
  • Yeah, import + directive is enough to make it work. – kissu Sep 06 '21 at 12:41

2 Answers2

2

You cannot use v-html as a directive directly because it can lead to XSS: https://v2.vuejs.org/v2/guide/syntax.html#Raw-HTML

Therefore you need to sanitize some of those user inputs.
To achieve this in Vue/Nuxt, I do recommend to use vue-dompurify-html

Some steps to follow

  • install it with yarn add vue-dompurify-html
  • import it in your .vue file like this
import Vue from 'vue'
import VueDOMPurifyHTML from 'vue-dompurify-html'
 
Vue.use(VueDOMPurifyHTML)
  • use it in your template like this
<div>
  <div v-dompurify-html="rawHtml"></div>
</div>

PS: if you want to use it into a Vue2 app, still to the v2.5.2, higher version only support Vue3.

kissu
  • 40,416
  • 14
  • 65
  • 133
  • After some further testing on this, it seems that if you disable javascript, the purified content won't load because vue-dompurify requires JS. Can you confirm? – redshift Oct 05 '21 at 13:41
  • @redshift yep, seems legit! – kissu Oct 05 '21 at 15:06
  • I was only needing to sanitize the markdown during user form input which was client side anyways, and using vue dompurify was fine for that). For reading the content during SSR, I just used v-html for that which worked fine with javascript off (disabled eslint XSS warning for that). – redshift Oct 05 '21 at 15:16
  • @redshift not sure that disabling the warning is a good idea because XSS can be serious, especially since it's coming from end user's input. – kissu Oct 05 '21 at 19:22
  • 1
    I am just disabling it on a page where it appears after content has been sanitized prior. – redshift Oct 06 '21 at 18:58
1

If you want to use it as a Nuxt 3 plugin just create a file plugins/vue-dompurify-html.js with this code:

import VueDOMPurifyHTML from 'vue-dompurify-html'

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.use(VueDOMPurifyHTML)
})

After this you can use it in any component without importing:

<div v-dompurify-html="rawHtml"></div>
Dollique
  • 952
  • 2
  • 10
  • 29