@contrast/assess 1.5.0 → 1.6.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.
@@ -166,17 +166,22 @@ module.exports = function(core) {
166
166
 
167
167
  const sourceContext = sources.getStore()?.assess;
168
168
  if (!sourceContext) {
169
- logger.debug('No sourceContext found during Sink event creation');
169
+ logger.debug('no sourceContext found during sink event creation');
170
170
  return null;
171
171
  }
172
-
173
172
  const signature = signatures.get(name);
173
+ if (!signature) {
174
+ logger.debug({ name }, 'no signature found for sink event name');
175
+ return null;
176
+ }
177
+ if (!history.length) {
178
+ logger.debug({ data }, 'empty history for sink event');
179
+ return null;
180
+ }
174
181
  if (
175
- !signature ||
176
- !history.length ||
177
182
  ((source && !source.match(annotationRegExp)) || (!source && !signature.source))
178
183
  ) {
179
- logger.debug({ data }, 'Wrong sink event data submited. Sink event not created');
184
+ logger.debug({ data }, 'malformed or missing sink event source field');
180
185
  return null;
181
186
  }
182
187
 
@@ -15,6 +15,9 @@
15
15
 
16
16
  'use strict';
17
17
 
18
+ const {
19
+ DataflowTag: { URL_ENCODED }
20
+ } = require('@contrast/common');
18
21
  const {
19
22
  createFullLengthCopyTags
20
23
  } = require('../../tag-utils');
@@ -47,7 +50,7 @@ module.exports = function(core) {
47
50
  // the result is not tracked, so we don't need to check for that
48
51
  const history = [argInfo];
49
52
  const newTags = createFullLengthCopyTags(argInfo.tags, result.length);
50
- delete newTags['url-encoded'];
53
+ delete newTags[URL_ENCODED];
51
54
 
52
55
  if (!Object.keys(newTags).length) return;
53
56
 
@@ -64,7 +67,7 @@ module.exports = function(core) {
64
67
  args: [{ value: argInfo.value, tracked: true }],
65
68
  tags: newTags,
66
69
  history,
67
- removedTags: ['url-encoded'],
70
+ removedTags: [URL_ENCODED],
68
71
  stacktraceOpts: {
69
72
  constructorOpt: hooked,
70
73
  prependFrames: [orig]
@@ -15,6 +15,9 @@
15
15
 
16
16
  'use strict';
17
17
 
18
+ const {
19
+ DataflowTag: { WEAK_URL_ENCODED }
20
+ } = require('@contrast/common');
18
21
  const {
19
22
  createFullLengthCopyTags
20
23
  } = require('../../../tag-utils');
@@ -48,7 +51,7 @@ module.exports = function(core) {
48
51
  const history = [argInfo];
49
52
  const newTags = createFullLengthCopyTags(argInfo.tags, result.length);
50
53
 
51
- newTags['weak-url-encoded'] = [0, result.length - 1];
54
+ newTags[WEAK_URL_ENCODED] = [0, result.length - 1];
52
55
 
53
56
  const event = createPropagationEvent({
54
57
  name: 'ejs.utils.escapeXML',
@@ -62,7 +65,7 @@ module.exports = function(core) {
62
65
  },
63
66
  args: [{ value: argInfo.value, tracked: true }],
64
67
  tags: newTags,
65
- addedTags: ['weak-url-encoded'],
68
+ addedTags: [WEAK_URL_ENCODED],
66
69
  history,
67
70
  stacktraceOpts: {
68
71
  constructorOpt: hooked,
@@ -15,10 +15,13 @@
15
15
 
16
16
  'use strict';
17
17
 
18
+ const {
19
+ DataflowTag: { HTML_ENCODED }
20
+ } = require('@contrast/common');
18
21
  const {
19
22
  createFullLengthCopyTags
20
23
  } = require('../../tag-utils');
21
- const { patchType, createModuleLabel } = require('../common');
24
+ const { patchType } = require('../common');
22
25
 
23
26
  module.exports = function(core) {
24
27
  const {
@@ -48,12 +51,12 @@ module.exports = function(core) {
48
51
  const history = [argInfo];
49
52
  const newTags = createFullLengthCopyTags(argInfo.tags, result.length);
50
53
 
51
- newTags['html-encoded'] = [0, result.length - 1];
54
+ newTags[HTML_ENCODED] = [0, result.length - 1];
52
55
 
53
56
  const event = createPropagationEvent({
54
57
  name: 'escape-html',
55
58
  object: {
56
- value: createModuleLabel('escape-html', version),
59
+ value: 'escape-html',
57
60
  tracked: false
58
61
  },
59
62
  result: {
@@ -63,7 +66,7 @@ module.exports = function(core) {
63
66
  args: [{ value: argInfo.value, tracked: true }],
64
67
  tags: newTags,
65
68
  history,
66
- addedTags: ['html-encoded'],
69
+ addedTags: [HTML_ENCODED],
67
70
  stacktraceOpts: {
68
71
  constructorOpt: hooked,
69
72
  prependFrames: [orig]
@@ -15,6 +15,9 @@
15
15
 
16
16
  'use strict';
17
17
 
18
+ const {
19
+ DataflowTag: { WEAK_URL_ENCODED }
20
+ } = require('@contrast/common');
18
21
  const {
19
22
  createFullLengthCopyTags
20
23
  } = require('../../tag-utils');
@@ -46,7 +49,7 @@ module.exports = function(core) {
46
49
  const history = [argInfo];
47
50
  const newTags = createFullLengthCopyTags(argInfo.tags, result.length);
48
51
 
49
- newTags['weak-url-encoded'] = [0, result.length - 1];
52
+ newTags[WEAK_URL_ENCODED] = [0, result.length - 1];
50
53
 
51
54
  const event = createPropagationEvent({
52
55
  name: 'global.escape',
@@ -61,7 +64,7 @@ module.exports = function(core) {
61
64
  args: [{ value: argInfo.value, tracked: true }],
62
65
  tags: newTags,
63
66
  history,
64
- addedTags: ['weak-url-encoded'],
67
+ addedTags: [WEAK_URL_ENCODED],
65
68
  stacktraceOpts: {
66
69
  constructorOpt: hooked,
67
70
  prependFrames: [orig]
@@ -15,6 +15,9 @@
15
15
 
16
16
  'use strict';
17
17
 
18
+ const {
19
+ DataflowTag: { HTML_ENCODED }
20
+ } = require('@contrast/common');
18
21
  const {
19
22
  createFullLengthCopyTags
20
23
  } = require('../../tag-utils');
@@ -48,7 +51,7 @@ module.exports = function(core) {
48
51
  const history = [argInfo];
49
52
  const newTags = createFullLengthCopyTags(argInfo.tags, result.length);
50
53
 
51
- newTags['html-encoded'] = [0, result.length - 1];
54
+ newTags[HTML_ENCODED] = [0, result.length - 1];
52
55
 
53
56
  const event = createPropagationEvent({
54
57
  name: 'handlebars.Utils.escapeExpression',
@@ -62,7 +65,7 @@ module.exports = function(core) {
62
65
  },
63
66
  args: [{ value: argInfo.value, tracked: true }],
64
67
  tags: newTags,
65
- addedTags: ['html-encoded'],
68
+ addedTags: [HTML_ENCODED],
66
69
  history,
67
70
  stacktraceOpts: {
68
71
  constructorOpt: hooked,
@@ -15,6 +15,9 @@
15
15
 
16
16
  'use strict';
17
17
 
18
+ const {
19
+ DataflowTag: { SQL_ENCODED }
20
+ } = require('@contrast/common');
18
21
  const {
19
22
  createFullLengthCopyTags
20
23
  } = require('../../tag-utils');
@@ -43,7 +46,7 @@ module.exports = function(core) {
43
46
  const history = [argInfo];
44
47
  const newTags = createFullLengthCopyTags(argInfo.tags, result.length);
45
48
 
46
- newTags['sql-encoded'] = [0, result.length - 1];
49
+ newTags[SQL_ENCODED] = [0, result.length - 1];
47
50
 
48
51
  const event = createPropagationEvent({
49
52
  name: eventName,
@@ -57,7 +60,7 @@ module.exports = function(core) {
57
60
  },
58
61
  args: [{ value: argInfo.value, tracked: true }],
59
62
  tags: newTags,
60
- addedTags: ['sql-encoded'],
63
+ addedTags: [SQL_ENCODED],
61
64
  history,
62
65
  stacktraceOpts: {
63
66
  constructorOpt: hooked,
@@ -14,8 +14,13 @@
14
14
  */
15
15
 
16
16
  'use strict';
17
+
17
18
  const util = require('util');
18
19
  const querystring = require('querystring');
20
+ const {
21
+ DataflowTag: { URL_ENCODED }
22
+ } = require('@contrast/common');
23
+
19
24
  const { patchType } = require('../../common');
20
25
  const { createSubsetTags, createAppendTags } = require('../../../tag-utils');
21
26
 
@@ -73,9 +78,9 @@ module.exports = function(core) {
73
78
  event.tags = createAppendTags(event.tags, resultInfo.tags, 0);
74
79
  Object.assign(resultInfo, event);
75
80
  }
76
- if (event.tags['url-encoded']) {
77
- delete event.tags['url-encoded'];
78
- event.removedTags = ['url-encoded'];
81
+ if (event.tags[URL_ENCODED]) {
82
+ delete event.tags[URL_ENCODED];
83
+ event.removedTags = [URL_ENCODED];
79
84
  }
80
85
  const { extern } = resultInfo || tracker.track(result, event);
81
86
  if (extern) {
@@ -15,6 +15,9 @@
15
15
 
16
16
  'use strict';
17
17
 
18
+ const {
19
+ DataflowTag: { UNTRUSTED }
20
+ } = require('@contrast/common');
18
21
  const { patchType } = require('../../common');
19
22
  const { createSubsetTags, createAppendTags } = require('../../../tag-utils');
20
23
 
@@ -148,7 +151,8 @@ module.exports = function(core) {
148
151
  !sources.getStore()?.assess ||
149
152
  instrumentation.isLocked() ||
150
153
  !data.result ||
151
- !data._accumTags?.untrusted
154
+ // todo: can we reuse this optimization in other propagators? e.g those performing substring-like operations
155
+ !data._accumTags?.[UNTRUSTED]
152
156
  ) return;
153
157
 
154
158
  const { _replacementInfo, obj, args, result, hooked, orig } = data;
@@ -15,6 +15,9 @@
15
15
 
16
16
  'use strict';
17
17
 
18
+ const {
19
+ DataflowTag: { WEAK_URL_ENCODED }
20
+ } = require('@contrast/common');
18
21
  const {
19
22
  createFullLengthCopyTags
20
23
  } = require('../../tag-utils');
@@ -45,7 +48,7 @@ module.exports = function(core) {
45
48
  const resultInfo = tracker.getData(result);
46
49
  const history = [argInfo];
47
50
  const newTags = createFullLengthCopyTags(argInfo.tags, result.length);
48
- delete newTags['weak-url-encoded'];
51
+ delete newTags[WEAK_URL_ENCODED];
49
52
 
50
53
  if (!Object.keys(newTags).length) return;
51
54
 
@@ -62,7 +65,7 @@ module.exports = function(core) {
62
65
  args: [{ value: argInfo.value, tracked: true }],
63
66
  tags: newTags,
64
67
  history,
65
- removedTags: ['weak-url-encoded'],
68
+ removedTags: [WEAK_URL_ENCODED],
66
69
  stacktraceOpts: {
67
70
  constructorOpt: hooked,
68
71
  prependFrames: [orig]
@@ -15,57 +15,66 @@
15
15
 
16
16
  'use strict';
17
17
 
18
+ const {
19
+ DataflowTag: {
20
+ ALPHANUM_SPACE_HYPHEN,
21
+ CUSTOM_VALIDATED,
22
+ HTML_ENCODED,
23
+ LIMITED_CHARS,
24
+ }
25
+ } = require('@contrast/common');
26
+
18
27
  module.exports = {
19
28
  validators: {
20
- isAfter: 'alphanum-space-hyphen',
21
- isAlpha: 'alphanum-space-hyphen',
22
- isAlphanumeric: 'alphanum-space-hyphen',
23
- isBase32: 'alphanum-space-hyphen',
24
- isBase58: 'alphanum-space-hyphen',
25
- isBase64: 'alphanum-space-hyphen',
26
- isBefore: 'alphanum-space-hyphen',
27
- isBIC: 'alphanum-space-hyphen',
28
- isBoolean: 'limited-chars',
29
- isBtcAddress: 'alphanum-space-hyphen',
30
- isCreditCard: 'limited-chars',
31
- isDate: 'limited-chars',
32
- isDecimal: 'limited-chars',
33
- isEAN: 'limited-chars',
34
- isEthereumAddress: 'alphanum-space-hyphen',
35
- isFloat: 'limited-chars',
36
- isHash: 'alphanum-space-hyphen',
37
- isHexadecimal: 'alphanum-space-hyphen',
38
- isHexColor: 'alphanum-space-hyphen',
39
- isHSL: 'alphanum-space-hyphen',
40
- isIBAN: 'limited-chars',
41
- isIdentityCard: 'alphanum-space-hyphen',
42
- isIMEI: 'limited-chars',
43
- isInt: 'limited-chars',
44
- isIP: 'limited-chars',
45
- isIPRange: 'limited-chars',
46
- isISBN: 'limited-chars',
47
- isISIN: 'limited-chars',
48
- isISO8601: 'alphanum-space-hyphen',
49
- isISO31661Alpha2: 'alphanum-space-hyphen',
50
- isISO31661Alpha3: 'alphanum-space-hyphen',
51
- isISRC: 'alphanum-space-hyphen',
52
- isISSN: 'limited-chars',
53
- isJWT: 'alphanum-space-hyphen',
54
- isLatLong: 'limited-chars',
55
- isLicensePlate: 'alphanum-space-hyphen',
56
- isMACAddress: 'alphanum-space-hyphen',
57
- isMagnetURI: 'alphanum-space-hyphen',
58
- isMD5: 'alphanum-space-hyphen',
59
- isMobilePhone: 'limited-chars',
60
- isNumeric: 'limited-chars',
61
- isOctal: 'alphanum-space-hyphen',
62
- isPassportNumber: 'limited-chars',
63
- isPostalCode: 'limited-chars',
64
- isSemVer: 'limited-chars',
65
- isTaxID: 'limited-chars',
66
- isUUID: 'alphanum-space-hyphen',
67
- isVAT: 'alphanum-space-hyphen',
68
- matches: 'custom-validated'
29
+ isAfter: ALPHANUM_SPACE_HYPHEN,
30
+ isAlpha: ALPHANUM_SPACE_HYPHEN,
31
+ isAlphanumeric: ALPHANUM_SPACE_HYPHEN,
32
+ isBase32: ALPHANUM_SPACE_HYPHEN,
33
+ isBase58: ALPHANUM_SPACE_HYPHEN,
34
+ isBase64: ALPHANUM_SPACE_HYPHEN,
35
+ isBefore: ALPHANUM_SPACE_HYPHEN,
36
+ isBIC: ALPHANUM_SPACE_HYPHEN,
37
+ isBoolean: LIMITED_CHARS,
38
+ isBtcAddress: ALPHANUM_SPACE_HYPHEN,
39
+ isCreditCard: LIMITED_CHARS,
40
+ isDate: LIMITED_CHARS,
41
+ isDecimal: LIMITED_CHARS,
42
+ isEAN: LIMITED_CHARS,
43
+ isEthereumAddress: ALPHANUM_SPACE_HYPHEN,
44
+ isFloat: LIMITED_CHARS,
45
+ isHash: ALPHANUM_SPACE_HYPHEN,
46
+ isHexadecimal: ALPHANUM_SPACE_HYPHEN,
47
+ isHexColor: ALPHANUM_SPACE_HYPHEN,
48
+ isHSL: ALPHANUM_SPACE_HYPHEN,
49
+ isIBAN: LIMITED_CHARS,
50
+ isIdentityCard: ALPHANUM_SPACE_HYPHEN,
51
+ isIMEI: LIMITED_CHARS,
52
+ isInt: LIMITED_CHARS,
53
+ isIP: LIMITED_CHARS,
54
+ isIPRange: LIMITED_CHARS,
55
+ isISBN: LIMITED_CHARS,
56
+ isISIN: LIMITED_CHARS,
57
+ isISO8601: ALPHANUM_SPACE_HYPHEN,
58
+ isISO31661Alpha2: ALPHANUM_SPACE_HYPHEN,
59
+ isISO31661Alpha3: ALPHANUM_SPACE_HYPHEN,
60
+ isISRC: ALPHANUM_SPACE_HYPHEN,
61
+ isISSN: LIMITED_CHARS,
62
+ isJWT: ALPHANUM_SPACE_HYPHEN,
63
+ isLatLong: LIMITED_CHARS,
64
+ isLicensePlate: ALPHANUM_SPACE_HYPHEN,
65
+ isMACAddress: ALPHANUM_SPACE_HYPHEN,
66
+ isMagnetURI: ALPHANUM_SPACE_HYPHEN,
67
+ isMD5: ALPHANUM_SPACE_HYPHEN,
68
+ isMobilePhone: LIMITED_CHARS,
69
+ isNumeric: LIMITED_CHARS,
70
+ isOctal: ALPHANUM_SPACE_HYPHEN,
71
+ isPassportNumber: LIMITED_CHARS,
72
+ isPostalCode: LIMITED_CHARS,
73
+ isSemVer: LIMITED_CHARS,
74
+ isTaxID: LIMITED_CHARS,
75
+ isUUID: ALPHANUM_SPACE_HYPHEN,
76
+ isVAT: ALPHANUM_SPACE_HYPHEN,
77
+ matches: CUSTOM_VALIDATED,
69
78
  },
70
79
  untrackers: [
71
80
  'equals',
@@ -74,9 +83,9 @@ module.exports = {
74
83
  'isRFC3339'
75
84
  ],
76
85
  sanitizers: {
77
- escape: 'html-encoded'
86
+ escape: HTML_ENCODED
78
87
  },
79
88
  custom: {
80
- isEmail: 'limited-chars'
89
+ isEmail: LIMITED_CHARS
81
90
  }
82
91
  };
@@ -41,10 +41,14 @@ module.exports = function (core) {
41
41
  require('./install/fastify')(core);
42
42
  require('./install/koa')(core);
43
43
  require('./install/child-process')(core);
44
+ require('./install/fs')(core);
44
45
  require('./install/http')(core);
46
+ require('./install/mongodb')(core);
45
47
  require('./install/mssql')(core);
48
+ require('./install/mysql')(core);
46
49
  require('./install/postgres')(core);
47
50
  require('./install/sqlite3')(core);
51
+ require('./install/marsdb')(core);
48
52
 
49
53
  sinks.install = function() {
50
54
  callChildComponentMethodsSync(core.assess.dataflow.sinks, 'install');
@@ -14,8 +14,12 @@
14
14
  */
15
15
 
16
16
  'use strict';
17
+ const {
18
+ DataflowTag: { UNTRUSTED }
19
+ } = require('@contrast/common');
20
+
17
21
  const { patchType } = require('../common');
18
- const { Rule, isString } = require('@contrast/common');
22
+ const { Rule, isString, inspect } = require('@contrast/common');
19
23
 
20
24
  module.exports = function (core) {
21
25
  const {
@@ -31,14 +35,14 @@ module.exports = function (core) {
31
35
  },
32
36
  } = core;
33
37
 
34
- const pre = (name) => (data) => {
35
- const store = sources.getStore()?.assess;
36
- if (!store || !data.args[0] || !isString(data.args[0])) return;
38
+ const safeTags = [];
37
39
 
38
- const strInfo = tracker.getData(data.args[0]);
39
- if (!strInfo || !isVulnerable('untrusted', [], strInfo.tags)) {
40
- return;
41
- }
40
+ function commandCheck(name, command, secondArg, thirdArg, hooked) {
41
+ const strInfo = tracker.getData(command);
42
+ if (!strInfo || !isVulnerable(UNTRUSTED, safeTags, strInfo.tags)) return {
43
+ strInfo: null,
44
+ reported: false
45
+ };
42
46
 
43
47
  const event = createSinkEvent({
44
48
  name,
@@ -52,11 +56,19 @@ module.exports = function (core) {
52
56
  value: strInfo.value,
53
57
  tracked: true,
54
58
  },
55
- ],
59
+ (secondArg && {
60
+ value: inspect(secondArg),
61
+ tracked: false
62
+ }),
63
+ (thirdArg && {
64
+ value: inspect(thirdArg),
65
+ tracked: false
66
+ })
67
+ ].filter(Boolean),
56
68
  tags: strInfo.tags,
57
69
  source: 'P0',
58
70
  stacktraceOpts: {
59
- contructorOpt: data.hooked,
71
+ constructorOpt: hooked,
60
72
  },
61
73
  });
62
74
 
@@ -65,18 +77,143 @@ module.exports = function (core) {
65
77
  ruleId: Rule.CMD_INJECTION,
66
78
  sinkEvent: event,
67
79
  });
80
+
81
+ return {
82
+ strInfo,
83
+ reported: true
84
+ };
68
85
  }
69
- };
86
+
87
+ return {
88
+ strInfo,
89
+ reported: false
90
+ };
91
+ }
92
+
93
+ function argumentsCheck(name, command, commandInfo, args, options, hooked) {
94
+ if (!Array.isArray(args) || !args?.length) return;
95
+
96
+ const trackedArgs = [];
97
+ let vulnerableArgIdx;
98
+
99
+ for (let i = 0; i < args.length; i++) {
100
+ const trackData = tracker.getData(args[i]);
101
+
102
+ trackedArgs.push(trackData);
103
+
104
+ if (!trackData) {
105
+ continue;
106
+ }
107
+
108
+ if (
109
+ !vulnerableArgIdx &&
110
+ vulnerableArgIdx != 0 &&
111
+ isVulnerable(UNTRUSTED, safeTags, trackData.tags)
112
+ ) {
113
+ vulnerableArgIdx = i;
114
+ }
115
+ }
116
+
117
+ if (vulnerableArgIdx != 0 && !vulnerableArgIdx) return;
118
+
119
+ const event = createSinkEvent({
120
+ name,
121
+ history: [trackedArgs[vulnerableArgIdx]],
122
+ object: {
123
+ value: 'child_process',
124
+ tracked: false,
125
+ },
126
+ args: [
127
+ {
128
+ value: commandInfo?.value || command,
129
+ tracked: !!commandInfo,
130
+ },
131
+ {
132
+ value: inspect(args),
133
+ tracked: true
134
+ },
135
+ {
136
+ value: inspect(options),
137
+ tracked: false
138
+ }
139
+ ],
140
+ tags: trackedArgs[vulnerableArgIdx].tags,
141
+ source: 'P1',
142
+ stacktraceOpts: {
143
+ contructorOpt: hooked,
144
+ },
145
+ });
146
+
147
+ if (event) {
148
+ reportFindings({
149
+ ruleId: Rule.CMD_INJECTION,
150
+ sinkEvent: event,
151
+ });
152
+ }
153
+ }
70
154
 
71
155
  core.assess.dataflow.sinks.cmdInjection = {
72
156
  install() {
73
157
  depHooks.resolve({ name: 'child_process' }, cp => {
74
- ['spawn', 'spawnSync', 'exec', 'execSync'].forEach((method) => {
158
+ ['spawn', 'spawnSync'].forEach((method) => {
159
+ const name = `child_process.${method}`;
160
+ patcher.patch(cp, method, {
161
+ name,
162
+ patchType,
163
+ pre(data) {
164
+ const store = sources.getStore()?.assess;
165
+ const [command] = data.args;
166
+
167
+ if (!store || !command || !isString(command)) return;
168
+
169
+ const cpArgs = Array.isArray(data.args[1]) && data.args[1];
170
+ const options = cpArgs ? data.args[2] : data.args[1];
171
+
172
+ const cmdCheck = commandCheck(name, command, cpArgs, options, data.hooked);
173
+
174
+ if (cmdCheck.reported || !options?.shell) return;
175
+
176
+ argumentsCheck(name, command, cmdCheck.strInfo, cpArgs, options, data.hooked);
177
+ }
178
+ });
179
+ });
180
+
181
+ ['exec', 'execSync'].forEach((method) => {
182
+ const name = `child_process.${method}`;
183
+ patcher.patch(cp, method, {
184
+ name,
185
+ patchType,
186
+ pre(data) {
187
+ const store = sources.getStore()?.assess;
188
+ const [command, secondArg, thirdArg] = data.args;
189
+
190
+ if (!store || !command || !isString(command)) return;
191
+
192
+ commandCheck(name, command, secondArg, thirdArg, data.hooked);
193
+ }
194
+ });
195
+ });
196
+
197
+ ['execFile', 'execFileSync'].forEach((method) => {
75
198
  const name = `child_process.${method}`;
76
199
  patcher.patch(cp, method, {
77
200
  name,
78
201
  patchType,
79
- pre: pre(name)
202
+ pre(data) {
203
+ const store = sources.getStore()?.assess;
204
+ const [command] = data.args;
205
+
206
+ if (!store || !command || !isString(command)) return;
207
+
208
+ const cpArgs = Array.isArray(data.args[1]) && data.args[1];
209
+ const options = cpArgs ? data.args[2] : data.args[1];
210
+
211
+ if (!options?.shell) return;
212
+
213
+ const cmdInfo = tracker.getData(command);
214
+
215
+ argumentsCheck(name, command, cmdInfo, cpArgs, options, data.hooked);
216
+ }
80
217
  });
81
218
  });
82
219
  });