0 day streak
javascript / intermediate
Snippet

Securing User-Provided Markup via Custom Vue Directive Binding

Binding raw user markup directly to v-html exposes components to Cross-Site Scripting (XSS) attacks. A custom Vue directive encapsulates strict DOMPurify sanitization during both element mounting and reactive updates, enforcing an allowlist of safe HTML tags and attributes.

snippet.js
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import DOMPurify from 'dompurify';
export const vSafeHtml = {
mounted(el, binding) {
const cleanContent = DOMPurify.sanitize(binding.value || '', {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a'],
ALLOWED_ATTR: ['href', 'target']
});
el.innerHTML = cleanContent;
},
updated(el, binding) {
if (binding.value !== binding.oldValue) {
el.innerHTML = DOMPurify.sanitize(binding.value || '', {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a'],
ALLOWED_ATTR: ['href', 'target']
});
}
}
};
vue
Breakdown
1
const cleanContent = DOMPurify.sanitize(binding.value || '', {
Executes HTML sanitization on the bound string input using configured safety options.
2
if (binding.value !== binding.oldValue) {
Compares new and old directive values to prevent redundant DOM updates on re-renders.
3
el.innerHTML = cleanContent;
Applies the vetted and harmless sanitized HTML string to the target DOM element.