eslint-plugin-security 1.2.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc +13 -0
- package/.github/workflows/ci.yml +47 -0
- package/.github/workflows/pr.yml +15 -0
- package/.prettierrc.json +7 -0
- package/CHANGELOG.md +65 -0
- package/README.md +97 -16
- package/docs/avoid-command-injection-node.md +85 -0
- package/docs/bypass-connect-csrf-protection-by-abusing.md +42 -0
- package/docs/regular-expression-dos-and-node.md +83 -0
- package/docs/the-dangers-of-square-bracket-notation.md +107 -0
- package/index.js +20 -0
- package/package.json +29 -4
- package/rules/data/fsFunctionData.json +49 -49
- package/rules/detect-buffer-noassert.js +66 -60
- package/rules/detect-child-process.js +37 -32
- package/rules/detect-disable-mustache-escape.js +24 -14
- package/rules/detect-eval-with-expression.js +19 -9
- package/rules/detect-new-buffer.js +17 -21
- package/rules/detect-no-csrf-before-method-override.js +34 -23
- package/rules/detect-non-literal-fs-filename.js +38 -37
- package/rules/detect-non-literal-regexp.js +24 -21
- package/rules/detect-non-literal-require.js +25 -21
- package/rules/detect-object-injection.js +61 -59
- package/rules/detect-possible-timing-attacks.js +39 -45
- package/rules/detect-pseudoRandomBytes.js +18 -15
- package/rules/detect-unsafe-regex.js +36 -23
- package/test/detect-buffer-noassert.js +30 -0
- package/test/detect-child-process.js +25 -0
- package/test/detect-disable-mustache-escape.js +16 -0
- package/test/detect-eval-with-expression.js +16 -0
- package/test/detect-new-buffer.js +17 -0
- package/test/detect-no-csrf-before-method-override.js +16 -0
- package/test/detect-non-literal-fs-filename.js +18 -0
- package/test/detect-non-literal-regexp.js +17 -0
- package/test/detect-non-literal-require.js +21 -0
- package/test/detect-object-injection.js +45 -0
- package/test/detect-possible-timing-attacks.js +34 -0
- package/test/detect-pseudoRandomBytes.js +17 -0
- package/test/detect-unsafe-regexp.js +27 -0
- package/.npmignore +0 -1
|
@@ -3,29 +3,32 @@
|
|
|
3
3
|
* @author Jon Lamendola
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
6
8
|
//------------------------------------------------------------------------------
|
|
7
9
|
// Rule Definition
|
|
8
10
|
//------------------------------------------------------------------------------
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
|
|
12
|
+
module.exports = {
|
|
13
|
+
meta: {
|
|
14
|
+
type: 'error',
|
|
15
|
+
docs: {
|
|
16
|
+
description: 'Detects "RegExp(variable)", which might allow an attacker to DOS your server with a long-running regular expression.',
|
|
17
|
+
category: 'Possible Security Vulnerability',
|
|
18
|
+
recommended: true,
|
|
19
|
+
url: 'https://github.com/nodesecurity/eslint-plugin-security/blob/main/docs/regular-expression-dos-and-node.md',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
create: function (context) {
|
|
23
|
+
return {
|
|
24
|
+
NewExpression: function (node) {
|
|
25
|
+
if (node.callee.name === 'RegExp') {
|
|
26
|
+
const args = node.arguments;
|
|
27
|
+
if (args && args.length > 0 && args[0].type !== 'Literal') {
|
|
28
|
+
return context.report(node, 'Found non-literal argument to RegExp Constructor');
|
|
29
|
+
}
|
|
30
30
|
}
|
|
31
|
-
}
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
};
|
|
@@ -1,33 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tries to detect calls to require with non-literal argument
|
|
3
|
-
* @author Adam Baldwin
|
|
3
|
+
* @author Adam Baldwin
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
6
8
|
//------------------------------------------------------------------------------
|
|
7
9
|
// Rule Definition
|
|
8
10
|
//------------------------------------------------------------------------------
|
|
9
11
|
|
|
10
|
-
module.exports =
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
module.exports = {
|
|
13
|
+
meta: {
|
|
14
|
+
type: 'error',
|
|
15
|
+
docs: {
|
|
16
|
+
description: 'Detects "require(variable)", which might allow an attacker to load and run arbitrary code, or access arbitrary files on disk. ',
|
|
17
|
+
category: 'Possible Security Vulnerability',
|
|
18
|
+
recommended: true,
|
|
19
|
+
url: 'https://github.com/nodesecurity/eslint-plugin-security#detect-non-literal-require',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
create: function (context) {
|
|
18
23
|
return {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
CallExpression: function (node) {
|
|
25
|
+
if (node.callee.name === 'require') {
|
|
26
|
+
const args = node.arguments;
|
|
27
|
+
if (
|
|
28
|
+
(args && args.length > 0 && args[0].type === 'TemplateLiteral' && args[0].expressions.length > 0) ||
|
|
29
|
+
(args[0].type !== 'TemplateLiteral' && args[0].type !== 'Literal')
|
|
30
|
+
) {
|
|
31
|
+
return context.report(node, 'Found non-literal argument in require');
|
|
32
|
+
}
|
|
28
33
|
}
|
|
29
|
-
|
|
34
|
+
},
|
|
30
35
|
};
|
|
31
|
-
|
|
36
|
+
},
|
|
32
37
|
};
|
|
33
|
-
|
|
@@ -3,77 +3,79 @@
|
|
|
3
3
|
* @author Jon Lamendola
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
6
8
|
//------------------------------------------------------------------------------
|
|
7
9
|
// Rule Definition
|
|
8
10
|
//------------------------------------------------------------------------------
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
const getPath = (value, seen, keys) => {
|
|
13
|
+
let index = seen.indexOf(value);
|
|
14
|
+
const path = [keys[index]];
|
|
15
|
+
for (index--; index >= 0; index--) {
|
|
16
|
+
if (seen[index][path[0]] === value) {
|
|
17
|
+
value = seen[index];
|
|
18
|
+
path.unshift(keys[index]);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return `~${path.join('.')}`;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const getSerialize = (fn, decycle) => {
|
|
25
|
+
const seen = [];
|
|
26
|
+
const keys = [];
|
|
27
|
+
decycle =
|
|
28
|
+
decycle ||
|
|
29
|
+
function (key, value) {
|
|
30
|
+
return `[Circular ${getPath(value, seen, keys)}]`;
|
|
31
|
+
};
|
|
32
|
+
return function (key, value) {
|
|
33
|
+
let ret = value;
|
|
18
34
|
if (typeof value === 'object' && value) {
|
|
19
|
-
if (seen.indexOf(value) !== -1)
|
|
35
|
+
if (seen.indexOf(value) !== -1) {
|
|
20
36
|
ret = decycle(key, value);
|
|
21
|
-
else {
|
|
37
|
+
} else {
|
|
22
38
|
seen.push(value);
|
|
23
39
|
keys.push(key);
|
|
24
40
|
}
|
|
25
41
|
}
|
|
26
|
-
if (fn)
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function getPath (value, seen, keys) {
|
|
32
|
-
var index = seen.indexOf(value);
|
|
33
|
-
var path = [ keys[index] ];
|
|
34
|
-
for (index--; index >= 0; index--) {
|
|
35
|
-
if (seen[index][ path[0] ] === value) {
|
|
36
|
-
value = seen[index];
|
|
37
|
-
path.unshift(keys[index]);
|
|
42
|
+
if (fn) {
|
|
43
|
+
ret = fn(key, ret);
|
|
38
44
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
45
|
+
return ret;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
42
48
|
|
|
43
|
-
|
|
49
|
+
const stringify = (obj, fn, spaces, decycle) => {
|
|
44
50
|
return JSON.stringify(obj, getSerialize(fn, decycle), spaces);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
stringify.getSerialize = getSerialize;module.exports = function(context) {
|
|
48
|
-
|
|
49
|
-
"use strict";
|
|
50
|
-
|
|
51
|
-
var isChanged = false;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return {
|
|
56
|
-
"MemberExpression": function(node) {
|
|
57
|
-
|
|
58
|
-
if (node.computed === true) {
|
|
59
|
-
var token = context.getTokens(node)[0];
|
|
60
|
-
if (node.property.type === 'Identifier') {
|
|
61
|
-
if (node.parent.type === 'VariableDeclarator') {
|
|
62
|
-
context.report(node, 'Variable Assigned to Object Injection Sink: ' + context.getFilename() + ': ' + token.loc.start.line+ '\n\t' + context.getSourceLines().slice(token.loc.start.line-1, token.loc.end.line).join('\n\t') + '\n\n');
|
|
63
|
-
|
|
64
|
-
} else if (node.parent.type === 'CallExpression') {
|
|
65
|
-
// console.log(node.parent)
|
|
66
|
-
context.report(node, 'Function Call Object Injection Sink: ' + context.getFilename() + ': ' + token.loc.start.line+ '\n\t' + context.getSourceLines().slice(token.loc.start.line-1, token.loc.end.line).join('\n\t') + '\n\n');
|
|
67
|
-
} else {
|
|
68
|
-
context.report(node, 'Generic Object Injection Sink: ' + context.getFilename() + ': ' + token.loc.start.line+ '\n\t' + context.getSourceLines().slice(token.loc.start.line-1, token.loc.end.line).join('\n\t') + '\n\n');
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
}
|
|
51
|
+
};
|
|
74
52
|
|
|
53
|
+
stringify.getSerialize = getSerialize;
|
|
54
|
+
module.exports = {
|
|
55
|
+
meta: {
|
|
56
|
+
type: 'error',
|
|
57
|
+
docs: {
|
|
58
|
+
description: 'Detects "variable[key]" as a left- or right-hand assignment operand.',
|
|
59
|
+
category: 'Possible Security Vulnerability',
|
|
60
|
+
recommended: true,
|
|
61
|
+
url: 'https://github.com/nodesecurity/eslint-plugin-security/blob/main/docs/the-dangers-of-square-bracket-notation.md',
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
create: function (context) {
|
|
65
|
+
return {
|
|
66
|
+
MemberExpression: function (node) {
|
|
67
|
+
if (node.computed === true) {
|
|
68
|
+
if (node.property.type === 'Identifier') {
|
|
69
|
+
if (node.parent.type === 'VariableDeclarator') {
|
|
70
|
+
context.report(node, 'Variable Assigned to Object Injection Sink');
|
|
71
|
+
} else if (node.parent.type === 'CallExpression') {
|
|
72
|
+
context.report(node, 'Function Call Object Injection Sink');
|
|
73
|
+
} else {
|
|
74
|
+
context.report(node, 'Generic Object Injection Sink');
|
|
75
75
|
}
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
},
|
|
81
|
+
};
|
|
@@ -3,62 +3,56 @@
|
|
|
3
3
|
* @author Adam Baldwin / Jon Lamendola
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
6
8
|
//------------------------------------------------------------------------------
|
|
7
9
|
// Rule Definition
|
|
8
10
|
//------------------------------------------------------------------------------
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
'password',
|
|
12
|
-
'secret',
|
|
13
|
-
'api',
|
|
14
|
-
'apiKey',
|
|
15
|
-
'token',
|
|
16
|
-
'auth',
|
|
17
|
-
'pass',
|
|
18
|
-
'hash'
|
|
19
|
-
].join(')|(') + '))';
|
|
20
|
-
|
|
21
|
-
var re = new RegExp('^' + keywords + '$', 'im');
|
|
22
|
-
|
|
23
|
-
function containsKeyword (node) {
|
|
24
|
-
if (node.type === 'Identifier') {
|
|
25
|
-
if (re.test(node.name))
|
|
26
|
-
return true;
|
|
27
|
-
}
|
|
28
|
-
return
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
module.exports = function(context) {
|
|
12
|
+
const keywords = `((${['password', 'secret', 'api', 'apiKey', 'token', 'auth', 'pass', 'hash'].join(')|(')}))`;
|
|
32
13
|
|
|
33
|
-
|
|
14
|
+
const re = new RegExp(`^${keywords}$`, 'im');
|
|
34
15
|
|
|
35
|
-
|
|
36
|
-
|
|
16
|
+
const containsKeyword = (node) => {
|
|
17
|
+
if (node.type === 'Identifier') {
|
|
18
|
+
if (re.test(node.name)) {
|
|
19
|
+
return true;
|
|
37
20
|
}
|
|
21
|
+
}
|
|
22
|
+
return;
|
|
23
|
+
};
|
|
38
24
|
|
|
25
|
+
module.exports = {
|
|
26
|
+
meta: {
|
|
27
|
+
type: 'error',
|
|
28
|
+
docs: {
|
|
29
|
+
description: 'Detects insecure comparisons (`==`, `!=`, `!==` and `===`), which check input sequentially.',
|
|
30
|
+
category: 'Possible Security Vulnerability',
|
|
31
|
+
recommended: true,
|
|
32
|
+
url: 'https://github.com/nodesecurity/eslint-plugin-security#detect-possible-timing-attacks'
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
create: function (context) {
|
|
39
36
|
return {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return context.report(node, "Potential timing attack, left side: " + left + '\n\t' + getSource(token));
|
|
50
|
-
}
|
|
51
|
-
}
|
|
37
|
+
IfStatement: function (node) {
|
|
38
|
+
if (node.test && node.test.type === 'BinaryExpression') {
|
|
39
|
+
if (node.test.operator === '==' || node.test.operator === '===' || node.test.operator === '!=' || node.test.operator === '!==') {
|
|
40
|
+
if (node.test.left) {
|
|
41
|
+
const left = containsKeyword(node.test.left);
|
|
42
|
+
if (left) {
|
|
43
|
+
return context.report(node, `Potential timing attack, left side: ${left}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
52
46
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
}
|
|
47
|
+
if (node.test.right) {
|
|
48
|
+
const right = containsKeyword(node.test.right);
|
|
49
|
+
if (right) {
|
|
50
|
+
return context.report(node, `Potential timing attack, right side: ${right}`);
|
|
51
|
+
}
|
|
60
52
|
}
|
|
53
|
+
}
|
|
61
54
|
}
|
|
55
|
+
}
|
|
62
56
|
};
|
|
63
|
-
|
|
57
|
+
}
|
|
64
58
|
};
|
|
@@ -3,26 +3,29 @@
|
|
|
3
3
|
* @author Adam Baldwin
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
6
8
|
//------------------------------------------------------------------------------
|
|
7
9
|
// Rule Definition
|
|
8
10
|
//------------------------------------------------------------------------------
|
|
9
11
|
|
|
10
|
-
module.exports =
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
module.exports = {
|
|
13
|
+
meta: {
|
|
14
|
+
type: 'error',
|
|
15
|
+
docs: {
|
|
16
|
+
description: 'Detects if "pseudoRandomBytes()" is in use, which might not give you the randomness you need and expect.',
|
|
17
|
+
category: 'Possible Security Vulnerability',
|
|
18
|
+
recommended: true,
|
|
19
|
+
url: 'https://github.com/nodesecurity/eslint-plugin-security#detect-pseudorandombytes',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
create: function (context) {
|
|
18
23
|
return {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return context.report(node, 'found crypto.pseudoRandomBytes which does not produce cryptographically strong numbers:\n\t' + getSource(token));
|
|
23
|
-
}
|
|
24
|
+
MemberExpression: function (node) {
|
|
25
|
+
if (node.property.name === 'pseudoRandomBytes') {
|
|
26
|
+
return context.report(node, 'Found crypto.pseudoRandomBytes which does not produce cryptographically strong numbers');
|
|
24
27
|
}
|
|
25
|
-
|
|
28
|
+
},
|
|
26
29
|
};
|
|
27
|
-
|
|
30
|
+
},
|
|
28
31
|
};
|
|
@@ -1,37 +1,50 @@
|
|
|
1
|
-
var safe = require('safe-regex');
|
|
2
1
|
/**
|
|
3
2
|
* Check if the regex is evil or not using the safe-regex module
|
|
4
3
|
* @author Adam Baldwin
|
|
5
4
|
*/
|
|
6
5
|
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
//-----------------------------------------------------------------------------
|
|
9
|
+
// Requirements
|
|
10
|
+
//-----------------------------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
const safe = require('safe-regex');
|
|
13
|
+
|
|
7
14
|
//------------------------------------------------------------------------------
|
|
8
15
|
// Rule Definition
|
|
9
16
|
//------------------------------------------------------------------------------
|
|
10
17
|
|
|
11
|
-
module.exports =
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
18
|
+
module.exports = {
|
|
19
|
+
meta: {
|
|
20
|
+
type: 'error',
|
|
21
|
+
docs: {
|
|
22
|
+
description: 'Locates potentially unsafe regular expressions, which may take a very long time to run, blocking the event loop.',
|
|
23
|
+
category: 'Possible Security Vulnerability',
|
|
24
|
+
recommended: true,
|
|
25
|
+
url: 'https://github.com/nodesecurity/eslint-plugin-security/blob/main/docs/regular-expression-dos-and-node.md'
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
create: function (context) {
|
|
15
29
|
return {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
30
|
+
Literal: function (node) {
|
|
31
|
+
const token = context.getTokens(node)[0];
|
|
32
|
+
const nodeType = token.type;
|
|
33
|
+
const nodeValue = token.value;
|
|
20
34
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
35
|
+
if (nodeType === 'RegularExpression') {
|
|
36
|
+
if (!safe(nodeValue)) {
|
|
37
|
+
context.report(node, 'Unsafe Regular Expression');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
NewExpression: function (node) {
|
|
42
|
+
if (node.callee.name === 'RegExp' && node.arguments && node.arguments.length > 0 && node.arguments[0].type === 'Literal') {
|
|
43
|
+
if (!safe(node.arguments[0].value)) {
|
|
44
|
+
context.report(node, 'Unsafe Regular Expression (new RegExp)');
|
|
45
|
+
}
|
|
33
46
|
}
|
|
47
|
+
}
|
|
34
48
|
};
|
|
35
|
-
|
|
49
|
+
}
|
|
36
50
|
};
|
|
37
|
-
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const RuleTester = require('eslint').RuleTester;
|
|
4
|
+
const tester = new RuleTester();
|
|
5
|
+
|
|
6
|
+
const ruleName = 'detect-buffer-noassert';
|
|
7
|
+
const rule = require(`../rules/${ruleName}`);
|
|
8
|
+
|
|
9
|
+
const allMethodNames = [...rule.meta.__methodsToCheck.read, ...rule.meta.__methodsToCheck.write];
|
|
10
|
+
|
|
11
|
+
tester.run(ruleName, rule, {
|
|
12
|
+
valid: [...allMethodNames.map((methodName) => `a.${methodName}(0)`), ...allMethodNames.map((methodName) => `a.${methodName}(0, false)`)],
|
|
13
|
+
invalid: [
|
|
14
|
+
...rule.meta.__methodsToCheck.read.map((methodName) => ({
|
|
15
|
+
code: `a.${methodName}(0, true)`,
|
|
16
|
+
errors: [{ message: `Found Buffer.${methodName} with noAssert flag set true` }],
|
|
17
|
+
})),
|
|
18
|
+
|
|
19
|
+
...rule.meta.__methodsToCheck.write.map((methodName) => ({
|
|
20
|
+
code: `a.${methodName}(0, 0, true)`,
|
|
21
|
+
errors: [{ message: `Found Buffer.${methodName} with noAssert flag set true` }],
|
|
22
|
+
})),
|
|
23
|
+
|
|
24
|
+
// hard-coded test to ensure #63 is fixed
|
|
25
|
+
{
|
|
26
|
+
code: 'a.readDoubleLE(0, true);',
|
|
27
|
+
errors: [{ message: 'Found Buffer.readDoubleLE with noAssert flag set true' }],
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const RuleTester = require('eslint').RuleTester;
|
|
4
|
+
const tester = new RuleTester();
|
|
5
|
+
|
|
6
|
+
const ruleName = 'detect-child-process';
|
|
7
|
+
const rule = require(`../rules/${ruleName}`);
|
|
8
|
+
|
|
9
|
+
tester.run(ruleName, rule, {
|
|
10
|
+
valid: ["child_process.exec('ls')"],
|
|
11
|
+
invalid: [
|
|
12
|
+
{
|
|
13
|
+
code: "require('child_process')",
|
|
14
|
+
errors: [{ message: 'Found require("child_process")' }],
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
code: "var child = require('child_process'); child.exec(com)",
|
|
18
|
+
errors: [{ message: 'Found require("child_process")' }, { message: 'Found child_process.exec() with non Literal first argument' }],
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
code: "var child = require('child_process'); child.exec()",
|
|
22
|
+
errors: [{ message: 'Found require("child_process")' }],
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const RuleTester = require('eslint').RuleTester;
|
|
4
|
+
const tester = new RuleTester();
|
|
5
|
+
|
|
6
|
+
const ruleName = 'detect-disable-mustache-escape';
|
|
7
|
+
|
|
8
|
+
tester.run(ruleName, require(`../rules/${ruleName}`), {
|
|
9
|
+
valid: [{ code: 'escapeMarkup = false' }],
|
|
10
|
+
invalid: [
|
|
11
|
+
{
|
|
12
|
+
code: 'a.escapeMarkup = false',
|
|
13
|
+
errors: [{ message: 'Markup escaping disabled.' }]
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const RuleTester = require('eslint').RuleTester;
|
|
4
|
+
const tester = new RuleTester();
|
|
5
|
+
|
|
6
|
+
const ruleName = 'detect-eval-with-expression';
|
|
7
|
+
|
|
8
|
+
tester.run(ruleName, require(`../rules/${ruleName}`), {
|
|
9
|
+
valid: [{ code: 'eval(\'alert()\')' }],
|
|
10
|
+
invalid: [
|
|
11
|
+
{
|
|
12
|
+
code: 'eval(a);',
|
|
13
|
+
errors: [{ message: 'eval with argument of type Identifier' }]
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const RuleTester = require('eslint').RuleTester;
|
|
4
|
+
const tester = new RuleTester();
|
|
5
|
+
|
|
6
|
+
const ruleName = 'detect-new-buffer';
|
|
7
|
+
const invalid = 'var a = new Buffer(c)';
|
|
8
|
+
|
|
9
|
+
tester.run(ruleName, require(`../rules/${ruleName}`), {
|
|
10
|
+
valid: [{ code: 'var a = new Buffer(\'test\')' }],
|
|
11
|
+
invalid: [
|
|
12
|
+
{
|
|
13
|
+
code: invalid,
|
|
14
|
+
errors: [{ message: 'Found new Buffer' }]
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const RuleTester = require('eslint').RuleTester;
|
|
4
|
+
const tester = new RuleTester();
|
|
5
|
+
|
|
6
|
+
const ruleName = 'detect-no-csrf-before-method-override';
|
|
7
|
+
|
|
8
|
+
tester.run(ruleName, require(`../rules/${ruleName}`), {
|
|
9
|
+
valid: [{ code: 'express.methodOverride();express.csrf()' }],
|
|
10
|
+
invalid: [
|
|
11
|
+
{
|
|
12
|
+
code: 'express.csrf();express.methodOverride()',
|
|
13
|
+
errors: [{ message: 'express.csrf() middleware found before express.methodOverride()' }]
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const RuleTester = require('eslint').RuleTester;
|
|
4
|
+
const tester = new RuleTester();
|
|
5
|
+
|
|
6
|
+
const invalid = 'var a = fs.open(c)';
|
|
7
|
+
|
|
8
|
+
const ruleName = 'detect-non-literal-fs-filename';
|
|
9
|
+
|
|
10
|
+
tester.run(ruleName, require(`../rules/${ruleName}`), {
|
|
11
|
+
valid: [{ code: 'var a = fs.open(\'test\')' }],
|
|
12
|
+
invalid: [
|
|
13
|
+
{
|
|
14
|
+
code: invalid,
|
|
15
|
+
errors: [{ message: 'Found fs.open with non literal argument at index 0' }]
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const RuleTester = require('eslint').RuleTester;
|
|
4
|
+
const tester = new RuleTester();
|
|
5
|
+
|
|
6
|
+
const ruleName = 'detect-non-literal-regexp';
|
|
7
|
+
const invalid = 'var a = new RegExp(c, \'i\')';
|
|
8
|
+
|
|
9
|
+
tester.run(ruleName, require(`../rules/${ruleName}`), {
|
|
10
|
+
valid: [{ code: 'var a = new RegExp(\'ab+c\', \'i\')' }],
|
|
11
|
+
invalid: [
|
|
12
|
+
{
|
|
13
|
+
code: invalid,
|
|
14
|
+
errors: [{ message: 'Found non-literal argument to RegExp Constructor' }]
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const RuleTester = require('eslint').RuleTester;
|
|
4
|
+
|
|
5
|
+
const tester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
|
|
6
|
+
|
|
7
|
+
const ruleName = 'detect-non-literal-require';
|
|
8
|
+
|
|
9
|
+
tester.run(ruleName, require(`../rules/${ruleName}`), {
|
|
10
|
+
valid: [{ code: 'var a = require(\'b\')' }, { code: 'var a = require(`b`)' }],
|
|
11
|
+
invalid: [
|
|
12
|
+
{
|
|
13
|
+
code: 'var a = require(c)',
|
|
14
|
+
errors: [{ message: 'Found non-literal argument in require' }]
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
code: 'var a = require(`${c}`)',
|
|
18
|
+
errors: [{ message: 'Found non-literal argument in require' }]
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
});
|