Skip to content
5 changes: 5 additions & 0 deletions .changeset/purple-lights-invite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'eslint-plugin-vue': minor
---

Added `ignorePattern` option to [`vue/no-v-html`](https://eslint.vuejs.org/rules/no-v-html.html)
19 changes: 18 additions & 1 deletion lib/rules/no-v-html.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/
'use strict'
const utils = require('../utils')
const { toRegExp } = require('../utils/regexp')

module.exports = {
meta: {
Expand All @@ -14,16 +15,32 @@ module.exports = {
url: 'https://eslint.vuejs.org/rules/no-v-html.html'
},
fixable: null,
schema: [],
schema: [{
type: 'object',
properties: {
ignorePattern: {
type: 'string'
}
}
}],
messages: {
unexpected: "'v-html' directive can lead to XSS attack."
}
},
/** @param {RuleContext} context */
create(context) {
const options = context.options[0]
let ignoredVarMatcher = null
if (options?.ignorePattern) {
ignoredVarMatcher = toRegExp(options.ignorePattern, { remove: 'g' })
}

return utils.defineTemplateBodyVisitor(context, {
/** @param {VDirective} node */
"VAttribute[directive=true][key.name.name='html']"(node) {
if (ignoredVarMatcher !== null && node.value.expression.type === 'Identifier' && ignoredVarMatcher.test(node.value.expression.name)) {
return
}
context.report({
node,
loc: node.loc,
Expand Down
11 changes: 11 additions & 0 deletions tests/lib/rules/no-v-html.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ ruleTester.run('no-v-html', rule, {
{
filename: 'test.vue',
code: '<template><div v-if="foo" v-bind="bar"></div></template>'
},
{
filename: 'test.vue',
code: '<template><div v-html="knownHtml"></div></template>',
options: [{ignorePattern: '/^(?:html|.+Html)$/'}]
}
],
invalid: [
Expand All @@ -45,6 +50,12 @@ ruleTester.run('no-v-html', rule, {
filename: 'test.vue',
code: '<template><section v-html/></template>',
errors: ["'v-html' directive can lead to XSS attack."]
},
{
filename: 'test.vue',
code: '<template><div v-html="unsafeString"></div></template>',
options: [{ignorePattern: '^(?:html|.+Html)$'}],
errors: ["'v-html' directive can lead to XSS attack."]
}
]
})