eslint-plugin-security 1.6.0 → 1.7.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.
@@ -0,0 +1 @@
1
+ /CHANGELOG.md
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.7.0](https://www.github.com/eslint-community/eslint-plugin-security/compare/v1.6.0...v1.7.0) (2023-01-26)
4
+
5
+
6
+ ### Features
7
+
8
+ * improve detect-child-process rule ([#108](https://www.github.com/eslint-community/eslint-plugin-security/issues/108)) ([64ae529](https://www.github.com/eslint-community/eslint-plugin-security/commit/64ae52944a86f9d9daee769acd63ebbdfc5b6631))
9
+
3
10
  ## [1.6.0](https://www.github.com/eslint-community/eslint-plugin-security/compare/v1.5.0...v1.6.0) (2023-01-11)
4
11
 
5
12
  ### Features
@@ -21,25 +28,25 @@
21
28
  ## 1.5.0 / 2022-04-14
22
29
 
23
30
  - Fix avoid crash when exec() is passed no arguments
24
- Closes [#82](https://github.com/nodesecurity/eslint-plugin-security/pull/82) with ref as [#23](https://github.com/nodesecurity/eslint-plugin-security/pull/23)
31
+ Closes [#82](https://github.com/eslint-community/eslint-plugin-security/pull/82) with ref as [#23](https://github.com/eslint-community/eslint-plugin-security/pull/23)
25
32
  - Fix incorrect method name in detect-buffer-noassert
26
- Closes [#63](https://github.com/nodesecurity/eslint-plugin-security/pull/63) and [#80](https://github.com/nodesecurity/eslint-plugin-security/pull/80)
33
+ Closes [#63](https://github.com/eslint-community/eslint-plugin-security/pull/63) and [#80](https://github.com/eslint-community/eslint-plugin-security/pull/80)
27
34
  - Clean up source code formatting
28
- Fixes [#4](https://github.com/nodesecurity/eslint-plugin-security/issues/4) and closes [#78](https://github.com/nodesecurity/eslint-plugin-security/pull/78)
35
+ Fixes [#4](https://github.com/eslint-community/eslint-plugin-security/issues/4) and closes [#78](https://github.com/eslint-community/eslint-plugin-security/pull/78)
29
36
  - Add release script
30
- [Script](https://github.com/nodesecurity/eslint-plugin-security/commit/0a6631ea448eb0031af7b351c85b3aa298c2e44c)
31
- - Add non-literal require TemplateLiteral support [#81](https://github.com/nodesecurity/eslint-plugin-security/pull/81)
32
- - Add meta object documentation for all rules [#79](https://github.com/nodesecurity/eslint-plugin-security/pull/79)
37
+ [Script](https://github.com/eslint-community/eslint-plugin-security/commit/0a6631ea448eb0031af7b351c85b3aa298c2e44c)
38
+ - Add non-literal require TemplateLiteral support [#81](https://github.com/eslint-community/eslint-plugin-security/pull/81)
39
+ - Add meta object documentation for all rules [#79](https://github.com/eslint-community/eslint-plugin-security/pull/79)
33
40
  - Added Git pre-commit hook to format JS files
34
- [Pre-commit hook](https://github.com/nodesecurity/eslint-plugin-security/commit/e2ae2ee9ef214ca6d8f69fbcc438d230fda2bf97)
41
+ [Pre-commit hook](https://github.com/eslint-community/eslint-plugin-security/commit/e2ae2ee9ef214ca6d8f69fbcc438d230fda2bf97)
35
42
  - Added yarn installation method
36
43
  - Fix linting errors and step
37
- [Lint errors](https://github.com/nodesecurity/eslint-plugin-security/commit/1258118c2d07722e9fb388a672b287bb43bc73b3), [Lint step](https://github.com/nodesecurity/eslint-plugin-security/commit/84f3ed3ab88427753c7ac047d0bccbe557f28aa5)
44
+ [Lint errors](https://github.com/eslint-community/eslint-plugin-security/commit/1258118c2d07722e9fb388a672b287bb43bc73b3), [Lint step](https://github.com/eslint-community/eslint-plugin-security/commit/84f3ed3ab88427753c7ac047d0bccbe557f28aa5)
38
45
  - Create workflows
39
46
  Check commit message on pull requests, Set up ci on main branch
40
47
  - Update test and lint commands to work cross-platform
41
- [Commit](https://github.com/nodesecurity/eslint-plugin-security/commit/d3d8e7a27894aa3f83b560f530eb49750e9ee19a)
42
- - Merge pull request [#47](https://github.com/nodesecurity/eslint-plugin-security/pull/47) from pdehaan/add-docs
48
+ [Commit](https://github.com/eslint-community/eslint-plugin-security/commit/d3d8e7a27894aa3f83b560f530eb49750e9ee19a)
49
+ - Merge pull request [#47](https://github.com/eslint-community/eslint-plugin-security/pull/47) from pdehaan/add-docs
43
50
  Add old liftsecurity blog posts to docs/ folder
44
51
  - Bumped up dependencies
45
52
  - Added `package-lock.json`
@@ -50,19 +57,19 @@
50
57
 
51
58
  - 1.4.0
52
59
  - Stuff and things for 1.4.0 beep boop 🤖
53
- - Merge pull request [#14](https://github.com/nodesecurity/eslint-plugin-security/issues/14) from travi/recommended-example
60
+ - Merge pull request [#14](https://github.com/eslint-community/eslint-plugin-security/issues/14) from travi/recommended-example
54
61
  Add recommended ruleset to the usage example
55
- - Merge pull request [#19](https://github.com/nodesecurity/eslint-plugin-security/issues/19) from pdehaan/add-changelog
62
+ - Merge pull request [#19](https://github.com/eslint-community/eslint-plugin-security/issues/19) from pdehaan/add-changelog
56
63
  Add basic CHANGELOG.md file
57
- - Merge pull request [#17](https://github.com/nodesecurity/eslint-plugin-security/issues/17) from pdehaan/issue-16
64
+ - Merge pull request [#17](https://github.com/eslint-community/eslint-plugin-security/issues/17) from pdehaan/issue-16
58
65
  Remove filename from error output
59
66
  - Add basic CHANGELOG.md file
60
67
  - Remove filename from error output
61
68
  - Add recommended ruleset to the usage example
62
- for [#9](https://github.com/nodesecurity/eslint-plugin-security/issues/9)
63
- - Merge pull request [#10](https://github.com/nodesecurity/eslint-plugin-security/issues/10) from pdehaan/issue-9
69
+ for [#9](https://github.com/eslint-community/eslint-plugin-security/issues/9)
70
+ - Merge pull request [#10](https://github.com/eslint-community/eslint-plugin-security/issues/10) from pdehaan/issue-9
64
71
  Add 'plugin:security/recommended' config to plugin
65
- - Merge pull request [#12](https://github.com/nodesecurity/eslint-plugin-security/issues/12) from tupaschoal/patch-1
72
+ - Merge pull request [#12](https://github.com/eslint-community/eslint-plugin-security/issues/12) from tupaschoal/patch-1
66
73
  Fix broken link for detect-object-injection
67
74
  - Fix broken link for detect-object-injection
68
75
  The current link leads to a 404 page, the new one is the proper page.
@@ -73,15 +80,15 @@
73
80
  - 1.3.0
74
81
  - Merge branch 'scottnonnenberg-update-docs'
75
82
  - Fix merge conflicts because I can't figure out how to accept pr's in the right order
76
- - Merge pull request [#7](https://github.com/nodesecurity/eslint-plugin-security/issues/7) from HamletDRC/patch-1
83
+ - Merge pull request [#7](https://github.com/eslint-community/eslint-plugin-security/issues/7) from HamletDRC/patch-1
77
84
  README.md - documentation detect-new-buffer rule
78
- - Merge pull request [#8](https://github.com/nodesecurity/eslint-plugin-security/issues/8) from HamletDRC/patch-2
85
+ - Merge pull request [#8](https://github.com/eslint-community/eslint-plugin-security/issues/8) from HamletDRC/patch-2
79
86
  README.md - document detect-disable-mustache-escape rule
80
- - Merge pull request [#3](https://github.com/nodesecurity/eslint-plugin-security/issues/3) from jesusprubio/master
87
+ - Merge pull request [#3](https://github.com/eslint-community/eslint-plugin-security/issues/3) from jesusprubio/master
81
88
  A bit of love
82
89
  - README.md - document detect-disable-mustache-escape rule
83
90
  - README.md - documentation detect-new-buffer rule
84
- - Merge pull request [#6](https://github.com/nodesecurity/eslint-plugin-security/issues/6) from mathieumg/csrf-bug
91
+ - Merge pull request [#6](https://github.com/eslint-community/eslint-plugin-security/issues/6) from mathieumg/csrf-bug
85
92
  Fixed crash with `detect-no-csrf-before-method-override` rule
86
93
  - Fixed crash with `detect-no-csrf-before-method-override` rule.
87
94
  - Finishing last commit
@@ -95,7 +102,6 @@
95
102
  - A little bit of massage to readme intro
96
103
  - Add additional information to README for each rule
97
104
 
98
-
99
105
  ## 1.2.0 / 2016-01-21
100
106
 
101
107
  - 1.2.0
@@ -11,7 +11,7 @@ Let's take a look at why this could be a problem.
11
11
  ## Issue #1: Bracket object notation with user input grants access to every property available on the object
12
12
 
13
13
  ```js
14
- exampleClass[userInput[1]] = userInput[2];
14
+ exampleClass[userInput[0]] = userInput[1];
15
15
  ```
16
16
 
17
17
  I won't spend much time here, as I believe this is fairly well known. If exampleClass contains a sensitive property, the above code will allow it to be edited.
@@ -20,7 +20,7 @@ I won't spend much time here, as I believe this is fairly well known. If example
20
20
 
21
21
  ```js
22
22
  userInput = ['constructor', '{}'];
23
- exampleClass[userInput[1]] = userInput[2];
23
+ exampleClass[userInput[0]] = userInput[1];
24
24
  ```
25
25
 
26
26
  This looks pretty innocuous, even if it is an uncommon pattern. The problem here is that we can access or overwrite prototypes such as `constructor` or `__defineGetter__`, which may be used later on. The most likely outcome of this scenario would be an application crash, when a string is attempted to be called as a function.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-security",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "description": "Security rules for eslint",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -18,7 +18,7 @@
18
18
  },
19
19
  "repository": {
20
20
  "type": "git",
21
- "url": "git+https://github.com/nodesecurity/eslint-plugin-security.git"
21
+ "url": "git+https://github.com/eslint-community/eslint-plugin-security.git"
22
22
  },
23
23
  "keywords": [
24
24
  "eslint",
@@ -28,9 +28,9 @@
28
28
  "author": "Node Security Project",
29
29
  "license": "Apache-2.0",
30
30
  "bugs": {
31
- "url": "https://github.com/nodesecurity/eslint-plugin-security/issues"
31
+ "url": "https://github.com/eslint-community/eslint-plugin-security/issues"
32
32
  },
33
- "homepage": "https://github.com/nodesecurity/eslint-plugin-security#readme",
33
+ "homepage": "https://github.com/eslint-community/eslint-plugin-security#readme",
34
34
  "gitHooks": {
35
35
  "pre-commit": "lint-staged"
36
36
  },
@@ -5,6 +5,9 @@
5
5
 
6
6
  'use strict';
7
7
 
8
+ const { getImportAccessPath } = require('../utils/import-utils');
9
+ const childProcessPackageNames = ['child_process', 'node:child_process'];
10
+
8
11
  //------------------------------------------------------------------------------
9
12
  // Rule Definition
10
13
  //------------------------------------------------------------------------------
@@ -20,54 +23,37 @@ module.exports = {
20
23
  },
21
24
  },
22
25
  create: function (context) {
23
- /*
24
- * Stores variable identifiers pointing to child_process to check (child_process).exec()
25
- */
26
- const childProcessIdentifiers = new Set();
27
-
28
- /**
29
- * Extract identifiers assigned the expression `require("child_process")`.
30
- * @param {Pattern} node
31
- */
32
- function extractChildProcessIdentifiers(node) {
33
- if (node.type !== 'Identifier') {
34
- return;
35
- }
36
- const variable = context.getScope().set.get(node.name);
37
- if (!variable) {
38
- return;
39
- }
40
- for (const reference of variable.references) {
41
- childProcessIdentifiers.add(reference.identifier);
42
- }
43
- }
44
-
45
26
  return {
46
27
  CallExpression: function (node) {
47
28
  if (node.callee.name === 'require') {
48
29
  const args = node.arguments[0];
49
- if (args && args.type === 'Literal' && args.value === 'child_process') {
50
- let pattern;
51
- if (node.parent.type === 'VariableDeclarator') {
52
- pattern = node.parent.id;
53
- } else if (node.parent.type === 'AssignmentExpression' && node.parent.operator === '=') {
54
- pattern = node.parent.left;
55
- }
56
- if (pattern) {
57
- extractChildProcessIdentifiers(pattern);
58
- }
59
- if (!pattern || pattern.type === 'Identifier') {
60
- return context.report({ node: node, message: 'Found require("child_process")' });
61
- }
30
+ if (
31
+ args &&
32
+ args.type === 'Literal' &&
33
+ childProcessPackageNames.includes(args.value) &&
34
+ node.parent.type !== 'VariableDeclarator' &&
35
+ node.parent.type !== 'AssignmentExpression' &&
36
+ node.parent.type !== 'MemberExpression'
37
+ ) {
38
+ context.report({ node: node, message: 'Found require("' + args.value + '")' });
62
39
  }
40
+ return;
63
41
  }
64
- },
65
- MemberExpression: function (node) {
66
- if (node.property.name === 'exec' && childProcessIdentifiers.has(node.object)) {
67
- if (node.parent && node.parent.arguments && node.parent.arguments.length && node.parent.arguments[0].type !== 'Literal') {
68
- return context.report({ node: node, message: 'Found child_process.exec() with non Literal first argument' });
69
- }
42
+
43
+ // Reports non-literal `exec()` calls.
44
+ if (!node.arguments.length || node.arguments[0].type === 'Literal') {
45
+ return;
46
+ }
47
+ const pathInfo = getImportAccessPath({
48
+ node: node.callee,
49
+ scope: context.getScope(),
50
+ packageNames: childProcessPackageNames,
51
+ });
52
+ const fnName = pathInfo && pathInfo.path.length === 1 && pathInfo.path[0];
53
+ if (fnName !== 'exec') {
54
+ return;
70
55
  }
56
+ context.report({ node: node, message: 'Found child_process.exec() with non Literal first argument' });
71
57
  },
72
58
  };
73
59
  },
@@ -1,7 +1,12 @@
1
1
  'use strict';
2
2
 
3
3
  const RuleTester = require('eslint').RuleTester;
4
- const tester = new RuleTester();
4
+ const tester = new RuleTester({
5
+ parserOptions: {
6
+ ecmaVersion: 6,
7
+ sourceType: 'module',
8
+ },
9
+ });
5
10
 
6
11
  const ruleName = 'detect-child-process';
7
12
  const rule = require(`../rules/${ruleName}`);
@@ -9,53 +14,123 @@ const rule = require(`../rules/${ruleName}`);
9
14
  tester.run(ruleName, rule, {
10
15
  valid: [
11
16
  "child_process.exec('ls')",
12
- {
13
- code: `
14
- var {} = require('child_process');
15
- var result = /hello/.exec(str);`,
16
- parserOptions: { ecmaVersion: 6 },
17
- },
18
- {
19
- code: "var { spawn } = require('child_process'); spawn(str);",
20
- parserOptions: { ecmaVersion: 6 },
21
- },
17
+ `
18
+ var {} = require('child_process');
19
+ var result = /hello/.exec(str);`,
20
+ `
21
+ var {} = require('node:child_process');
22
+ var result = /hello/.exec(str);`,
23
+ `
24
+ import {} from 'child_process';
25
+ var result = /hello/.exec(str);`,
26
+ `
27
+ import {} from 'node:child_process';
28
+ var result = /hello/.exec(str);`,
29
+ "var { spawn } = require('child_process'); spawn(str);",
30
+ "var { spawn } = require('node:child_process'); spawn(str);",
31
+ "import { spawn } from 'child_process'; spawn(str);",
32
+ "import { spawn } from 'node:child_process'; spawn(str);",
33
+ `
34
+ var foo = require('child_process');
35
+ function fn () {
36
+ var foo = /hello/;
37
+ var result = foo.exec(str);
38
+ }`,
39
+ "var child = require('child_process'); child.spawn(str)",
40
+ "var child = require('node:child_process'); child.spawn(str)",
41
+ "import child from 'child_process'; child.spawn(str)",
42
+ "import child from 'node:child_process'; child.spawn(str)",
43
+ `
44
+ var foo = require('child_process');
45
+ function fn () {
46
+ var result = foo.spawn(str);
47
+ }`,
48
+ "require('child_process').spawn(str)",
49
+ `
50
+ function fn () {
51
+ require('child_process').spawn(str)
52
+ }`,
22
53
  ],
23
54
  invalid: [
24
55
  {
25
56
  code: "require('child_process')",
26
57
  errors: [{ message: 'Found require("child_process")' }],
27
58
  },
59
+ {
60
+ code: "require('node:child_process')",
61
+ errors: [{ message: 'Found require("node:child_process")' }],
62
+ },
28
63
  {
29
64
  code: "var child = require('child_process'); child.exec(com)",
30
- errors: [{ message: 'Found require("child_process")' }, { message: 'Found child_process.exec() with non Literal first argument' }],
65
+ errors: [{ message: 'Found child_process.exec() with non Literal first argument' }],
31
66
  },
32
67
  {
33
- code: "var child = require('child_process'); child.exec()",
34
- errors: [{ message: 'Found require("child_process")' }],
68
+ code: "var child = require('node:child_process'); child.exec(com)",
69
+ errors: [{ message: 'Found child_process.exec() with non Literal first argument' }],
70
+ },
71
+ {
72
+ code: "import child from 'child_process'; child.exec(com)",
73
+ errors: [{ message: 'Found child_process.exec() with non Literal first argument' }],
74
+ },
75
+ {
76
+ code: "import child from 'node:child_process'; child.exec(com)",
77
+ errors: [{ message: 'Found child_process.exec() with non Literal first argument' }],
35
78
  },
36
79
  {
37
80
  code: "var child = sinon.stub(require('child_process')); child.exec.returns({});",
38
81
  errors: [{ message: 'Found require("child_process")' }],
39
82
  },
83
+ {
84
+ code: "var child = sinon.stub(require('node:child_process')); child.exec.returns({});",
85
+ errors: [{ message: 'Found require("node:child_process")' }],
86
+ },
40
87
  {
41
88
  code: `
42
89
  var foo = require('child_process');
43
90
  function fn () {
44
91
  var result = foo.exec(str);
45
92
  }`,
46
- errors: [
47
- { message: 'Found require("child_process")', line: 2 },
48
- { message: 'Found child_process.exec() with non Literal first argument', line: 4 },
49
- ],
93
+ errors: [{ message: 'Found child_process.exec() with non Literal first argument', line: 4 }],
50
94
  },
51
95
  {
52
96
  code: `
53
- var foo = require('child_process');
97
+ import foo from 'child_process';
98
+ function fn () {
99
+ var result = foo.exec(str);
100
+ }`,
101
+ errors: [{ message: 'Found child_process.exec() with non Literal first argument', line: 4 }],
102
+ },
103
+ {
104
+ code: `
105
+ import foo from 'node:child_process';
54
106
  function fn () {
55
- var foo = /hello/;
56
107
  var result = foo.exec(str);
57
108
  }`,
58
- errors: [{ message: 'Found require("child_process")', line: 2 }],
109
+ errors: [{ message: 'Found child_process.exec() with non Literal first argument', line: 4 }],
110
+ },
111
+ {
112
+ code: `
113
+ require('child_process').exec(str)`,
114
+ errors: [{ message: 'Found child_process.exec() with non Literal first argument', line: 2 }],
115
+ },
116
+ {
117
+ code: `
118
+ function fn () {
119
+ require('child_process').exec(str)
120
+ }`,
121
+ errors: [{ message: 'Found child_process.exec() with non Literal first argument', line: 3 }],
122
+ },
123
+ {
124
+ code: `
125
+ const {exec} = require('child_process');
126
+ exec(str)`,
127
+ errors: [{ message: 'Found child_process.exec() with non Literal first argument', line: 3 }],
128
+ },
129
+ {
130
+ code: `
131
+ const {exec} = require('node:child_process');
132
+ exec(str)`,
133
+ errors: [{ message: 'Found child_process.exec() with non Literal first argument', line: 3 }],
59
134
  },
60
135
  ],
61
136
  });