Skip to content

Commit 38088ac

Browse files
committed
Rule fix: no-append-html: Allow passing selectors to some methods
Fixes #326
1 parent bd0218c commit 38088ac

File tree

3 files changed

+29
-4
lines changed

3 files changed

+29
-4
lines changed

docs/rules/no-append-html.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22

33
# no-append-html
44

5-
Disallows using [`.append`](https://api.jquery.com/append/)/[`.prepend`](https://api.jquery.com/prepend/)/[`.before`](https://api.jquery.com/before/)/[`.after`](https://api.jquery.com/after/)/[`.replaceWith`](https://api.jquery.com/replaceWith/)/[`.add`](https://api.jquery.com/add/)/[`.appendTo`](https://api.jquery.com/appendTo/)/[`.prependTo`](https://api.jquery.com/prependTo/) to inject HTML, in order to prevent possible XSS bugs.
5+
Disallows using [`.append`](https://api.jquery.com/append/)/[`.prepend`](https://api.jquery.com/prepend/)/[`.before`](https://api.jquery.com/before/)/[`.after`](https://api.jquery.com/after/)/[`.replaceWith`](https://api.jquery.com/replaceWith/)/[`.add`](https://api.jquery.com/add/)/[`.appendTo`](https://api.jquery.com/appendTo/)/[`.prependTo`](https://api.jquery.com/prependTo/)/[`.insertBefore`](https://api.jquery.com/insertBefore/)/[`.insertAfter`](https://api.jquery.com/insertAfter/) to inject HTML, in order to prevent possible XSS bugs.
66

77
## Rule details
88

99
❌ Examples of **incorrect** code:
1010
```js
1111
$div.append( '<xss>' );
12+
$div.append( 'unescaped html' );
1213
$div.prepend( '<xss>' );
1314
$div.before( '<xss>' );
1415
$div.after( '<xss>' );
@@ -47,6 +48,12 @@ $div.append( test ? $el1 : '' );
4748

4849
$el = getSomething();
4950
$div.append( $el );
51+
52+
$div.add( '.foo' );
53+
$div.appendTo( '.foo' );
54+
$div.prependTo( '.foo' );
55+
$div.insertBefore( '.foo' );
56+
$div.insertAfter( '.foo' );
5057
```
5158

5259
## Resources

src/rules/no-append-html.js

+12-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
'use strict';
22

33
const utils = require( '../utils.js' );
4-
const methods = [ 'append', 'prepend', 'before', 'after', 'replaceWith', 'add', 'appendTo', 'prependTo' ];
4+
// htmlStrings or jQuery collections
5+
const htmlOrCollectionMethods = [ 'append', 'prepend', 'before', 'after', 'replaceWith' ];
6+
// htmlStrings, selectors or jQuery collections
7+
const htmlOrSelectorOrCollectionMethods = [ 'add', 'appendTo', 'prependTo', 'insertBefore', 'insertAfter' ];
8+
const allMethods = htmlOrCollectionMethods.concat( htmlOrSelectorOrCollectionMethods );
59

610
function alljQueryOrEmpty( context, node ) {
711
if ( node.type === 'ConditionalExpression' ) {
@@ -22,7 +26,7 @@ module.exports = {
2226
meta: {
2327
type: 'suggestion',
2428
docs: {
25-
description: 'Disallows using ' + methods.map( utils.jQueryCollectionLink ).join( '/' ) +
29+
description: 'Disallows using ' + allMethods.map( utils.jQueryCollectionLink ).join( '/' ) +
2630
' to inject HTML, in order to prevent possible XSS bugs.'
2731
},
2832
schema: []
@@ -32,13 +36,18 @@ module.exports = {
3236
'CallExpression:exit': ( node ) => {
3337
if ( !(
3438
node.callee.type === 'MemberExpression' &&
35-
methods.includes( node.callee.property.name )
39+
allMethods.includes( node.callee.property.name )
3640
) ) {
3741
return;
3842
}
3943
if ( node.arguments.every( ( arg ) => alljQueryOrEmpty( context, arg ) ) ) {
4044
return;
4145
}
46+
if ( htmlOrSelectorOrCollectionMethods.includes( node.callee.property.name ) ) {
47+
if ( node.arguments.every( ( arg ) => !utils.isHtmlString( arg ) ) ) {
48+
return;
49+
}
50+
}
4251

4352
if ( utils.isjQuery( context, node.callee ) ) {
4453
context.report( {

tests/rules/no-append-html.js

+9
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ ruleTester.run( 'no-append-html', rule, {
2727
'$div.append(test ? $el1 : undefined)',
2828
'$div.append(test ? $el1 : "")',
2929
'$el=getSomething();\n$div.append($el);',
30+
'$div.add(".foo")',
31+
'$div.appendTo(".foo")',
32+
'$div.prependTo(".foo")',
33+
'$div.insertBefore(".foo")',
34+
'$div.insertAfter(".foo")',
3035
{
3136
code: 'div.append("<xss>")',
3237
docgen: false
@@ -37,6 +42,10 @@ ruleTester.run( 'no-append-html', rule, {
3742
code: '$div.append("<xss>")',
3843
errors: [ error ]
3944
},
45+
{
46+
code: '$div.append("unescaped html")',
47+
errors: [ error ]
48+
},
4049
{
4150
code: '$div.prepend("<xss>")',
4251
errors: [ error ]

0 commit comments

Comments
 (0)