@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
 
@@ -17,10 +17,17 @@
17
17
 
18
18
  const { patchType } = require('../common');
19
19
  const {
20
- DataflowTag: { UNTRUSTED, SQL_ENCODED, LIMITED_CHARS, CUSTOM_VALIDATED, CUSTOM_ENCODED },
21
- Rule: { SQL_INJECTION },
20
+ DataflowTag: {
21
+ CUSTOM_VALIDATED,
22
+ CUSTOM_ENCODED,
23
+ LIMITED_CHARS,
24
+ SQL_ENCODED,
25
+ UNTRUSTED,
26
+ },
27
+ Rule: { SQL_INJECTION: ruleId },
22
28
  isString
23
29
  } = require('@contrast/common');
30
+ const { InstrumentationType: { RULE } } = require('../../../constants');
24
31
 
25
32
  const safeTags = [
26
33
  SQL_ENCODED,
@@ -29,12 +36,19 @@ const safeTags = [
29
36
  CUSTOM_ENCODED,
30
37
  ];
31
38
 
39
+ /**
40
+ * @param {{
41
+ * assess: import('@contrast/assess').Assess,
42
+ * config: import('@contrast/config').Config,
43
+ * }} core
44
+ * @returns {import('@contrast/common').Installable}
45
+ */
32
46
  module.exports = function(core) {
33
47
  const {
34
48
  depHooks,
35
49
  patcher,
36
- scopes: { sources },
37
50
  assess: {
51
+ getSourceContext,
38
52
  eventFactory: { createSinkEvent },
39
53
  dataflow: {
40
54
  tracker,
@@ -44,12 +58,11 @@ module.exports = function(core) {
44
58
  } = core;
45
59
 
46
60
  const pre = (name, method) => (data) => {
47
- const store = sources.getStore()?.assess;
48
61
  if (
49
- !store ||
62
+ !getSourceContext(RULE, ruleId) ||
50
63
  !data.args[0] ||
51
64
  !isString(data.args[0]) ||
52
- isLocked(SQL_INJECTION)
65
+ isLocked(ruleId)
53
66
  ) return;
54
67
 
55
68
  const strInfo = tracker.getData(data.args[0]);
@@ -83,7 +96,7 @@ module.exports = function(core) {
83
96
 
84
97
  if (event) {
85
98
  reportFindings({
86
- ruleId: SQL_INJECTION,
99
+ ruleId,
87
100
  sinkEvent: event,
88
101
  });
89
102
  }
@@ -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,7 +16,6 @@
16
16
  'use strict';
17
17
  const { patchType, filterSafeTags } = require('../common');
18
18
  const {
19
- isString,
20
19
  DataflowTag: {
21
20
  UNTRUSTED,
22
21
  CUSTOM_ENCODED_TRUST_BOUNDARY_VIOLATION,
@@ -25,14 +24,17 @@ const {
25
24
  CUSTOM_VALIDATED,
26
25
  LIMITED_CHARS,
27
26
  },
28
- Rule: { UNSAFE_CODE_EXECUTION },
29
- isNonEmptyObject,
27
+ Rule: { UNSAFE_CODE_EXECUTION: ruleId },
30
28
  inspect,
31
- traverseValues,
29
+ isNonEmptyObject,
30
+ isString,
32
31
  join,
33
32
  split,
33
+ traverseValues,
34
34
  } = require('@contrast/common');
35
+ const { InstrumentationType: { RULE } } = require('../../../constants');
35
36
  const { createAdjustedQueryTags } = require('../../tag-utils');
37
+
36
38
  const safeTags = [
37
39
  CUSTOM_ENCODED_TRUST_BOUNDARY_VIOLATION,
38
40
  CUSTOM_ENCODED,
@@ -41,13 +43,20 @@ const safeTags = [
41
43
  LIMITED_CHARS,
42
44
  ];
43
45
 
46
+ /**
47
+ * @param {{
48
+ * assess: import('@contrast/assess').Assess,
49
+ * config: import('@contrast/config').Config,
50
+ * }} core
51
+ * @returns {import('@contrast/common').Installable}
52
+ */
44
53
  module.exports = function (core) {
45
54
  const {
46
55
  config,
47
56
  depHooks,
48
57
  patcher,
49
- scopes: { sources, instrumentation },
50
58
  assess: {
59
+ getSourceContext,
51
60
  eventFactory: { createSinkEvent },
52
61
  dataflow: {
53
62
  tracker,
@@ -133,14 +142,7 @@ module.exports = function (core) {
133
142
  }
134
143
 
135
144
  function around(next, { args: origArgs, hooked, orig, name }) {
136
- const store = sources.getStore()?.assess;
137
- if (
138
- !store ||
139
- instrumentation.isLocked() ||
140
- isLocked(UNSAFE_CODE_EXECUTION)
141
- ) {
142
- return next();
143
- }
145
+ if (!getSourceContext(RULE, ruleId) || isLocked(ruleId)) return next();
144
146
 
145
147
  const methodPath = split(name, '.');
146
148
  const method = methodPath[methodPath.length - 1];
@@ -189,13 +191,13 @@ module.exports = function (core) {
189
191
 
190
192
  reportSafePositive({
191
193
  name,
192
- ruleId: UNSAFE_CODE_EXECUTION,
194
+ ruleId,
193
195
  safeTags: Array.from(foundSafeTags),
194
196
  strInfo,
195
197
  });
196
198
 
197
199
  return name === 'vm.runInNewContext'
198
- ? runInActiveSink(UNSAFE_CODE_EXECUTION, () => next())
200
+ ? runInActiveSink(ruleId, () => next())
199
201
  : next();
200
202
  }
201
203
 
@@ -233,14 +235,14 @@ module.exports = function (core) {
233
235
 
234
236
  if (event) {
235
237
  reportFindings({
236
- ruleId: UNSAFE_CODE_EXECUTION,
238
+ ruleId,
237
239
  sinkEvent: event,
238
240
  });
239
241
  }
240
242
  }
241
243
 
242
244
  return name === 'vm.runInNewContext'
243
- ? runInActiveSink(UNSAFE_CODE_EXECUTION, () => next())
245
+ ? runInActiveSink(ruleId, () => next())
244
246
  : next();
245
247
  }
246
248
 
@@ -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
 
@@ -22,7 +22,7 @@ const {
22
22
  join,
23
23
  } = require('@contrast/common');
24
24
 
25
- module.exports = function(core) {
25
+ module.exports = function (core) {
26
26
  const {
27
27
  assess: {
28
28
  eventFactory,
@@ -33,9 +33,10 @@ module.exports = function(core) {
33
33
  },
34
34
  config,
35
35
  createSnapshot,
36
- logger,
37
36
  } = core;
38
37
 
38
+ const logger = core.logger.child({ name: 'contrast:sources' });
39
+
39
40
  const emptyStack = Object.freeze([]);
40
41
 
41
42
  sources.createTags = function createTags({ inputType, fieldName = '', value }) {
@@ -55,13 +56,13 @@ module.exports = function(core) {
55
56
  return tags;
56
57
  };
57
58
 
58
- sources.createStacktrace = function(stacktraceOpts) {
59
+ sources.createStacktrace = function (stacktraceOpts) {
59
60
  return config.assess.stacktraces === 'NONE'
60
61
  ? emptyStack
61
62
  : createSnapshot(stacktraceOpts)();
62
63
  };
63
64
 
64
- sources.handle = function({
65
+ sources.handle = function ({
65
66
  context,
66
67
  keys,
67
68
  name,
@@ -73,7 +74,7 @@ module.exports = function(core) {
73
74
  if (!data) return;
74
75
 
75
76
  if (!sourceContext) {
76
- core.logger.trace({ inputType, name }, 'skipping assess source handling - no request context');
77
+ logger.trace({ inputType, sourceName: name }, 'skipping assess source handling - no request context');
77
78
  return null;
78
79
  }
79
80
 
@@ -119,7 +120,7 @@ module.exports = function(core) {
119
120
  const pathName = join(path, '.');
120
121
 
121
122
  if (sourceContext.sourceEventsCount >= max) {
122
- core.logger.trace({ inputType, name }, 'exiting assess source handling - %s max events exceeded', max);
123
+ logger.trace({ inputType, sourceName: name }, 'exiting assess source handling - %s max events exceeded', max);
123
124
  return true;
124
125
  }
125
126
 
@@ -136,13 +137,13 @@ module.exports = function(core) {
136
137
 
137
138
  const event = createEvent({ pathName, value, fieldName });
138
139
  if (!event) {
139
- core.logger.warn({ inputType, name, pathName, value }, 'unable to create source event');
140
+ logger.warn({ inputType, sourceName: name, pathName, value }, 'unable to create source event');
140
141
  return;
141
142
  }
142
143
 
143
144
  const { extern } = tracker.track(value, event);
144
145
  if (extern) {
145
- logger.trace({ extern, fieldName, name, inputType }, 'tracked');
146
+ logger.trace({ extern, fieldName, sourceName: name, inputType }, 'tracked');
146
147
  obj[fieldName] = extern;
147
148
 
148
149
  sourceContext.sourceEventsCount++;
@@ -152,7 +153,7 @@ module.exports = function(core) {
152
153
  if (event) {
153
154
  tracker.track(value, event);
154
155
  } else {
155
- core.logger.warn({ inputType, name, pathName, value }, 'unable to create source event');
156
+ logger.warn({ inputType, sourceName: name, pathName, value }, 'unable to create source event');
156
157
  }
157
158
  }
158
159
  });
@@ -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
 
@@ -26,7 +26,7 @@ module.exports = function (core) {
26
26
  require('./install/fastify')(core);
27
27
  require('./install/koa')(core);
28
28
  require('./install/body-parser1')(core);
29
- require('./install/busboy1')(core);
29
+ require('./install/busboy')(core);
30
30
  require('./install/cookie-parser1')(core);
31
31
  require('./install/formidable1')(core);
32
32
  require('./install/http')(core);
@@ -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
 
@@ -29,23 +29,23 @@ const INPUT_TYPES = {
29
29
  module.exports = function init(core) {
30
30
  const { assess, depHooks, logger, patcher, scopes } = core;
31
31
 
32
- const createPreHook = (name) => (data) => {
32
+ const preHook = (data) => {
33
33
  const [req, , next] = data.args;
34
34
  data.args[2] = scopes.wrap(function contrastNext(...args) {
35
35
  const sourceContext = scopes.sources.getStore()?.assess;
36
36
 
37
37
  if (!sourceContext) {
38
- logger.error({ name }, 'unable to handle source. Missing `sourceContext`');
38
+ logger.error({ funcKey: data.funcKey }, 'unable to handle source. Missing `sourceContext`');
39
39
  return next(...args);
40
40
  }
41
41
 
42
42
  if (sourceContext.parsedBody) {
43
- logger.trace({ name }, 'values already tracked');
43
+ logger.trace({ funcKey: data.funcKey }, 'values already tracked');
44
44
  return next(...args);
45
45
  }
46
46
 
47
47
  // when using a specific parser, we know the input type.
48
- let inputType = INPUT_TYPES[name];
48
+ let inputType = INPUT_TYPES[data.name];
49
49
  // when using `bodyParser()`, determine input type by content type.
50
50
  if (!inputType) {
51
51
  inputType = req.headers?.['content-type']?.includes('json')
@@ -71,7 +71,7 @@ module.exports = function init(core) {
71
71
  assess.dataflow.sources.handle({
72
72
  context,
73
73
  data: _data,
74
- name,
74
+ name: data.name,
75
75
  keys,
76
76
  inputType,
77
77
  sourceContext,
@@ -82,7 +82,7 @@ module.exports = function init(core) {
82
82
 
83
83
  sourceContext.parsedBody = !!Object.keys(_data).length;
84
84
  } catch (err) {
85
- logger.error({ name, err }, 'unable to handle source');
85
+ logger.error({ err, funcKey: data.funcKey }, 'unable to handle source');
86
86
  }
87
87
 
88
88
  return next(...args);
@@ -99,11 +99,10 @@ module.exports = function init(core) {
99
99
  name: 'body-parser',
100
100
  patchType,
101
101
  post(data) {
102
- const name = 'body-parser.bodyParser';
103
102
  data.result = patcher.patch(data.result, {
104
- name,
103
+ name: 'body-parser.bodyParser',
105
104
  patchType,
106
- pre: createPreHook(name),
105
+ pre: preHook,
107
106
  });
108
107
  },
109
108
  });
@@ -113,11 +112,10 @@ module.exports = function init(core) {
113
112
  name: `body-parser.${method}`,
114
113
  patchType,
115
114
  post(data) {
116
- const name = `body-parser.${method}.${method}Parser`;
117
115
  data.result = patcher.patch(data.result, {
118
- name,
116
+ name: `body-parser.${method}.${method}Parser`,
119
117
  patchType,
120
- pre: createPreHook(name)
118
+ pre: preHook
121
119
  });
122
120
  },
123
121
  });
@@ -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
 
@@ -18,6 +18,9 @@
18
18
  const { InputType } = require('@contrast/common');
19
19
  const { patchType } = require('../common');
20
20
 
21
+ const inputType = InputType.MULTIPART_VALUE;
22
+ const name = 'busboy';
23
+
21
24
  module.exports = (core) => {
22
25
  const {
23
26
  depHooks,
@@ -26,21 +29,18 @@ module.exports = (core) => {
26
29
  assess: { dataflow: { sources } },
27
30
  } = core;
28
31
 
29
- const name = 'busboy';
30
-
31
32
  function createPreHook(finalEventName) {
32
- return function(data) {
33
- const { orig, hooked } = data;
33
+ return function (data) {
34
+ const { orig, hooked, funcKey } = data;
34
35
  const sourceContext = core.scopes.sources.getStore()?.assess;
35
- const inputType = InputType.MULTIPART_VALUE;
36
36
 
37
37
  if (!sourceContext) {
38
- logger.error({ inputType, name }, 'unable to handle source. Missing `sourceContext`');
38
+ logger.error({ inputType, funcKey }, 'unable to handle source. Missing `sourceContext`');
39
39
  return;
40
40
  }
41
41
 
42
42
  if (sourceContext.parsedBody) {
43
- logger.trace({ inputType, name }, 'values already tracked');
43
+ logger.trace({ inputType, funcKey }, 'values already tracked');
44
44
  return;
45
45
  }
46
46
 
@@ -67,7 +67,7 @@ module.exports = (core) => {
67
67
  data.args[2] = obj[fieldName];
68
68
  sourceContext.busboyParsedBody = true;
69
69
  } catch (err) {
70
- logger.error({ err, inputType, name }, 'unable to handle source');
70
+ logger.error({ err, inputType, funcKey }, 'unable to handle source');
71
71
  }
72
72
  }
73
73
 
@@ -88,8 +88,8 @@ module.exports = (core) => {
88
88
  });
89
89
 
90
90
 
91
- depHooks.resolve({ name, version: '>=1.0.0' }, (busboy) => patcher.patch(
92
- busboy, {
91
+ depHooks.resolve({ name, version: '>=1.0.0' }, (busboy) =>
92
+ patcher.patch(busboy, {
93
93
  name,
94
94
  patchType,
95
95
  post(data) {
@@ -99,14 +99,14 @@ module.exports = (core) => {
99
99
  pre: createPreHook('close')
100
100
  });
101
101
  }
102
- }
103
- ));
102
+ })
103
+ );
104
104
  }
105
105
 
106
- const busboy1Instrumentation = sources.busboy1Instrumentation = {
106
+ const busboyInstrumentation = sources.busboyInstrumentation = {
107
107
  install
108
108
  };
109
109
 
110
- return busboy1Instrumentation;
110
+ return busboyInstrumentation;
111
111
  };
112
112
 
@@ -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
 
@@ -36,17 +36,18 @@ module.exports = function init(core) {
36
36
  name,
37
37
  patchType,
38
38
  pre(data) {
39
+ const { funcKey } = data;
39
40
  const [req, , next] = data.args;
40
41
  data.args[2] = function contrastNext(...args) {
41
42
  const sourceContext = scopes.sources.getStore()?.assess;
42
43
 
43
44
  if (!sourceContext) {
44
- logger.error({ name }, 'unable to handle source. Missing `sourceContext`');
45
+ logger.error({ funcKey }, 'unable to handle source. Missing `sourceContext`');
45
46
  return;
46
47
  }
47
48
 
48
49
  if (sourceContext.parsedCookies) {
49
- logger.trace({ name }, 'cookies already tracked');
50
+ logger.trace({ funcKey }, 'cookies already tracked');
50
51
  } else if (req.cookies) {
51
52
  try {
52
53
  assess.dataflow.sources.handle({
@@ -62,12 +63,12 @@ module.exports = function init(core) {
62
63
 
63
64
  sourceContext.parsedCookies = !!Object.keys(req.cookies).length;
64
65
  } catch (err) {
65
- logger.error({ name, err }, 'unable to handle source');
66
+ logger.error({ err, funcKey }, 'unable to handle source');
66
67
  }
67
68
  }
68
69
 
69
70
  if (sourceContext.parsedSignedCookies) {
70
- logger.trace({ name }, 'signedCookies already tracked');
71
+ logger.trace({ funcKey }, 'signedCookies already tracked');
71
72
  } else if (req.signedCookies) {
72
73
  try {
73
74
  assess.dataflow.sources.handle({
@@ -83,7 +84,7 @@ module.exports = function init(core) {
83
84
 
84
85
  sourceContext.parsedSignedCookies = !!Object.keys(req.signedCookies).length;
85
86
  } catch (err) {
86
- logger.error({ name, err }, 'unable to handle source');
87
+ logger.error({ err, funcKey }, 'unable to handle source');
87
88
  }
88
89
  }
89
90
 
@@ -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
 
@@ -16,7 +16,7 @@
16
16
  'use strict';
17
17
 
18
18
  const { InputType } = require('@contrast/common');
19
- const { patchType } = require('../../../propagation/common');
19
+ const { patchType } = require('../../common');
20
20
 
21
21
  module.exports = function init(core) {
22
22
  const { depHooks, patcher, logger } = core;
@@ -30,25 +30,24 @@ module.exports = function init(core) {
30
30
  patcher.patch(Layer.prototype, 'match', {
31
31
  name,
32
32
  patchType,
33
- post(data) {
34
- const layer = data.obj;
33
+ post({ obj: layer, result, orig, hooked, funcKey }) {
35
34
 
36
35
  // we can exit early if
37
36
  // the layer doesn't match the request or
38
37
  // the layer doesn't recognize any parameters
39
- if (!data.result || !layer.keys || layer.keys.length === 0) {
38
+ if (!result || !layer.keys || layer.keys.length === 0) {
40
39
  return;
41
40
  }
42
41
 
43
42
  const sourceContext = core.scopes.sources.getStore()?.assess;
44
43
 
45
44
  if (!sourceContext) {
46
- logger.error({ name }, 'unable to handle source. Missing `sourceContext`');
45
+ logger.error({ funcKey }, 'unable to handle source. Missing `sourceContext`');
47
46
  return;
48
47
  }
49
48
 
50
49
  if (sourceContext.parsedParams) {
51
- logger.trace({ name }, 'values already tracked');
50
+ logger.trace({ funcKey }, 'values already tracked');
52
51
  return;
53
52
  }
54
53
 
@@ -58,15 +57,15 @@ module.exports = function init(core) {
58
57
  name,
59
58
  inputType: InputType.PARAMETER_VALUE,
60
59
  stacktraceOpts: {
61
- constructorOpt: data.hooked,
62
- prependFrames: [data.orig]
60
+ constructorOpt: hooked,
61
+ prependFrames: [orig]
63
62
  },
64
63
  data: layer.params,
65
64
  sourceContext
66
65
  });
67
66
  sourceContext.parsedParams = true;
68
67
  } catch (err) {
69
- logger.error({ err, name }, 'unable to handle source');
68
+ logger.error({ err, funcKey }, 'unable to handle source');
70
69
  }
71
70
  }
72
71
  });
@@ -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
 
@@ -31,9 +31,8 @@ module.exports = function (core) {
31
31
  depHooks.resolve({ name: 'fastify', version: '>=3.0.0' }, (fastify) => patcher.patch(fastify, {
32
32
  name: 'fastify.constructor',
33
33
  patchType,
34
- post({ result: server }) {
34
+ post({ result: server, funcKey }) {
35
35
  server.addHook('preValidation', function preValidationHandler(request, reply, done) {
36
- const name = 'fastify.preValidation';
37
36
  const bodyType = request?.headers?.['content-type']?.includes('/json')
38
37
  ? InputType.JSON_VALUE
39
38
  : typeof request.body == 'object'
@@ -42,7 +41,7 @@ module.exports = function (core) {
42
41
  const sourceContext = core.scopes.sources.getStore()?.assess;
43
42
 
44
43
  if (!sourceContext) {
45
- logger.error({ name }, 'unable to handle source. Missing `sourceContext`');
44
+ logger.error({ funcKey }, 'unable to handle source. Missing `sourceContext`');
46
45
  return;
47
46
  }
48
47
 
@@ -52,7 +51,7 @@ module.exports = function (core) {
52
51
  { key: 'body', inputType: bodyType, alreadyTrackedFlag: 'parsedBody' }
53
52
  ].forEach(({ key, inputType, alreadyTrackedFlag }) => {
54
53
  if (sourceContext[alreadyTrackedFlag]) {
55
- logger.trace({ inputType, name }, 'values already tracked');
54
+ logger.trace({ inputType, funcKey }, 'values already tracked');
56
55
  return;
57
56
  }
58
57
 
@@ -61,14 +60,14 @@ module.exports = function (core) {
61
60
  context: `req.${key}`,
62
61
  data: request[key],
63
62
  inputType,
64
- name,
63
+ name: 'fastify.preValidation',
65
64
  stacktraceOpts: {
66
65
  constructorOpt: preValidationHandler,
67
66
  },
68
67
  sourceContext
69
68
  });
70
69
  } catch (err) {
71
- logger.error({ err, inputType, name }, 'unable to handle Fastify source');
70
+ logger.error({ err, inputType, funcKey }, 'unable to handle Fastify source');
72
71
  }
73
72
  });
74
73
 
@@ -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