eslint-plugin-security 1.3.0 → 1.4.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/CHANGELOG.md ADDED
@@ -0,0 +1,34 @@
1
+ 1.4.0 / 2017-06-12
2
+ ==================
3
+
4
+ * Add recommended ruleset to the usage example
5
+ * Removes filenames from error output
6
+
7
+ 1.3.0 / 2017-02-09
8
+ ==================
9
+
10
+ * README.md - document detect-disable-mustache-escape rule
11
+ * README.md - documentation detect-new-buffer rule
12
+ * Fixed crash with `detect-no-csrf-before-method-override` rule.
13
+ * Style guide applied to all the code involving the tests
14
+ * Removing a repeated test and style changes
15
+ * ESLint added to the workflow
16
+ * Removed not needed variables
17
+ * Fix to a problem with a rule detected implementing the tests
18
+ * Test engine with tests for all the rules
19
+ * Add additional information to README for each rule
20
+
21
+ 1.2.0 / 2016-01-21
22
+ ==================
23
+
24
+ * updated to check for new RegExp too
25
+
26
+ 1.1.0 / 2016-01-06
27
+ ==================
28
+
29
+ * adding eslint rule to detect new buffer hotspot
30
+
31
+ 1.0.0 / 2015-11-15
32
+ ==================
33
+
34
+ * rules disabled by default
package/README.md CHANGED
@@ -15,6 +15,9 @@ Add the following to your `.eslintrc` file:
15
15
  ```js
16
16
  "plugins": [
17
17
  "security"
18
+ ],
19
+ "extends": [
20
+ "plugin:security/recommended"
18
21
  ]
19
22
  ```
20
23
 
@@ -94,7 +97,7 @@ More information: http://www.bennadel.com/blog/2169-where-does-node-js-and-requi
94
97
 
95
98
  Detects `variable[key]` as a left- or right-hand assignment operand.
96
99
 
97
- More information: https://blog.liftsecurity.io/2015/01/15/the-dangers-of-square-bracket-notation
100
+ More information: https://blog.liftsecurity.io/2015/01/14/the-dangers-of-square-bracket-notation/
98
101
 
99
102
  #### `detect-possible-timing-attacks`
100
103
 
package/index.js CHANGED
@@ -34,5 +34,27 @@ module.exports = {
34
34
  'detect-disable-mustache-escape': 0,
35
35
  'detect-object-injection': 0,
36
36
  'detect-new-buffer': 0
37
+ },
38
+ configs: {
39
+ recommended: {
40
+ plugins: [
41
+ 'security'
42
+ ],
43
+ rules: {
44
+ 'security/detect-buffer-noassert': 'warn',
45
+ 'security/detect-child-process': 'warn',
46
+ 'security/detect-disable-mustache-escape': 'warn',
47
+ 'security/detect-eval-with-expression': 'warn',
48
+ 'security/detect-new-buffer': 'warn',
49
+ 'security/detect-no-csrf-before-method-override': 'warn',
50
+ 'security/detect-non-literal-fs-filename': 'warn',
51
+ 'security/detect-non-literal-regexp': 'warn',
52
+ 'security/detect-non-literal-require': 'warn',
53
+ 'security/detect-object-injection': 'warn',
54
+ 'security/detect-possible-timing-attacks': 'warn',
55
+ 'security/detect-pseudoRandomBytes': 'warn',
56
+ 'security/detect-unsafe-regex': 'warn'
57
+ }
58
+ }
37
59
  }
38
60
  };
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "eslint-plugin-security",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Security rules for eslint",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
+ "changelog": "changelog eslint-plugin-security all > CHANGELOG.md",
7
8
  "test": "./node_modules/.bin/mocha test/**/*",
8
9
  "lint": "./node_modules/.bin/eslint .",
9
10
  "cont-int": "npm test && npm run-script lint"
@@ -27,6 +28,7 @@
27
28
  "safe-regex": "^1.1.0"
28
29
  },
