@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
 
@@ -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,25 @@
17
17
  const {
18
18
  DataflowTag: { UNTRUSTED },
19
19
  join,
20
- Rule,
20
+ Rule: { CMD_INJECTION: ruleId },
21
21
  isString,
22
22
  inspect,
23
23
  } = require('@contrast/common');
24
-
24
+ const { InstrumentationType: { RULE } } = require('../../../constants');
25
25
  const { patchType } = require('../common');
26
26
 
27
+ /**
28
+ * @param {{
29
+ * assess: import('@contrast/assess').Assess,
30
+ * }} core
31
+ * @returns {import('@contrast/common').Installable}
32
+ */
27
33
  module.exports = function(core) {
28
34
  const {
29
35
  depHooks,
30
36
  patcher,
31
- scopes: { sources },
32
37
  assess: {
38
+ getSourceContext,
33
39
  eventFactory: { createSinkEvent },
34
40
  dataflow: {
35
41
  tracker,
@@ -92,7 +98,7 @@ module.exports = function(core) {
92
98
 
93
99
  if (event) {
94
100
  reportFindings({
95
- ruleId: Rule.CMD_INJECTION,
101
+ ruleId,
96
102
  sinkEvent: event,
97
103
  });
98
104
 
@@ -178,7 +184,7 @@ module.exports = function(core) {
178
184
 
179
185
  if (event) {
180
186
  reportFindings({
181
- ruleId: Rule.CMD_INJECTION,
187
+ ruleId,
182
188
  sinkEvent: event,
183
189
  });
184
190
  }
@@ -193,10 +199,10 @@ module.exports = function(core) {
193
199
  name,
194
200
  patchType,
195
201
  pre(data) {
196
- const store = sources.getStore()?.assess;
197
- const [command] = data.args;
202
+ if (!getSourceContext(RULE, ruleId)) return;
198
203
 
199
- if (!store || !command || !isString(command)) return;
204
+ const [command] = data.args;
205
+ if (!command || !isString(command)) return;
200
206
 
201
207
  const cpArgs = Array.isArray(data.args[1]) && data.args[1];
202
208
  const options = cpArgs ? data.args[2] : data.args[1];
@@ -233,10 +239,10 @@ module.exports = function(core) {
233
239
  name,
234
240
  patchType,
235
241
  pre(data) {
236
- const store = sources.getStore()?.assess;
237
- const [command, secondArg, thirdArg] = data.args;
242
+ if (!getSourceContext(RULE, ruleId)) return;
238
243
 
239
- if (!store || !command || !isString(command)) return;
244
+ const [command, secondArg, thirdArg] = data.args;
245
+ if (!command || !isString(command)) return;
240
246
 
241
247
  commandCheck(
242
248
  name,
@@ -257,10 +263,10 @@ module.exports = function(core) {
257
263
  name,
258
264
  patchType,
259
265
  pre(data) {
260
- const store = sources.getStore()?.assess;
261
- const [command] = data.args;
266
+ if (!getSourceContext(RULE, ruleId)) return;
262
267
 
263
- if (!store || !command || !isString(command)) return;
268
+ const [command] = data.args;
269
+ if (!command || !isString(command)) return;
264
270
 
265
271
  const cpArgs = Array.isArray(data.args[1]) && data.args[1];
266
272
  const options = cpArgs ? data.args[2] : data.args[1];
@@ -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
 
@@ -25,8 +25,9 @@ const {
25
25
  CUSTOM_VALIDATED,
26
26
  LIMITED_CHARS,
27
27
  },
28
- Rule: { UNSAFE_CODE_EXECUTION },
28
+ Rule: { UNSAFE_CODE_EXECUTION: ruleId },
29
29
  } = require('@contrast/common');
30
+ const { InstrumentationType: { RULE } } = require('../../../constants');
30
31
  const { patchType, filterSafeTags } = require('../common');
31
32
 
32
33
  const safeTags = [
@@ -37,13 +38,21 @@ const safeTags = [
37
38
  LIMITED_CHARS,
38
39
  ];
39
40
 
41
+ /**
42
+ * @param {{
43
+ * assess: import('@contrast/assess').Assess,
44
+ * config: import('@contrast/config').Config,
45
+ * logger: import('@contrast/logger').Logger,
46
+ * }} core
47
+ * @returns {import('@contrast/common').Installable}
48
+ */
40
49
  module.exports = function (core) {
41
50
  const {
42
51
  config,
43
52
  logger,
44
53
  patcher,
45
- scopes: { sources, instrumentation },
46
54
  assess: {
55
+ getSourceContext,
47
56
  eventFactory: { createSinkEvent },
48
57
  dataflow: {
49
58
  tracker,
@@ -63,19 +72,12 @@ module.exports = function (core) {
63
72
  name: 'global.ContrastMethods.eval',
64
73
  patchType,
65
74
  pre({ args, orig }) {
66
- const store = sources.getStore()?.assess;
75
+ if (!getSourceContext(RULE, ruleId)) return;
76
+
67
77
  const script = args[0];
68
- if (
69
- !store ||
70
- instrumentation.isLocked() ||
71
- !script ||
72
- !isString(script)
73
- ) {
74
- return;
75
- }
78
+ if (!script || !isString(script)) return;
76
79
 
77
80
  const strInfo = tracker.getData(script);
78
-
79
81
  if (!strInfo) return;
80
82
 
81
83
  const isArgVulnerable = isVulnerable(
@@ -93,7 +95,7 @@ module.exports = function (core) {
93
95
 
94
96
  reportSafePositive({
95
97
  name: 'eval',
96
- ruleId: UNSAFE_CODE_EXECUTION,
98
+ ruleId,
97
99
  safeTags: foundSafeTags,
98
100
  strInfo: safeStrInfo,
99
101
  });
@@ -120,7 +122,7 @@ module.exports = function (core) {
120
122
 
121
123
  if (event) {
122
124
  reportFindings({
123
- ruleId: UNSAFE_CODE_EXECUTION,
125
+ ruleId,
124
126
  sinkEvent: event,
125
127
  });
126
128
  }
@@ -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
 
@@ -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,6 +17,7 @@
17
17
 
18
18
  const util = require('util');
19
19
  const {
20
+ Rule: { UNVALIDATED_REDIRECT: ruleId },
20
21
  DataflowTag: {
21
22
  UNTRUSTED,
22
23
  CUSTOM_ENCODED,
@@ -27,18 +28,25 @@ const {
27
28
  },
28
29
  isString
29
30
  } = require('@contrast/common');
30
- const { patchType, filterSafeTags } = require('../../common');
31
+ const { InstrumentationType: { RULE } } = require('../../../../constants');
31
32
  const { createSubsetTags } = require('../../../tag-utils');
33
+ const { patchType, filterSafeTags } = require('../../common');
32
34
 
33
- const ruleId = 'unvalidated-redirect';
34
-
35
+ /**
36
+ * @param {{
37
+ * assess: import('@contrast/assess').Assess,
38
+ * config: import('@contrast/config').Config,
39
+ * logger: import('@contrast/logger').Logger,
40
+ * }} core
41
+ * @returns {import('@contrast/common').Installable}
42
+ */
35
43
  module.exports = function(core) {
36
44
  const {
37
45
  depHooks,
38
46
  patcher,
39
47
  config,
40
- scopes: { sources },
41
48
  assess: {
49
+ getSourceContext,
42
50
  eventFactory: { createSinkEvent },
43
51
  dataflow: {
44
52
  tracker,
@@ -46,9 +54,8 @@ module.exports = function(core) {
46
54
  },
47
55
  },
48
56
  } = core;
49
- const unvalidatedRedirect =
50
- (core.assess.dataflow.sinks.express.unvalidatedRedirect = {});
51
57
 
58
+ const unvalidatedRedirect = core.assess.dataflow.sinks.express.unvalidatedRedirect = {};
52
59
  const inspect = patcher.unwrap(util.inspect);
53
60
 
54
61
  const safeTags = [
@@ -66,8 +73,7 @@ module.exports = function(core) {
66
73
  name: 'Express.Response.location',
67
74
  patchType,
68
75
  pre: (data) => {
69
- const assessStore = sources.getStore()?.assess;
70
- if (!assessStore) return;
76
+ if (!getSourceContext(RULE, ruleId)) return;
71
77
 
72
78
  let [url] = data.args;
73
79
  if (url === 'back') {
@@ -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
 
@@ -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,6 +17,7 @@
17
17
 
18
18
  const util = require('util');
19
19
  const {
20
+ Rule: { UNVALIDATED_REDIRECT: ruleId },
20
21
  DataflowTag: {
21
22
  UNTRUSTED,
22
23
  CUSTOM_ENCODED,
@@ -27,11 +28,10 @@ const {
27
28
  },
28
29
  isString
29
30
  } = require('@contrast/common');
31
+ const { InstrumentationType: { RULE } } = require('../../../../constants');
30
32
  const { createSubsetTags } = require('../../../tag-utils');
31
33
  const { filterSafeTags, patchType } = require('../../common');
32
34
 
33
- const ruleId = 'unvalidated-redirect';
34
-
35
35
  const getURLArgument = (args) => {
36
36
  if (!Array.isArray(args)) {
37
37
  return { index: null, url: undefined };
@@ -51,13 +51,21 @@ const getURLArgument = (args) => {
51
51
  };
52
52
  };
53
53
 
54
+ /**
55
+ *
56
+ * @param {{
57
+ * assess: import('@contrast/assess').Assess,
58
+ * config: import('@contrast/config').Config,
59
+ * }} core
60
+ * @returns {import('@contrast/common').Installable}
61
+ */
54
62
  module.exports = function(core) {
55
63
  const {
56
64
  config,
57
65
  depHooks,
58
66
  patcher,
59
- scopes: { sources },
60
67
  assess: {
68
+ getSourceContext,
61
69
  eventFactory: { createSinkEvent },
62
70
  dataflow: {
63
71
  tracker,
@@ -85,8 +93,7 @@ module.exports = function(core) {
85
93
  name,
86
94
  patchType,
87
95
  post(data) {
88
- const assessStore = sources.getStore()?.assess;
89
- if (!assessStore) return;
96
+ if (!getSourceContext(RULE, ruleId)) return;
90
97
 
91
98
  const { url, index: valueIndex } = getURLArgument(data.args);
92
99
  if (!url || !isString(url)) return;
@@ -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,9 +16,6 @@
16
16
  'use strict';
17
17
  const { patchType } = require('../common');
18
18
  const {
19
- FS_METHODS,
20
- Rule,
21
- isString,
22
19
  DataflowTag: {
23
20
  URL_ENCODED,
24
21
  LIMITED_CHARS,
@@ -26,16 +23,20 @@ const {
26
23
  SAFE_PATH,
27
24
  UNTRUSTED,
28
25
  },
26
+ FS_METHODS,
27
+ Rule: { PATH_TRAVERSAL: ruleId },
29
28
  inspect,
29
+ isString,
30
30
  join,
31
31
  } = require('@contrast/common');
32
+ const { InstrumentationType: { RULE } } = require('../../../constants');
32
33
 
33
34
  module.exports = function(core) {
34
35
  const {
35
36
  depHooks,
36
37
  patcher,
37
- scopes: { instrumentation, sources },
38
38
  assess: {
39
+ getSourceContext,
39
40
  eventFactory: { createSinkEvent },
40
41
  dataflow: {
41
42
  tracker,
@@ -61,8 +62,7 @@ module.exports = function(core) {
61
62
 
62
63
  const pre = (name, method, moduleName = 'fs', fullMethodName = '') => (data) => {
63
64
  const { name: methodName, indices } = method;
64
- const store = sources.getStore()?.assess;
65
- if (!store || instrumentation.isLocked()) return;
65
+ if (!getSourceContext(RULE, ruleId)) return;
66
66
 
67
67
  const values = getValues(indices, data.args);
68
68
  if (!values.length) return;
@@ -105,7 +105,7 @@ module.exports = function(core) {
105
105
 
106
106
  if (event) {
107
107
  reportFindings({
108
- ruleId: Rule.PATH_TRAVERSAL,
108
+ ruleId,
109
109
  sinkEvent: event,
110
110
  });
111
111
  }
@@ -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
 
@@ -27,8 +27,9 @@ const {
27
27
  CUSTOM_VALIDATED,
28
28
  LIMITED_CHARS,
29
29
  },
30
- Rule: { UNSAFE_CODE_EXECUTION }
30
+ Rule: { UNSAFE_CODE_EXECUTION: ruleId }
31
31
  } = require('@contrast/common');
32
+ const { InstrumentationType: { RULE } } = require('../../../constants');
32
33
  const { patchType, filterSafeTags } = require('../common');
33
34
 
34
35
  const safeTags = [
@@ -44,8 +45,8 @@ module.exports = function (core) {
44
45
  config,
45
46
  logger,
46
47
  patcher,
47
- scopes: { sources, instrumentation },
48
48
  assess: {
49
+ getSourceContext,
49
50
  eventFactory: { createSinkEvent },
50
51
  dataflow: {
51
52
  tracker,
@@ -65,15 +66,10 @@ module.exports = function (core) {
65
66
  name: 'global.ContrastMethods.Function',
66
67
  patchType,
67
68
  pre({ args: origArgs, hooked, orig, name }) {
68
- const store = sources.getStore()?.assess;
69
+ if (!getSourceContext(RULE, ruleId)) return;
70
+
69
71
  const fnBody = origArgs[origArgs.length - 1];
70
- if (
71
- !store ||
72
- instrumentation.isLocked() ||
73
- !fnBody ||
74
- !isString(fnBody)
75
- )
76
- return;
72
+ if (!fnBody || !isString(fnBody)) return;
77
73
 
78
74
  const strInfo = tracker.getData(fnBody);
79
75
 
@@ -90,7 +86,7 @@ module.exports = function (core) {
90
86
 
91
87
  reportSafePositive({
92
88
  name,
93
- ruleId: UNSAFE_CODE_EXECUTION,
89
+ ruleId,
94
90
  safeTags: foundSafeTags,
95
91
  strInfo: safeStrInfo,
96
92
  });
@@ -142,7 +138,7 @@ module.exports = function (core) {
142
138
 
143
139
  if (event) {
144
140
  reportFindings({
145
- ruleId: UNSAFE_CODE_EXECUTION,
141
+ ruleId,
146
142
  sinkEvent: event,
147
143
  });
148
144
  }
@@ -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
 
@@ -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,6 +15,7 @@
15
15
 
16
16
  'use strict';
17
17
 
18
+ const Url = require('url');
18
19
  const {
19
20
  inspect,
20
21
  isString,
@@ -25,19 +26,27 @@ const {
25
26
  CUSTOM_VALIDATED_SSRF,
26
27
  CUSTOM_VALIDATED,
27
28
  LIMITED_CHARS
28
- }
29
+ },
30
+ Rule: { SSRF: ruleId },
29
31
  } = require('@contrast/common');
30
- const Url = require('url');
31
- const trustedLibs = [/^(?!.*(newrelic)).*http.*$/];
32
- const { patchType } = require('../../common');
32
+ const { InstrumentationType: { RULE } } = require('../../../../constants');
33
33
  const { createAppendTags } = require('../../../tag-utils');
34
+ const { patchType } = require('../../common');
35
+
36
+ const trustedLibs = [/^(?!.*(newrelic)).*http.*$/];
34
37
 
38
+ /**
39
+ * @param {{
40
+ * assess: import('@contrast/assess').Assess,
41
+ * }} core
42
+ * @returns {import('@contrast/common').Installable}
43
+ */
35
44
  module.exports = function(core) {
36
45
  const {
37
46
  depHooks,
38
47
  patcher,
39
- scopes: { sources },
40
48
  assess: {
49
+ getSourceContext,
41
50
  eventFactory: { createSinkEvent },
42
51
  dataflow: {
43
52
  tracker,
@@ -92,8 +101,7 @@ module.exports = function(core) {
92
101
  name,
93
102
  patchType,
94
103
  pre(data) {
95
- const sourceContext = sources.getStore()?.assess;
96
- if (!sourceContext) return;
104
+ if (!getSourceContext(RULE, ruleId)) return;
97
105
 
98
106
  const [req] = data.args;
99
107
  if (!req) return;
@@ -136,7 +144,7 @@ module.exports = function(core) {
136
144
 
137
145
  if (event) {
138
146
  reportFindings({
139
- ruleId: 'ssrf',
147
+ ruleId,
140
148
  sinkEvent: event
141
149
  });
142
150
  }
@@ -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
 
@@ -31,15 +31,24 @@ const {
31
31
  },
32
32
  Rule: { REFLECTED_XSS: ruleId },
33
33
  } = require('@contrast/common');
34
+ const { InstrumentationType: { RULE } } = require('../../../../constants');
35
+
34
36
  const { patchType, filterSafeTags } = require('../../common');
35
37
 
38
+ /**
39
+ * @param {{
40
+ * assess: import('@contrast/assess').Assess,
41
+ * config: import('@contrast/config').Config,
42
+ * }} core
43
+ * @returns {import('@contrast/common').Installable}
44
+ */
36
45
  module.exports = function(core) {
37
46
  const {
38
47
  config,
39
48
  depHooks,
40
49
  patcher,
41
- scopes: { sources },
42
50
  assess: {
51
+ getSourceContext,
43
52
  eventFactory: { createSinkEvent },
44
53
  dataflow: {
45
54
  tracker,
@@ -68,7 +77,7 @@ module.exports = function(core) {
68
77
  ];
69
78
 
70
79
  const preHook = (name, method) => (data) => {
71
- const sourceContext = sources.getStore()?.assess;
80
+ const sourceContext = getSourceContext(RULE, ruleId);
72
81
  if (!sourceContext) return;
73
82
 
74
83
  const payload = data.args[0];
@@ -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
 
@@ -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
 
@@ -25,20 +25,29 @@ const {
25
25
  LIMITED_CHARS,
26
26
  URL_ENCODED,
27
27
  },
28
+ Rule: { UNVALIDATED_REDIRECT: ruleId },
28
29
  isString
29
30
  } = require('@contrast/common');
31
+ const { InstrumentationType: { RULE } } = require('../../../../constants');
30
32
  const { createSubsetTags } = require('../../../tag-utils');
31
33
  const { filterSafeTags, patchType } = require('../../common');
32
34
 
33
- const ruleId = 'unvalidated-redirect';
34
-
35
+ /**
36
+ * @param {{
37
+ * assess: import('@contrast/assess').Assess,
38
+ * config: import('@contrast/config').Config,
39
+ * logger: import('@contrast/logger').Logger,
40
+ * messages: import('@contrast/common').Messages,
41
+ * }} core
42
+ * @returns {import('@contrast/common').Installable}
43
+ */
35
44
  module.exports = function(core) {
36
45
  const {
37
46
  depHooks,
38
47
  patcher,
39
48
  config,
40
- scopes: { sources },
41
49
  assess: {
50
+ getSourceContext,
42
51
  eventFactory: { createSinkEvent },
43
52
  dataflow: {
44
53
  tracker,
@@ -46,11 +55,8 @@ module.exports = function(core) {
46
55
  },
47
56
  },
48
57
  } = core;
49
- const unvalidatedRedirect =
50
- (core.assess.dataflow.sinks.koa.unvalidatedRedirect = {});
51
58
 
52
59
  const inspect = patcher.unwrap(util.inspect);
53
-
54
60
  const safeTags = [
55
61
  CUSTOM_ENCODED,
56
62
  CUSTOM_VALIDATED,
@@ -59,6 +65,8 @@ module.exports = function(core) {
59
65
  URL_ENCODED,
60
66
  ];
61
67
 
68
+ const unvalidatedRedirect = core.assess.dataflow.sinks.koa.unvalidatedRedirect = {};
69
+
62
70
  unvalidatedRedirect.install = function() {
63
71
  depHooks.resolve({ name: 'koa', file: 'lib/response', version: '<2.9.0' }, (Response) => {
64
72
  const name = 'Koa.Response.redirect';
@@ -66,8 +74,7 @@ module.exports = function(core) {
66
74
  name,
67
75
  patchType,
68
76
  pre(data) {
69
- const assessStore = sources.getStore()?.assess;
70
- if (!assessStore) return;
77
+ if (!getSourceContext(RULE, ruleId)) return;
71
78
 
72
79
  let isBackRoute = false;
73
80
  let [url] = data.args;