Vue Sanitize Directive
vue-sanitize-directive is a Vue.js directive designed for declarative HTML sanitization within templates, powered by the flexible `sanitize-html` library. It provides a `v-sanitize` directive that can be used to remove potentially unsafe HTML content from user-provided input, offering various modifiers like `.strip`, `.basic`, `.inline`, and `.nothing` for different sanitization levels. The current stable version is 0.2.1. Recent updates in version 0.2.0 introduced support for both Vue 2.x and Vue 3.x, alongside experimental server-side rendering (SSR) capabilities. This package differentiates itself by integrating robust `sanitize-html` functionality directly into Vue's templating system, simplifying the process of displaying user-generated content safely. While convenient for client-side display, the documentation explicitly warns that primary validation and sanitization of user-provided input should always occur on the backend for robust security.
Common errors
-
Failed to resolve directive: sanitize
cause The `vue-sanitize-directive` plugin has not been correctly installed and registered with your Vue application instance.fixEnsure you have called `app.use(VueSanitize)` (for Vue 3) or `Vue.use(VueSanitize)` (for Vue 2) in your application's entry point (e.g., `main.ts` or `main.js`) after importing `VueSanitize`. -
My HTML is not being sanitized as expected; some tags or attributes are still present.
cause This often occurs after upgrading to `vue-sanitize-directive` v0.2.0+, due to breaking changes in `sanitize-html` v2.x which introduced new, stricter default allowed tags and attributes. Your content might contain tags that are no longer allowed by default.fixIf specific tags or attributes are needed, provide a custom allowlist array as the first argument to the directive: `<div v-sanitize="[myCustomAllowlist, unsafeHtml]"></div>`. Consult the `sanitize-html` documentation for detailed configuration options.
Warnings
- breaking Version 0.2.0 introduced a breaking change by updating the underlying `sanitize-html` library to 2.7.0. `sanitize-html` version 2.x has significantly different default allowed tags and attributes compared to 1.x.
- gotcha Client-side HTML sanitization using `v-sanitize` should not be the sole security measure for user-provided input. Backend validation and sanitization are crucial to prevent XSS and other vulnerabilities, especially before storing data in a database.
- gotcha The `.nothing` modifier effectively bypasses all sanitization, making `v-sanitize.nothing` functionally equivalent to `v-html`. Using this modifier with untrusted input can introduce Cross-Site Scripting (XSS) vulnerabilities.
- gotcha `sanitize-html` (the underlying library) version 2.7.0 and prior had known vulnerabilities, including Regular Expression Denial of Service (ReDoS) and Information Exposure issues. While `vue-sanitize-directive` bundles `sanitize-html`, older bundled versions might be susceptible.
Install
-
npm install vue-sanitize-directive -
yarn add vue-sanitize-directive -
pnpm add vue-sanitize-directive
Imports
- VueSanitize
const VueSanitize = require('vue-sanitize-directive')import VueSanitize from 'vue-sanitize-directive'
- v-sanitize
<div v-sanitize="unsafeHtml"></div>
- VueSanitizeDirectiveSSR
import { VueSanitizeDirectiveSSR } from 'vue-sanitize-directive'
Quickstart
import { createApp } from 'vue';
import VueSanitize from 'vue-sanitize-directive';
const app = createApp({
data() {
return {
unsafeHtml: '<p>Hello <script>alert("XSS")</script> World! <a href="javascript:alert(\'XSS\')">Click me</a> <span style="color: red;">Red Text</span></p>',
anotherUnsafeHtml: '<div><img src="x" onerror="alert(\'XSS\')"></div>',
customAllowedTags: ['p', 'span', 'strong']
};
},
template: `
<div>
<h1>Vue Sanitize Directive Demo</h1>
<h2>Default (.basic) Sanitization</h2>
<p>Original: {{ unsafeHtml }}</p>
<div v-sanitize="unsafeHtml"></div>
<hr>
<h2>.strip Modifier (removes all tags)</h2>
<p>Original: {{ unsafeHtml }}</p>
<div v-sanitize.strip="unsafeHtml"></div>
<hr>
<h2>Custom Allowlist (only p, span, strong)</h2>
<p>Original: {{ unsafeHtml }}</p>
<div v-sanitize="[customAllowedTags, unsafeHtml]"></div>
<hr>
<h2>.nothing Modifier (be careful!)</h2>
<p>Original: {{ anotherUnsafeHtml }}</p>
<div v-sanitize.nothing="anotherUnsafeHtml"></div>
</div>
`
});
app.use(VueSanitize);
app.mount('#app');