-
-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
159 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# vue-i18n/no-v-html | ||
|
||
> disallow use of localization methods on v-html to prevent XSS attack | ||
- :star: The `"extends": "plugin:vue-i18n/recommended"` property in a configuration file enables this rule. | ||
|
||
This rule reports all uses of localization methods on `v-html` directive in order to reduce the risk of injecting potentially unsafe / unescaped html into the browser leading to Cross-Site Scripting (XSS) attacks. | ||
|
||
## :book: Rule Details | ||
|
||
You can be detected with this rule the following: | ||
|
||
- `$t` | ||
- `t` | ||
- `$tc` | ||
- `tc` | ||
|
||
:-1: Examples of **incorrect** code for this rule: | ||
|
||
locale messages: | ||
```json | ||
{ | ||
"term": "<p>I accept xxx <a href=\"\/term\">Terms of Service Agreement</a></p>" | ||
} | ||
``` | ||
|
||
localization codes: | ||
|
||
```vue | ||
<template> | ||
<div class="app"> | ||
<!-- ✗ BAD --> | ||
<p v-html="$t('term')"></p> | ||
</div> | ||
</template> | ||
``` | ||
|
||
:+1: Examples of **correct** code for this rule: | ||
|
||
locale messages: | ||
```json | ||
{ | ||
"tos": "Term of Service", | ||
"term": "I accept xxx {0}." | ||
} | ||
``` | ||
|
||
localization codes: | ||
|
||
```vue | ||
<template> | ||
<div class="app"> | ||
<!-- ✗ GOOD --> | ||
<i18n path="term" tag="label" for="tos"> | ||
<a :href="url" target="_blank">{{ $t('tos') }}</a> | ||
</i18n> | ||
</div> | ||
</template> | ||
``` | ||
|
||
## :mute: When Not To Use It | ||
|
||
If you are certain the content passed to `v-html` is sanitized HTML you can disable this rule. | ||
|
||
## :books: Further reading | ||
|
||
- [XSS in Vue.js](https://blog.sqreen.io/xss-in-vue-js/) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/** | ||
* @author kazuya kawaguchi (a.k.a. kazupon) | ||
*/ | ||
'use strict' | ||
|
||
const { defineTemplateBodyVisitor } = require('../utils/index') | ||
|
||
function checkDirective (context, node) { | ||
if ((node.value && node.value.type === 'VExpressionContainer') && | ||
(node.value.expression && node.value.expression.type === 'CallExpression')) { | ||
const expressionNode = node.value.expression | ||
const funcName = (expressionNode.callee.type === 'MemberExpression' && expressionNode.callee.property.name) || expressionNode.callee.name | ||
if (!/^(\$t|t|\$tc|tc)$/.test(funcName) || !expressionNode.arguments || !expressionNode.arguments.length) { | ||
return | ||
} | ||
context.report({ | ||
node, | ||
message: `Using ${funcName} on 'v-html' directive can lead to XSS attack.` | ||
}) | ||
} | ||
} | ||
|
||
function create (context) { | ||
return defineTemplateBodyVisitor(context, { | ||
"VAttribute[directive=true][key.name='html']" (node) { | ||
checkDirective(context, node) | ||
}, | ||
|
||
"VAttribute[directive=true][key.name.name='html']" (node) { | ||
checkDirective(context, node) | ||
} | ||
}) | ||
} | ||
|
||
module.exports = { | ||
meta: { | ||
type: 'suggestion', | ||
docs: { | ||
description: 'disallow use of localization methods on v-html to prevent XSS attack', | ||
category: 'Possible Errors', | ||
recommended: true | ||
}, | ||
fixable: null, | ||
schema: [] | ||
}, | ||
create | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/** | ||
* @author kazuya kawaguchi (a.k.a. kazupon) | ||
*/ | ||
'use strict' | ||
|
||
const RuleTester = require('eslint').RuleTester | ||
const rule = require('../../../lib/rules/no-v-html') | ||
|
||
const tester = new RuleTester({ | ||
parser: 'vue-eslint-parser', | ||
parserOptions: { ecmaVersion: 2015 } | ||
}) | ||
|
||
tester.run('no-v-html', rule, { | ||
valid: [{ | ||
code: `<template> | ||
<div class="app"> | ||
<i18n path="term" tag="label" for="tos"> | ||
<a :href="url" target="_blank">{{ $t('tos') }}</a> | ||
</i18n> | ||
</div> | ||
</template>` | ||
}], | ||
|
||
invalid: [{ | ||
code: `<template> | ||
<p v-html="$t('hello')"></p> | ||
</template>`, | ||
errors: [ | ||
`Using $t on 'v-html' directive can lead to XSS attack.` | ||
] | ||
}, { | ||
code: `<template> | ||
<p v-html="this.t('hello')"></p> | ||
</template>`, | ||
errors: [ | ||
`Using t on 'v-html' directive can lead to XSS attack.` | ||
] | ||
}] | ||
}) |