@contrast/assess 1.18.0 → 1.20.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.
Files changed (160) hide show
  1. package/LICENSE +1 -1
  2. package/lib/constants.js +26 -0
  3. package/lib/crypto-analysis/common.js +20 -0
  4. package/lib/crypto-analysis/index.js +44 -0
  5. package/lib/crypto-analysis/install/crypto.js +156 -0
  6. package/lib/crypto-analysis/install/math.js +104 -0
  7. package/lib/dataflow/index.js +1 -1
  8. package/lib/dataflow/propagation/common.js +1 -1
  9. package/lib/dataflow/propagation/index.js +1 -1
  10. package/lib/dataflow/propagation/install/JSON/index.js +1 -1
  11. package/lib/dataflow/propagation/install/JSON/parse-fn.js +1 -1
  12. package/lib/dataflow/propagation/install/JSON/parse.js +15 -14
  13. package/lib/dataflow/propagation/install/JSON/stringify.js +2 -2
  14. package/lib/dataflow/propagation/install/array-prototype-join.js +1 -1
  15. package/lib/dataflow/propagation/install/buffer.js +1 -1
  16. package/lib/dataflow/propagation/install/contrast-methods/add.js +1 -1
  17. package/lib/dataflow/propagation/install/contrast-methods/index.js +1 -1
  18. package/lib/dataflow/propagation/install/contrast-methods/number.js +4 -3
  19. package/lib/dataflow/propagation/install/contrast-methods/string.js +1 -1
  20. package/lib/dataflow/propagation/install/contrast-methods/tag.js +1 -1
  21. package/lib/dataflow/propagation/install/decode-uri-component.js +1 -1
  22. package/lib/dataflow/propagation/install/ejs/escape-xml.js +3 -3
  23. package/lib/dataflow/propagation/install/ejs/index.js +2 -1
  24. package/lib/dataflow/propagation/install/ejs/template.js +79 -0
  25. package/lib/dataflow/propagation/install/encode-uri.js +1 -1
  26. package/lib/dataflow/propagation/install/escape-html.js +1 -1
  27. package/lib/dataflow/propagation/install/escape.js +1 -1
  28. package/lib/dataflow/propagation/install/handlebars-utils-escape-expression.js +1 -1
  29. package/lib/dataflow/propagation/install/isnumeric-0.js +3 -3
  30. package/lib/dataflow/propagation/install/joi/any.js +1 -1
  31. package/lib/dataflow/propagation/install/joi/boolean.js +1 -1
  32. package/lib/dataflow/propagation/install/joi/expression.js +1 -1
  33. package/lib/dataflow/propagation/install/joi/index.js +1 -1
  34. package/lib/dataflow/propagation/install/joi/keys.js +1 -1
  35. package/lib/dataflow/propagation/install/joi/number.js +1 -1
  36. package/lib/dataflow/propagation/install/joi/object.js +1 -1
  37. package/lib/dataflow/propagation/install/joi/string-schema.js +1 -1
  38. package/lib/dataflow/propagation/install/joi/utils.js +1 -1
  39. package/lib/dataflow/propagation/install/joi/values.js +1 -1
  40. package/lib/dataflow/propagation/install/mongoose/common.js +1 -1
  41. package/lib/dataflow/propagation/install/mongoose/index.js +1 -1
  42. package/lib/dataflow/propagation/install/mongoose/schema-map.js +1 -1
  43. package/lib/dataflow/propagation/install/mongoose/schema-mixed.js +1 -1
  44. package/lib/dataflow/propagation/install/mongoose/schema-string.js +1 -1
  45. package/lib/dataflow/propagation/install/mustache-escape.js +1 -1
  46. package/lib/dataflow/propagation/install/mysql-connection-escape.js +1 -1
  47. package/lib/dataflow/propagation/install/parse-int.js +3 -3
  48. package/lib/dataflow/propagation/install/path/basename.js +1 -1
  49. package/lib/dataflow/propagation/install/path/common.js +1 -1
  50. package/lib/dataflow/propagation/install/path/dirname.js +1 -1
  51. package/lib/dataflow/propagation/install/path/extname.js +1 -1
  52. package/lib/dataflow/propagation/install/path/format.js +1 -1
  53. package/lib/dataflow/propagation/install/path/index.js +1 -1
  54. package/lib/dataflow/propagation/install/path/join-and-resolve.js +1 -1
  55. package/lib/dataflow/propagation/install/path/normalize.js +1 -1
  56. package/lib/dataflow/propagation/install/path/parse.js +1 -1
  57. package/lib/dataflow/propagation/install/path/relative.js +1 -1
  58. package/lib/dataflow/propagation/install/path/toNamespacedPath.js +1 -1
  59. package/lib/dataflow/propagation/install/pug/index.js +3 -3
  60. package/lib/dataflow/propagation/install/pug-runtime-escape.js +1 -1
  61. package/lib/dataflow/propagation/install/querystring/escape.js +1 -1
  62. package/lib/dataflow/propagation/install/querystring/index.js +1 -1
  63. package/lib/dataflow/propagation/install/querystring/parse.js +1 -1
  64. package/lib/dataflow/propagation/install/querystring/stringify.js +1 -1
  65. package/lib/dataflow/propagation/install/reg-exp-prototype-exec.js +1 -1
  66. package/lib/dataflow/propagation/install/send.js +1 -1
  67. package/lib/dataflow/propagation/install/sequelize/index.js +1 -1
  68. package/lib/dataflow/propagation/install/sequelize/query-generator.js +1 -1
  69. package/lib/dataflow/propagation/install/sequelize/sql-string.js +1 -1
  70. package/lib/dataflow/propagation/install/sql-template-strings.js +1 -1
  71. package/lib/dataflow/propagation/install/string/concat.js +1 -1
  72. package/lib/dataflow/propagation/install/string/format-methods.js +1 -1
  73. package/lib/dataflow/propagation/install/string/html-methods.js +1 -1
  74. package/lib/dataflow/propagation/install/string/index.js +1 -1
  75. package/lib/dataflow/propagation/install/string/match-all.js +1 -1
  76. package/lib/dataflow/propagation/install/string/match.js +1 -1
  77. package/lib/dataflow/propagation/install/string/replace.js +1 -1
  78. package/lib/dataflow/propagation/install/string/slice.js +1 -1
  79. package/lib/dataflow/propagation/install/string/split.js +1 -1
  80. package/lib/dataflow/propagation/install/string/substring.js +1 -1
  81. package/lib/dataflow/propagation/install/string/trim.js +1 -1
  82. package/lib/dataflow/propagation/install/unescape.js +1 -1
  83. package/lib/dataflow/propagation/install/url/domain-parsers.js +1 -1
  84. package/lib/dataflow/propagation/install/url/index.js +1 -1
  85. package/lib/dataflow/propagation/install/url/parse.js +1 -1
  86. package/lib/dataflow/propagation/install/url/searchParams.js +1 -1
  87. package/lib/dataflow/propagation/install/url/url.js +1 -1
  88. package/lib/dataflow/propagation/install/util-format.js +10 -4
  89. package/lib/dataflow/propagation/install/validator/hooks.js +1 -1
  90. package/lib/dataflow/propagation/install/validator/index.js +1 -1
  91. package/lib/dataflow/propagation/install/validator/methods.js +1 -1
  92. package/lib/dataflow/sinks/common.js +1 -1
  93. package/lib/dataflow/sinks/index.js +1 -1
  94. package/lib/dataflow/sinks/install/child-process.js +21 -15
  95. package/lib/dataflow/sinks/install/eval.js +17 -15
  96. package/lib/dataflow/sinks/install/express/index.js +1 -1
  97. package/lib/dataflow/sinks/install/express/unvalidated-redirect.js +15 -9
  98. package/lib/dataflow/sinks/install/fastify/index.js +1 -1
  99. package/lib/dataflow/sinks/install/fastify/unvalidated-redirect.js +13 -6
  100. package/lib/dataflow/sinks/install/fs.js +8 -8
  101. package/lib/dataflow/sinks/install/function.js +9 -13
  102. package/lib/dataflow/sinks/install/http/index.js +1 -1
  103. package/lib/dataflow/sinks/install/http/request.js +17 -9
  104. package/lib/dataflow/sinks/install/http/server-response.js +12 -3
  105. package/lib/dataflow/sinks/install/koa/index.js +1 -1
  106. package/lib/dataflow/sinks/install/koa/unvalidated-redirect.js +16 -9
  107. package/lib/dataflow/sinks/install/libxmljs.js +16 -11
  108. package/lib/dataflow/sinks/install/marsdb.js +17 -12
  109. package/lib/dataflow/sinks/install/mongodb.js +32 -22
  110. package/lib/dataflow/sinks/install/mssql.js +21 -10
  111. package/lib/dataflow/sinks/install/mysql.js +16 -9
  112. package/lib/dataflow/sinks/install/node-serialize.js +16 -18
  113. package/lib/dataflow/sinks/install/postgres.js +18 -5
  114. package/lib/dataflow/sinks/install/sequelize.js +23 -17
  115. package/lib/dataflow/sinks/install/sqlite3.js +21 -8
  116. package/lib/dataflow/sinks/install/vm.js +20 -18
  117. package/lib/dataflow/sources/common.js +1 -1
  118. package/lib/dataflow/sources/handler.js +11 -10
  119. package/lib/dataflow/sources/index.js +2 -2
  120. package/lib/dataflow/sources/install/body-parser1.js +11 -13
  121. package/lib/dataflow/sources/install/{busboy1.js → busboy.js} +15 -15
  122. package/lib/dataflow/sources/install/cookie-parser1.js +7 -6
  123. package/lib/dataflow/sources/install/express/index.js +1 -1
  124. package/lib/dataflow/sources/install/express/params.js +9 -10
  125. package/lib/dataflow/sources/install/express/parsedUrl.js +1 -1
  126. package/lib/dataflow/sources/install/fastify/fastify.js +6 -7
  127. package/lib/dataflow/sources/install/fastify/index.js +1 -1
  128. package/lib/dataflow/sources/install/formidable1.js +8 -6
  129. package/lib/dataflow/sources/install/http.js +17 -45
  130. package/lib/dataflow/sources/install/koa/index.js +2 -1
  131. package/lib/dataflow/sources/install/koa/koa-bodyparsers.js +10 -9
  132. package/lib/dataflow/sources/install/koa/koa-multer.js +102 -0
  133. package/lib/dataflow/sources/install/koa/koa-routers.js +6 -8
  134. package/lib/dataflow/sources/install/koa/koa2.js +42 -38
  135. package/lib/dataflow/sources/install/multer1.js +26 -52
  136. package/lib/dataflow/sources/install/qs6.js +7 -6
  137. package/lib/dataflow/sources/install/querystring.js +5 -8
  138. package/lib/dataflow/tag-utils.js +1 -1
  139. package/lib/dataflow/tracker.js +1 -1
  140. package/lib/dataflow/utils/is-safe-content-type.js +1 -1
  141. package/lib/dataflow/utils/is-vulnerable.js +1 -1
  142. package/lib/event-factory.js +75 -26
  143. package/lib/get-policy.js +68 -0
  144. package/lib/get-source-context.js +62 -0
  145. package/lib/index.d.ts +64 -0
  146. package/lib/index.js +21 -20
  147. package/lib/make-source-context.js +78 -0
  148. package/lib/response-scanning/handlers/index.js +56 -29
  149. package/lib/response-scanning/handlers/utils.js +1 -1
  150. package/lib/response-scanning/index.js +1 -1
  151. package/lib/response-scanning/install/http.js +14 -8
  152. package/lib/rule-scopes.js +48 -0
  153. package/lib/session-configuration/common.js +1 -1
  154. package/lib/session-configuration/handlers.js +66 -47
  155. package/lib/session-configuration/index.js +3 -1
  156. package/lib/session-configuration/install/express-session.js +23 -26
  157. package/lib/session-configuration/install/fastify-cookie.js +110 -0
  158. package/lib/session-configuration/install/hapi.js +8 -11
  159. package/lib/session-configuration/install/koa.js +101 -0
  160. package/package.json +2 -2
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright: 2023 Contrast Security, Inc
2
+ * Copyright: 2024 Contrast Security, Inc
3
3
  * Contact: support@contrastsecurity.com
