Skip to content

Commit

Permalink
Add no innerHTML rule
Browse files Browse the repository at this point in the history
  • Loading branch information
manuelpuyol committed Sep 9, 2021
1 parent 641649a commit 2599d2a
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 1 deletion.
19 changes: 19 additions & 0 deletions docs/rules/no-innter-html.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# No `innerHTML`

Using `innerHTML` poses a potential security risk. It should only be used when clearing content.

```js
// bad
function setContent(element, content) {
element.innerHTML = content
}

// good
function clearContent(element) {
element.innerHTML = ''
}
```

## See Also

https://github.com/github/paste-markdown/security/advisories/GHSA-gpfj-4j6g-c4w9
1 change: 1 addition & 0 deletions lib/configs/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module.exports = {
'github/no-blur': 'error',
'github/no-dataset': 'error',
'github/no-innerText': 'error',
'github/no-inner-html': 'error',
'github/unescaped-html-literal': 'error',
'github/no-useless-passive': 'error',
'github/require-passive-events': 'error',
Expand Down
2 changes: 1 addition & 1 deletion lib/configs/typescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module.exports = {
camelcase: 'off',
'no-unused-vars': 'off',
'no-shadow': 'off',
'no-invalid-this': "off",
'no-invalid-this': 'off',
'@typescript-eslint/no-invalid-this': ['error'],
'@typescript-eslint/no-shadow': ['error'],
'@typescript-eslint/interface-name-prefix': 'off',
Expand Down
1 change: 1 addition & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = {
'no-dataset': require('./rules/no-dataset'),
'no-implicit-buggy-globals': require('./rules/no-implicit-buggy-globals'),
'no-innerText': require('./rules/no-innerText'),
'no-inner-html': require('./rules/no-inner-html'),
'no-then': require('./rules/no-then'),
'unescaped-html-literal': require('./rules/unescaped-html-literal'),
'no-useless-passive': require('./rules/no-useless-passive'),
Expand Down
33 changes: 33 additions & 0 deletions lib/rules/no-inner-html.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module.exports = {
meta: {
type: 'problem',
docs: {
description: 'disallow `Element.prototype.innerHTML``',
url: require('../url')(module)
},
schema: []
},

create(context) {
return {
AssignmentExpression(node) {
if (node.operator === "=") {
const leftNode = node.left;
const rightNode = node.right;

if (leftNode.property && leftNode.property.name === 'innerHTML') {
if (rightNode.type === 'Literal' && rightNode.value === '') {
return
}

context.report({
node: node,
message:
'Using innerHTML poses a potential security risk and should not be used other than cleaning content.'
})
}
}
}
}
}
}
34 changes: 34 additions & 0 deletions tests/no-inner-html.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const rule = require('../lib/rules/no-inner-html')
const RuleTester = require('eslint').RuleTester

const ruleTester = new RuleTester()

ruleTester.run('no-innter-html', rule, {
valid: [
{
code: 'document.createElement("js-flash-text").innerHTML = ""'
}
],
invalid: [
{
code: 'document.createElement("js-flash-text").innerHTML = "foo"',
errors: [
{
message:
'Using innerHTML poses a potential security risk and should not be used other than cleaning content.',
type: 'AssignmentExpression'
}
]
},
{
code: 'document.querySelector("js-flash-text").innerHTML = "<div>code</div>"',
errors: [
{
message:
'Using innerHTML poses a potential security risk and should not be used other than cleaning content.',
type: 'AssignmentExpression'
}
]
}
]
})

0 comments on commit 2599d2a

Please sign in to comment.