29
30
  "devDependencies": {
31
+ "changelog": "1.3.0",
30
32
  "eslint": "^2.10.1",
31
33
  "eslint-config-nodesecurity": "^1.3.1",
32
34
  "mocha": "^2.4.5"
@@ -47,11 +47,6 @@ module.exports = function(context) {
47
47
  "writeDoubleBE"
48
48
  ];
49
49
 
50
-
51
- var getSource = function (token) {
52
- return token.loc.start.line+ ': ' + context.getSourceLines().slice(token.loc.start.line-1, token.loc.end.line).join('\n\t');
53
- }
54
-
55
50
  return {
56
51
  "MemberExpression": function (node) {
57
52
  var index;
@@ -63,7 +58,7 @@ module.exports = function(context) {
63
58
 
64
59
  if (index && node.parent && node.parent.arguments && node.parent.arguments[index] && node.parent.arguments[index].value) {
65
60
  var token = context.getTokens(node)[0];
66
- return context.report(node, 'Found Buffer.' + node.property.name + ' with noAssert flag set true:\n\t' + getSource(token));
61
+ return context.report(node, 'Found Buffer.' + node.property.name + ' with noAssert flag set true');
67
62
 
68
63
  }
69
64
  }
@@ -13,10 +13,6 @@ module.exports = function(context) {
13
13
 
14
14
  "use strict";
15
15
 
16
- var getSource = function (token) {
17
- return token.loc.start.line+ ': ' + context.getSourceLines().slice(token.loc.start.line-1, token.loc.end.line).join('\n\t');
18
- }
19
-
20
16
  return {
21
17
  "CallExpression": function (node) {
22
18
  var token = context.getTokens(node)[0];
@@ -28,7 +24,7 @@ module.exports = function(context) {
28
24
  } else if (node.parent.type === 'AssignmentExpression' && node.parent.operator === '=') {
29
25
  names.push(node.parent.left.name);
30
26
  }
31
- return context.report(node, 'Found require("child_process")\n\t' + getSource(token));
27
+ return context.report(node, 'Found require("child_process")');
32
28
  }
33
29
  }
34
30
  },
@@ -36,7 +32,7 @@ module.exports = function(context) {
36
32
  var token = context.getTokens(node)[0];
37
33
  if (node.property.name === 'exec' && names.indexOf(node.object.name) > -1) {
38
34
  if (node.parent && node.parent.arguments && node.parent.arguments[0].type !== 'Literal') {
39
- return context.report(node, 'Found child_process.exec() with non Literal first argument\n\t' + getSource(token));
35
+ return context.report(node, 'Found child_process.exec() with non Literal first argument');
40
36
  }
41
37
  }
42
38
  }
@@ -1,11 +1,4 @@
1
1
  module.exports = function (context) {
2
-
3
- var getSource = function (node) {
4
- var token = context.getTokens(node)[0];
5
- return token.loc.start.line+ ': ' + context.getSourceLines().slice(token.loc.start.line-1, token.loc.end.line).join('\n\t');
6
- }
7
-
8
-
9
2
  // Detects instances of new Buffer(argument)
10
3
  // where argument is any non literal value.
11
4
  return {
@@ -14,7 +7,7 @@ module.exports = function (context) {
14
7
  node.arguments[0] &&
15
8
  node.arguments[0].type != 'Literal') {
16
9
 
17
- return context.report(node, "Found new Buffer\n\t" + getSource(node));
10
+ return context.report(node, "Found new Buffer");
18
11
  }
19
12
 
20
13
 
@@ -15,10 +15,6 @@ module.exports = function(context) {
15
15
 
16
16
  "use strict";
17
17
 
18
- var getSource = function (token) {
19
- return token.loc.start.line+ ': ' + context.getSourceLines().slice(token.loc.start.line-1, token.loc.end.line).join('\n\t');
20
- }
21
-
22
18
  return {
23
19
  "MemberExpression": function (node) {
24
20
  var result = [];
@@ -36,13 +32,13 @@ module.exports = function(context) {
36
32
 
37
33
  if (result.length > 0) {
38
34
  var token = context.getTokens(node)[0];
39
- return context.report(node, 'Found fs.' + node.property.name + ' with non literal argument at index ' + result.join(',') + '\n\t' + getSource(token));
35
+ return context.report(node, 'Found fs.' + node.property.name + ' with non literal argument at index ' + result.join(','));
40
36
  }
41
37
 
42
38
 
43
39
  /*
44
40
  if (node.parent && node.parent.arguments && node.parent.arguments[index].value) {
45
- return context.report(node, 'found Buffer.' + node.property.name + ' with noAssert flag set true:\n\t' + getSource(token));
41
+ return context.report(node, 'found Buffer.' + node.property.name + ' with noAssert flag set true');
46
42
 
47
43
  }
48
44
  */
@@ -12,16 +12,13 @@ module.exports = function(context) {
12
12
 
13
13
  "use strict";
14
14
 
15
- var getSource = function(token) {
16
- return token.loc.start.line + ': ' + context.getSourceLines().slice(token.loc.start.line - 1, token.loc.end.line).join('\n\t');
17
- }
18
15
  return {
19
16
  "NewExpression": function(node) {
20
17
  if (node.callee.name === 'RegExp') {
21
18
  var args = node.arguments;
22
19
  if (args && args.length > 0 && args[0].type !== 'Literal') {
23
20
  var token = context.getTokens(node)[0];
24
- return context.report(node, 'Found non-literal argument to RegExp Constructor\n\t' + getSource(token));
21
+ return context.report(node, 'Found non-literal argument to RegExp Constructor');
25
22
  }
26
23
  }
27
24
 
@@ -11,17 +11,13 @@ module.exports = function(context) {
11
11
 
12
12
  "use strict";
13
13
 
14
- var getSource = function (token) {
15
- return token.loc.start.line+ ': ' + context.getSourceLines().slice(token.loc.start.line-1, token.loc.end.line).join('\n\t');
16
- }
17
-
18
14
  return {
19
15
  "CallExpression": function (node) {
20
16
  if (node.callee.name === 'require') {
21
17
  var args = node.arguments;
22
18
  if (args && args.length > 0 && args[0].type !== 'Literal') {
23
19
  var token = context.getTokens(node)[0];
24
- return context.report(node, 'Found non-literal argument in require\n\t' + getSource(token));
20
+ return context.report(node, 'Found non-literal argument in require');
25
21
  }
26
22
  }
27
23
 
@@ -59,13 +59,13 @@ var isChanged = false;
59
59
  var token = context.getTokens(node)[0];
60
60
  if (node.property.type === 'Identifier') {
61
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');
62
+ context.report(node, 'Variable Assigned to Object Injection Sink');
63
63
 
64
64
  } else if (node.parent.type === 'CallExpression') {
65
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');
66
+ context.report(node, 'Function Call Object Injection Sink');
67
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');
68
+ context.report(node, 'Generic Object Injection Sink');
69
69
 
70
70
  }
71
71
 
@@ -32,10 +32,6 @@ module.exports = function(context) {
32
32
 
33
33
  "use strict";
34
34
 
35
- var getSource = function (token) {
36
- return token.loc.start.line+ ': ' + context.getSourceLines().slice(token.loc.start.line-1, token.loc.end.line).join('\n\t');
37
- }
38
-
39
35
  return {
40
36
  "IfStatement": function(node) {
41
37
  if (node.test && node.test.type === 'BinaryExpression') {
@@ -46,14 +42,14 @@ module.exports = function(context) {
46
42
  if (node.test.left) {
47
43
  var left = containsKeyword(node.test.left);
48
44
  if (left) {
49
- return context.report(node, "Potential timing attack, left side: " + left + '\n\t' + getSource(token));
45
+ return context.report(node, "Potential timing attack, left side: " + left);
50
46
  }
51
47
  }
52
48
 
53
49
  if (node.test.right) {
54
50
  var right = containsKeyword(node.test.right);
55
51
  if (right) {
56
- return context.report(node, "Potential timing attack, right side: " + right + '\n\t' + getSource(token));
52
+ return context.report(node, "Potential timing attack, right side: " + right);
57
53
  }
58
54
  }
59
55
  }
@@ -11,15 +11,11 @@ module.exports = function(context) {
11
11
 
12
12
  "use strict";
13
13
 
14
- var getSource = function (token) {
15
- return token.loc.start.line+ ': ' + context.getSourceLines().slice(token.loc.start.line-1, token.loc.end.line).join('\n\t');
16
- }
17
-
18
14
  return {
19
15
  "MemberExpression": function (node) {
20
16
  if (node.property.name === 'pseudoRandomBytes') {
21
17
  var token = context.getTokens(node)[0];
22
- return context.report(node, 'Found crypto.pseudoRandomBytes which does not produce cryptographically strong numbers:\n\t' + getSource(token));
18
+ return context.report(node, 'Found crypto.pseudoRandomBytes which does not produce cryptographically strong numbers');
23
19
  }
24
20
  }
25
21
 
@@ -14,7 +14,7 @@ tester.run(ruleName, Rule, {
14
14
  invalid: [
15
15
  {
16
16
  code: invalid,
17
- errors: [{ message: `Found Buffer.readUInt8 with noAssert flag set true:\n\t1: ${invalid}` }]
17
+ errors: [{ message: 'Found Buffer.readUInt8 with noAssert flag set true' }]
18
18
  }
19
19
  ]
20
20
  });
@@ -24,7 +24,7 @@ tester.run(`${ruleName} (false)`, Rule, {
24
24
  invalid: [
25
25
  {
26
26
  code: invalid,
27
- errors: [{ message: `Found Buffer.readUInt8 with noAssert flag set true:\n\t1: ${invalid}` }]
27
+ errors: [{ message: 'Found Buffer.readUInt8 with noAssert flag set true' }]
28
28
  }
29
29
  ]
30
30
  });
@@ -16,7 +16,7 @@ tester.run(`${ruleName} (require("child_process"))`, Rule, {
16
16
  invalid: [
17
17
  {
18
18
  code: invalidRequire,
19
- errors: [{ message: `Found require("child_process")\n\t1: ${invalidRequire}` }]
19
+ errors: [{ message: 'Found require("child_process")' }]
20
20
  }
21
21
  ]
22
22
  });
@@ -28,8 +28,8 @@ tester.run(`${ruleName} (child_process.exec() wih non literal 1st arg.)`, Rule,
28
28
  {
29
29
  code: invalidExec,
30
30
  errors: [
31
- { message: `Found require("child_process")\n\t1: ${invalidExec}` },
32
- { message: `Found child_process.exec() with non Literal first argument\n\t1: ${invalidExec}` }]
31
+ { message: 'Found require("child_process")' },
32
+ { message: 'Found child_process.exec() with non Literal first argument' }]
33
33
  }
34
34
  ]
35
35
  });
@@ -12,7 +12,7 @@ tester.run(ruleName, require(`../rules/${ruleName}`), {
12
12
  invalid: [
13
13
  {
14
14
  code: invalid,
15
- errors: [{ message: `Found new Buffer\n\t1: ${invalid}` }]
15
+ errors: [{ message: 'Found new Buffer' }]
16
16
  }
17
17
  ]
18
18
  });
@@ -13,7 +13,7 @@ tester.run(ruleName, require(`../rules/${ruleName}`), {
13
13
  invalid: [
14
14
  {
15
15
  code: invalid,
16
- errors: [{ message: `Found fs.open with non literal argument at index 0\n\t1: ${invalid}` }]
16
+ errors: [{ message: 'Found fs.open with non literal argument at index 0' }]
17
17
  }
18
18
  ]
19
19
  });
@@ -12,7 +12,7 @@ tester.run(ruleName, require(`../rules/${ruleName}`), {
12
12
  invalid: [
13
13
  {
14
14
  code: invalid,
15
- errors: [{ message: `Found non-literal argument to RegExp Constructor\n\t1: ${invalid}` }]
15
+ errors: [{ message: 'Found non-literal argument to RegExp Constructor' }]
16
16
  }
17
17
  ]
18
18
  });
@@ -12,7 +12,7 @@ tester.run(ruleName, require(`../rules/${ruleName}`), {
12
12
  invalid: [
13
13
  {
14
14
  code: invalid,
15
- errors: [{ message: `Found non-literal argument in require\n\t1: ${invalid}` }]
15
+ errors: [{ message: 'Found non-literal argument in require' }]
16
16
  }
17
17
  ]
18
18
  });
@@ -19,7 +19,7 @@ const invalidGeneric = 'var a = {}; a[b] = 4';
19
19
  // invalid: [
20
20
  // {
21
21
  // code: invalidVariable,
22
- // errors: [{ message: `Variable Assigned to Object Injection Sink: <input>: 1\n\t${invalidVariable}\n\n` }]
22
+ // errors: [{ message: 'Variable Assigned to Object Injection Sink' }]
23
23
  // }
24
24
  // ]
25
25
  // });
@@ -41,7 +41,7 @@ tester.run(`${ruleName} (Generic)`, Rule, {
41
41
  invalid: [
42
42
  {
43
43
  code: invalidGeneric,
44
- errors: [{ message: `Generic Object Injection Sink: <input>: 1\n\t${invalidGeneric}\n\n` }]
44
+ errors: [{ message: 'Generic Object Injection Sink' }]
45
45
  }
46
46
  ]
47
47
  });
@@ -19,7 +19,7 @@ tester.run(`${ruleName} (left side)`, Rule, {
19
19
  invalid: [
20
20
  {
21
21
  code: invalidLeft,
22
- errors: [{ message: `Potential timing attack, left side: true\n\t1: ${invalidLeft}` }]
22
+ errors: [{ message: 'Potential timing attack, left side: true' }]
23
23
  }
24
24
  ]
25
25
  });
@@ -30,7 +30,7 @@ tester.run(`${ruleName} (right side)`, Rule, {
30
30
  invalid: [
31
31
  {
32
32
  code: invalidRigth,
33
- errors: [{ message: `Potential timing attack, right side: true\n\t1: ${invalidRigth}` }]
33
+ errors: [{ message: 'Potential timing attack, right side: true' }]
34
34
  }
35
35
  ]
36
36
  });
@@ -12,7 +12,7 @@ tester.run(ruleName, require(`../rules/${ruleName}`), {
12
12
  invalid: [
13
13
  {
14
14
  code: invalid,
15
- errors: [{ message: `Found crypto.pseudoRandomBytes which does not produce cryptographically strong numbers:\n\t1: ${invalid}` }]
15
+ errors: [{ message: 'Found crypto.pseudoRandomBytes which does not produce cryptographically strong numbers' }]
16
16
  }
17
17
  ]
18
18
  });