4
4
  * License: Commercial
5
5
 
@@ -15,9 +15,8 @@
15
15
 
16
16
  'use strict';
17
17
 
18
- const { patchType } = require('../common');
19
18
  const {
20
- Rule: { XXE },
19
+ Rule: { XXE: ruleId },
21
20
  isString,
22
21
  DataflowTag: {
23
22
  UNTRUSTED,
@@ -26,18 +25,29 @@ const {
26
25
  },
27
26
  inspect
28
27
  } = require('@contrast/common');
28
+ const { InstrumentationType: { RULE } } = require('../../../constants');
29
+ const { patchType } = require('../common');
29
30
 
30
31
  const safeTags = [
31
32
  LIMITED_CHARS,
32
33
  ALPHANUM_SPACE_HYPHEN
33
34
  ];
34
35
 
36
+ /**
37
+ * @param {{
38
+ * assess: import('@contrast/assess').Assess,
39
+ * config: import('@contrast/config').Config,
40
+ * logger: import('@contrast/logger').Logger,
41
+ * messages: import('@contrast/common').Messages,
42
+ * }} core
43
+ * @returns {import('@contrast/common').Installable}
44
+ */
35
45
  module.exports = function(core) {
36
46
  const {
37
47
  depHooks,
38
48
  patcher,
39
- scopes: { sources, instrumentation },
40
49
  assess: {
50
+ getSourceContext,
41
51
  eventFactory: { createSinkEvent },
42
52
  dataflow: {
43
53
  tracker,
@@ -60,12 +70,7 @@ module.exports = function(core) {
60
70
  name: `${moduleName}.${method}`,
61
71
  patchType,
62
72
  pre(data) {
63
- const store = sources.getStore()?.assess;
64
- if (
65
- !store ||
66
- !data.args[0] ||
67
- instrumentation.isLocked()
68
- ) return;
73
+ if (!getSourceContext(RULE, ruleId) || !data.args[0]) return;
69
74
 
70
75
  const [xmlString, opts] = data.args;
71
76
 
@@ -104,7 +109,7 @@ module.exports = function(core) {
104
109
 
105
110
  if (event) {
106
111
  reportFindings({
107
- ruleId: XXE,
112
+ ruleId,
108
113
  sinkEvent: event,
109
114
  });
110
115
  }
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright: 2023 Contrast Security, Inc
2
+ * Copyright: 2024 Contrast Security, Inc
3
3
  * Contact: support@contrastsecurity.com
4
4
  * License: Commercial
5
5
 
@@ -15,10 +15,9 @@
15
15
  'use strict';
16
16
 
17
17
  const util = require('util');
18
- const { patchType } = require('../common');
19
18
  const {
20
19
  traverseValues,
21
- Rule,
20
+ Rule: { NOSQL_INJECTION_MONGO: ruleId },
22
21
  DataflowTag: {
23
22
  ALPHANUM_SPACE_HYPHEN,
24
23
  LIMITED_CHARS,
@@ -27,6 +26,8 @@ const {
27
26
  CUSTOM_VALIDATED_NOSQL_INJECTION,
28
27
  },
29
28
  } = require('@contrast/common');
29
+ const { InstrumentationType: { RULE } } = require('../../../constants');
30
+ const { patchType } = require('../common');
30
31
 
31
32
  const collectionMethods = ['find', 'findOne', 'update', 'remove'];
32
33
  const querySafeTags = [
@@ -36,13 +37,20 @@ const querySafeTags = [
36
37
  CUSTOM_VALIDATED_NOSQL_INJECTION,
37
38
  ];
38
39
 
39
- module.exports = function(core) {
40
+ /**
41
+ * @param {{
42
+ * assess: import('@contrast/assess').Assess,
43
+ * logger: import('@contrast/logger').Logger,
44
+ * }} core
45
+ * @returns {import('@contrast/common').Installable}
46
+ */
47
+ module.exports = function (core) {
40
48
  const {
41
49
  depHooks,
42
50
  logger,
43
51
  patcher,
44
- scopes: { sources, instrumentation },
45
52
  assess: {
53
+ getSourceContext,
46
54
  eventFactory: { createSinkEvent },
47
55
  dataflow: {
48
56
  tracker,
@@ -74,7 +82,7 @@ module.exports = function(core) {
74
82
  const name = `marsdb.Collection.prototype.${method}`;
75
83
 
76
84
  if (!proto[method]) {
77
- logger.trace({ name }, `marsdb method ${method} not found!`);
85
+ logger.trace('method %s not found - skipping instrumentation', name);
78
86
  return;
79
87
  }
80
88
 
@@ -82,10 +90,7 @@ module.exports = function(core) {
82
90
  name,
83
91
  patchType,
84
92
  around(next, data) {
85
- const sourceCtx = sources.getStore()?.assess;
86
- if (!sourceCtx || instrumentation.isLocked()) {
87
- return next();
88
- }
93
+ if (!getSourceContext(RULE, ruleId)) return next();
89
94
 
90
95
  const argIdx = 0;
91
96
  const result = getVulnerabilityInfo(data.args[argIdx]);
@@ -120,7 +125,7 @@ module.exports = function(core) {
120
125
  });
121
126
 
122
127
  if (sinkEvent) {
123
- reportFindings({ ruleId: Rule.NOSQL_INJECTION_MONGO, sinkEvent });
128
+ reportFindings({ ruleId, sinkEvent });
124
129
  }
125
130
 
126
131
  return next();
@@ -128,7 +133,7 @@ module.exports = function(core) {
128
133
  });
129
134
  }
130
135
 
131
- instr.install = function() {
136
+ instr.install = function () {
132
137
  depHooks.resolve({ name: 'marsdb' }, (marsdb) => {
133
138
  collectionMethods.forEach((method) => patchCollection(marsdb, method));
134
139
  });
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright: 2023 Contrast Security, Inc
2
+ * Copyright: 2024 Contrast Security, Inc
3
3
  * Contact: support@contrastsecurity.com
4
4
  * License: Commercial
5
5
 
@@ -24,12 +24,13 @@ const {
24
24
  LIMITED_CHARS,
25
25
  STRING_TYPE_CHECKED,
26
26
  },
27
- Rule: { NOSQL_INJECTION_MONGO },
27
+ Rule: { NOSQL_INJECTION_MONGO: ruleId },
28
28
  isNonEmptyObject,
29
29
  traverseValues,
30
30
  isString,
31
31
  inspect
32
32
  } = require('@contrast/common');
33
+ const { InstrumentationType: { RULE } } = require('../../../constants');
33
34
  const utils = require('../../tag-utils');
34
35
  const { patchType, filterSafeTags } = require('../common');
35
36
 
@@ -66,19 +67,28 @@ const querySafeTags = [
66
67
  STRING_TYPE_CHECKED,
67
68
  ];
68
69
 
69
- module.exports = function(core) {
70
+ /**
71
+ *
72
+ * @param {{
73
+ * assess: import('@contrast/assess').Assess,
74
+ * config: import('@contrast/config').Config,
75
+ * }} core
76
+ * @returns {import('@contrast/common').Installable}
77
+ */
78
+ module.exports = function (core) {
70
79
  const {
71
80
  config,
72
81
  depHooks,
73
82
  logger,
74
83
  patcher,
75
- scopes: { sources, instrumentation },
76
84
  assess: {
85
+ getSourceContext,
77
86
  eventFactory: { createSinkEvent },
78
87
  dataflow: {
79
88
  tracker,
80
- sinks: { isVulnerable, runInActiveSink, isLocked, reportFindings, reportSafePositive }
81
- }
89
+ sinks: { isVulnerable, reportFindings, reportSafePositive }
90
+ },
91
+ ruleScopes,
82
92
  }
83
93
  } = core;
84
94
 
@@ -227,18 +237,14 @@ module.exports = function(core) {
227
237
 
228
238
  function createAroundHook(entity, name, method, getInfoMethod, vulnerableArgIdxs) {
229
239
  const argsIdxsToCheck = vulnerableArgIdxs || [0];
230
- return function(next, data) {
231
- const { obj, args: origArgs } = data;
232
- const sourceCtx = sources.getStore()?.assess;
233
-
234
- if (isLocked(NOSQL_INJECTION_MONGO) || instrumentation.isLocked() || !sourceCtx) {
235
- return next();
236
- }
240
+ return function (next, data) {
241
+ if (!getSourceContext(RULE, ruleId)) return next();
237
242
 
243
+ const { obj, args: origArgs } = data;
244
+ const safeReports = [];
238
245
  let vulnInfo;
239
246
  let reportSafe;
240
247
  let vulnArgIdx;
241
- const safeReports = [];
242
248
 
243
249
  try {
244
250
  for (const argIdx of argsIdxsToCheck) {
@@ -272,13 +278,15 @@ module.exports = function(core) {
272
278
 
273
279
  reportSafePositive({
274
280
  name,
275
- ruleId: NOSQL_INJECTION_MONGO,
281
+ ruleId,
276
282
  safeTags,
277
283
  strInfo: strInfo.length === 1 ? strInfo[0] : strInfo
278
284
  });
279
285
  }
280
286
 
281
- return methodsWithNestedCalls.includes(method) ? runInActiveSink(NOSQL_INJECTION_MONGO, async () => await next()) : next();
287
+ return methodsWithNestedCalls.includes(method)
288
+ ? ruleScopes.run(ruleId, async () => await next())
289
+ : next();
282
290
  }
283
291
 
284
292
  const { path, strInfo } = vulnInfo;
@@ -313,17 +321,19 @@ module.exports = function(core) {
313
321
  });
314
322
 
315
323
  if (sinkEvent) {
316
- reportFindings({ ruleId: NOSQL_INJECTION_MONGO, sinkEvent });
324
+ reportFindings({ ruleId, sinkEvent });
317
325
  }
318
326
  } catch (err) {
319
- core.logger.error({ name, err }, 'assess sink analysis failed');
327
+ core.logger.error({ err, funcKey: data.funcKey }, 'assess sink analysis failed');
320
328
  }
321
329
 
322
- return methodsWithNestedCalls.includes(method) ? runInActiveSink(NOSQL_INJECTION_MONGO, async () => await next()) : next();
330
+ return methodsWithNestedCalls.includes(method)
331
+ ? ruleScopes.run(ruleId, async () => await next())
332
+ : next();
323
333
  };
324
334
  }
325
335
 
326
- instr.install = function() {
336
+ instr.install = function () {
327
337
  depHooks.resolve({ name: 'mongodb' }, (mongodb, version) => {
328
338
  patchCollection(mongodb, version);
329
339
  patchDatabase(mongodb, version);
@@ -336,7 +346,7 @@ module.exports = function(core) {
336
346
  const name = `mongodb.Collection.prototype.${method}`;
337
347
 
338
348
  if (!proto[method]) {
339
- logger.trace({ name, version }, 'method not found - skipping instrumentation');
349
+ logger.trace({ version }, 'method %s not found - skipping instrumentation', name);
340
350
  continue;
341
351
  }
342
352
 
@@ -374,7 +384,7 @@ module.exports = function(core) {
374
384
  const name = `mongodb.Db.prototype.${method}`;
375
385
 
376
386
  if (!proto[method]) {
377
- logger.trace({ name, version }, 'method not found - skipping instrumentation');
387
+ logger.trace({ version }, 'method %s not found - skipping instrumentation', name);
378
388
  continue;
379
389
  }
380
390
 
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright: 2023 Contrast Security, Inc
2
+ * Copyright: 2024 Contrast Security, Inc
3
3
  * Contact: support@contrastsecurity.com
4
4
  * License: Commercial
5
5
 
@@ -16,10 +16,17 @@
16
16
  'use strict';
17
17
 
18
18
  const {
19
- DataflowTag: { UNTRUSTED, SQL_ENCODED, LIMITED_CHARS, CUSTOM_VALIDATED, CUSTOM_ENCODED },
20
- Rule: { SQL_INJECTION },
19
+ DataflowTag: {
20
+ CUSTOM_VALIDATED,
21
+ CUSTOM_ENCODED,
22
+ LIMITED_CHARS,
23
+ SQL_ENCODED,
24
+ UNTRUSTED,
25
+ },
26
+ Rule: { SQL_INJECTION: ruleId },
21
27
  isString
22
28
  } = require('@contrast/common');
29
+ const { InstrumentationType: { RULE } } = require('../../../constants');
23
30
  const { createModuleLabel } = require('../../propagation/common');
24
31
  const { patchType, filterSafeTags } = require('../common');
25
32
 
@@ -30,15 +37,20 @@ const safeTags = [
30
37
  CUSTOM_ENCODED,
31
38
  ];
32
39
 
33
- const ruleId = SQL_INJECTION;
34
-
40
+ /**
41
+ * @param {{
42
+ * assess: import('@contrast/assess').Assess,
43
+ * config: import('@contrast/config').Config,
44
+ * }} core
45
+ * @returns {import('@contrast/common').Installable}
46
+ */
35
47
  module.exports = function(core) {
36
48
  const {
37
49
  depHooks,
38
50
  patcher,
39
51
  config,
40
- scopes: { sources },
41
52
  assess: {
53
+ getSourceContext,
42
54
  eventFactory: { createSinkEvent },
43
55
  dataflow: {
44
56
  tracker,
@@ -48,12 +60,11 @@ module.exports = function(core) {
48
60
  } = core;
49
61
 
50
62
  const pre = (name, method, obj, version) => (data) => {
51
- const store = sources.getStore()?.assess;
52
63
  if (
53
- !store ||
64
+ !getSourceContext(RULE, ruleId) ||
54
65
  !data.args[0] ||
55
66
  !isString(data.args[0]) ||
56
- isLocked(SQL_INJECTION)
67
+ isLocked(ruleId)
57
68
  ) return;
58
69
 
59
70
  const strInfo = tracker.getData(data.args[0]);
@@ -86,7 +97,7 @@ module.exports = function(core) {
86
97
 
87
98
  if (event) {
88
99
  reportFindings({
89
- ruleId: SQL_INJECTION,
100
+ ruleId,
90
101
  sinkEvent: event,
91
102
  });
92
103
  }
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright: 2023 Contrast Security, Inc
2
+ * Copyright: 2024 Contrast Security, Inc
3
3
  * Contact: support@contrastsecurity.com
4
4
  * License: Commercial
5
5
 
@@ -17,8 +17,7 @@
17
17
 
18
18
  const { patchType } = require('../common');
19
19
  const {
20
- Rule: { SQL_INJECTION },
21
- isString,
20
+ Rule: { SQL_INJECTION: ruleId },
22
21
  DataflowTag: {
23
22
  CUSTOM_ENCODED_SQL_INJECTION,
24
23
  CUSTOM_ENCODED,
@@ -28,8 +27,10 @@ const {
28
27
  LIMITED_CHARS,
29
28
  UNTRUSTED
30
29
  },
31
- inspect
30
+ isString,
31
+ inspect,
32
32
  } = require('@contrast/common');
33
+ const { InstrumentationType: { RULE } } = require('../../../constants');
33
34
 
34
35
  const safeTags = [
35
36
  CUSTOM_ENCODED_SQL_INJECTION,
@@ -40,12 +41,19 @@ const safeTags = [
40
41
  LIMITED_CHARS,
41
42
  ];
42
43
 
44
+ /**
45
+ * @param {{
46
+ * assess: import('@contrast/assess').Assess,
47
+ * config: import('@contrast/config').Config,
48
+ * }} core
49
+ * @returns {import('@contrast/common').Installable}
50
+ */
43
51
  module.exports = function(core) {
44
52
  const {
45
53
  depHooks,
46
54
  patcher,
47
- scopes: { sources },
48
55
  assess: {
56
+ getSourceContext,
49
57
  eventFactory: { createSinkEvent },
50
58
  dataflow: {
51
59
  tracker,
@@ -65,11 +73,10 @@ module.exports = function(core) {
65
73
  }
66
74
 
67
75
  const pre = (module, file, obj, method) => (data) => {
68
- const store = sources.getStore()?.assess;
69
76
  if (
70
- !store ||
77
+ !getSourceContext(RULE, ruleId) ||
71
78
  !data.args[0] ||
72
- isLocked(SQL_INJECTION)
79
+ isLocked(ruleId)
73
80
  ) return;
74
81
 
75
82
  const val = getValueFromArgs(data.args);
@@ -106,7 +113,7 @@ module.exports = function(core) {
106
113
 
107
114
  if (event) {
108
115
  reportFindings({
109
- ruleId: SQL_INJECTION,
116
+ ruleId,
110
117
  sinkEvent: event,
111
118
  });
112
119
  }
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright: 2023 Contrast Security, Inc
2
+ * Copyright: 2024 Contrast Security, Inc
3
3
  * Contact: support@contrastsecurity.com
4
4
  * License: Commercial
5
5
 
@@ -15,21 +15,29 @@
15
15
 
16
16
  'use strict';
17
17
 
18
- const { patchType } = require('../common');
19
18
  const {
20
- Rule: { UNTRUSTED_DESERIALIZATION },
19
+ Rule: { UNTRUSTED_DESERIALIZATION: ruleId },
21
20
  isString,
22
21
  DataflowTag: {
23
22
  UNTRUSTED
24
23
  }
25
24
  } = require('@contrast/common');
25
+ const { InstrumentationType: { RULE } } = require('../../../constants');
26
+ const { patchType } = require('../common');
26
27
 
28
+ /**
29
+ * @param {{
30
+ * assess: import('@contrast/assess').Assess,
31
+ * config: import('@contrast/config').Config,
32
+ * }} core
33
+ * @returns {import('@contrast/common').Installable}
34
+ */
27
35
  module.exports = function(core) {
28
36
  const {
29
37
  depHooks,
30
38
  patcher,
31
- scopes: { sources, instrumentation },
32
39
  assess: {
40
+ getSourceContext,
33
41
  eventFactory: { createSinkEvent },
34
42
  dataflow: {
35
43
  tracker,
@@ -45,23 +53,13 @@ module.exports = function(core) {
45
53
  name: 'node-serialize.unserialize',
46
54
  patchType,
47
55
  pre(data) {
48
- const store = sources.getStore()?.assess;
49
- if (
50
- !store ||
51
- !data.args[0] ||
52
- instrumentation.isLocked()
53
- ) return;
56
+ if (!getSourceContext(RULE, ruleId) || !data.args[0]) return;
54
57
 
55
58
  const [input] = data.args;
56
-
57
- if (!isString(input)) {
58
- return;
59
- }
59
+ if (!isString(input)) return;
60
60
 
61
61
  const strInfo = tracker.getData(input);
62
- if (!strInfo || !isVulnerable(UNTRUSTED, [], strInfo.tags)) {
63
- return;
64
- }
62
+ if (!strInfo || !isVulnerable(UNTRUSTED, [], strInfo.tags)) return;
65
63
 
66
64
  const sinkEvent = createSinkEvent({
67
65
  name: 'node-serialize.unserialize',
@@ -89,7 +87,7 @@ module.exports = function(core) {
89
87
 
90
88
  if (sinkEvent) {
91
89
  reportFindings({
92
- ruleId: UNTRUSTED_DESERIALIZATION,
90
+ ruleId,
93
91
  sinkEvent,
94
92
  });
95
93
  }
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright: 2023 Contrast Security, Inc
2
+ * Copyright: 2024 Contrast Security, Inc
3
3
  * Contact: support@contrastsecurity.com
4
4
  * License: Commercial
5
5
 
@@ -17,19 +17,33 @@
17
17
 
18
18
  const util = require('util');
19
19
  const {
20
- DataflowTag: { UNTRUSTED, SQL_ENCODED, LIMITED_CHARS, CUSTOM_VALIDATED, CUSTOM_ENCODED },
20
+ DataflowTag: {
21
+ CUSTOM_VALIDATED,
22
+ CUSTOM_ENCODED,
23
+ LIMITED_CHARS,
24
+ SQL_ENCODED,
25
+ UNTRUSTED,
26
+ },
21
27
  Rule: { SQL_INJECTION: ruleId },
22
28
  isString,
23
29
  } = require('@contrast/common');
30
+ const { InstrumentationType: { RULE } } = require('../../../constants');
24
31
  const { filterSafeTags, patchType } = require('../common');
25
32
 
33
+ /**
34
+ * @param {{
35
+ * assess: import('@contrast/assess').Assess,
36
+ * config: import('@contrast/config').Config,
37
+ * }} core
38
+ * @returns {import('@contrast/common').Installable}
39
+ */
26
40
  module.exports = function(core) {
27
41
  const {
28
42
  config,
29
43
  depHooks,
30
44
  patcher,
31
- scopes: { sources },
32
45
  assess: {
46
+ getSourceContext,
33
47
  eventFactory: { createSinkEvent },
34
48
  dataflow: {
35
49
  tracker,
@@ -50,8 +64,7 @@ module.exports = function(core) {
50
64
  const postgres = core.assess.dataflow.sinks.postgres = {};
51
65
 
52
66
  const preHook = (methodSignature) => (data) => {
53
- const assessStore = sources.getStore()?.assess;
54
- if (!assessStore || isLocked(ruleId)) return;
67
+ if (!getSourceContext(RULE, ruleId) || isLocked(ruleId)) return;
55
68
 
56
69
  const [arg0] = data.args;
57
70
  const query = arg0?.text || arg0;
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright: 2023 Contrast Security, Inc
2
+ * Copyright: 2024 Contrast Security, Inc
3
3
  * Contact: support@contrastsecurity.com
4
4
  * License: Commercial
5
5
 
@@ -17,7 +17,7 @@
17
17
 
18
18
  const util = require('util');
19
19
  const {
20
- Rule: { SQL_INJECTION },
20
+ Rule: { SQL_INJECTION: ruleId },
21
21
  DataflowTag: {
22
22
  UNTRUSTED,
23
23
  SQL_ENCODED,
@@ -26,15 +26,23 @@ const {
26
26
  CUSTOM_ENCODED,
27
27
  },
28
28
  } = require('@contrast/common');
29
+ const { InstrumentationType: { RULE } } = require('../../../constants');
29
30
  const { patchType, filterSafeTags } = require('../common');
30
31
 
31
- module.exports = function(core) {
32
+ /**
33
+ * @param {{
34
+ * assess: import('@contrast/assess').Assess,
35
+ * config: import('@contrast/config').Config,
36
+ * }} core
37
+ * @returns {import('@contrast/common').Installable}
38
+ */
39
+ module.exports = function (core) {
32
40
  const {
33
41
  depHooks,
34
42
  patcher,
35
43
  config,
36
- scopes: { sources },
37
44
  assess: {
45
+ getSourceContext,
38
46
  eventFactory: { createSinkEvent },
39
47
  dataflow: {
40
48
  tracker,
@@ -54,17 +62,15 @@ module.exports = function(core) {
54
62
 
55
63
  const sequelize = (core.assess.dataflow.sinks.sequelize = {});
56
64
 
57
- sequelize.install = function() {
58
- const sequelizeQueryPatchName = 'sequelize.prototype.query';
65
+ sequelize.install = function () {
59
66
  depHooks.resolve({ name: 'sequelize' }, (sequelize) => {
60
67
  patcher.patch(sequelize.prototype, 'query', {
61
- name: sequelizeQueryPatchName,
68
+ name: 'sequelize.prototype.query',
62
69
  patchType,
63
70
  around(next, data) {
64
- const { args, hooked, orig } = data;
65
- const sourceContext = sources.getStore()?.assess;
66
- if (!sourceContext || !args[0]) return next();
71
+ if (!getSourceContext(RULE, ruleId) || !data.args[0]) return next();
67
72
 
73
+ const { args, hooked, orig } = data;
68
74
  const query = typeof args[0] === 'string' ? args[0] : args[0].query;
69
75
 
70
76
  try {
@@ -73,8 +79,8 @@ module.exports = function(core) {
73
79
 
74
80
  if (queryInfo && !isVulnerableQuery && config.assess.safe_positives.enable) {
75
81
  reportSafePositive({
76
- name: sequelizeQueryPatchName,
77
- ruleId: SQL_INJECTION,
82
+ name: data.name,
83
+ ruleId,
78
84
  safeTags: filterSafeTags(safeTags, queryInfo),
79
85
  strInfo: {
80
86
  value: queryInfo?.value,
@@ -87,7 +93,7 @@ module.exports = function(core) {
87
93
  !queryInfo ||
88
94
  !isVulnerableQuery
89
95
  ) {
90
- return runInActiveSink(SQL_INJECTION, async () => await next());
96
+ return runInActiveSink(ruleId, async () => await next());
91
97
  }
92
98
 
93
99
  const sqlValue =
@@ -103,7 +109,7 @@ module.exports = function(core) {
103
109
 
104
110
  const event = createSinkEvent({
105
111
  context: `sequelize.prototype.query(${contextArgs})`,
106
- name: sequelizeQueryPatchName,
112
+ name: data.name,
107
113
  moduleName: 'sequelize',
108
114
  methodName: 'prototype.query',
109
115
  history: [queryInfo],
@@ -122,19 +128,19 @@ module.exports = function(core) {
122
128
 
123
129
  if (event) {
124
130
  reportFindings({
125
- ruleId: SQL_INJECTION,
131
+ ruleId,
126
132
  sinkEvent: event,
127
133
  });
128
134
  }
129
135
  /* c8 ignore next 3 */
130
136
  } catch (err) {
131
137
  core.logger.error(
132
- { name: sequelizeQueryPatchName, err },
138
+ { err, funcKey: data.funcKey },
133
139
  'assess sink analysis failed'
134
140
  );
135
141
  }
136
142
 
137
- return runInActiveSink(SQL_INJECTION, async () => await next());
143
+ return runInActiveSink(ruleId, async () => await next());
138
144
  },
139
145
  });
140
146
  });