@contrast/agent-bundle 5.46.0 → 5.47.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 (178) hide show
  1. package/README.md +1 -1
  2. package/node_modules/@contrast/agent/README.md +1 -1
  3. package/node_modules/@contrast/agent/package.json +12 -12
  4. package/node_modules/@contrast/agentify/package.json +15 -15
  5. package/node_modules/@contrast/architecture-components/package.json +5 -5
  6. package/node_modules/@contrast/assess/lib/{session-configuration → configuration-analysis}/common.js +1 -1
  7. package/node_modules/@contrast/assess/lib/{session-configuration → configuration-analysis}/handlers.js +23 -10
  8. package/node_modules/@contrast/assess/lib/{session-configuration → configuration-analysis}/index.js +6 -4
  9. package/node_modules/@contrast/assess/lib/configuration-analysis/install/apollo-server.js +92 -0
  10. package/node_modules/@contrast/assess/lib/{session-configuration → configuration-analysis}/install/express-session.js +2 -2
  11. package/node_modules/@contrast/assess/lib/{session-configuration → configuration-analysis}/install/fastify-cookie.js +2 -2
  12. package/node_modules/@contrast/assess/lib/configuration-analysis/install/graphql-yoga.js +90 -0
  13. package/node_modules/@contrast/assess/lib/{session-configuration → configuration-analysis}/install/hapi.js +2 -2
  14. package/node_modules/@contrast/assess/lib/{session-configuration → configuration-analysis}/install/koa.js +3 -3
  15. package/node_modules/@contrast/assess/lib/dataflow/propagation/install/string/substring.js +1 -1
  16. package/node_modules/@contrast/assess/lib/dataflow/sources/handler.js +9 -2
  17. package/node_modules/@contrast/assess/lib/dataflow/sources/index.js +2 -0
  18. package/node_modules/@contrast/assess/lib/dataflow/sources/install/fastify-websocket.js +63 -0
  19. package/node_modules/@contrast/assess/lib/dataflow/sources/install/http.js +42 -38
  20. package/node_modules/@contrast/assess/lib/dataflow/sources/install/koa/index.js +1 -1
  21. package/node_modules/@contrast/assess/lib/dataflow/sources/install/koa/koa-bodyparsers.js +76 -48
  22. package/node_modules/@contrast/assess/lib/dataflow/sources/install/koa/koa-multer.js +1 -1
  23. package/node_modules/@contrast/assess/lib/dataflow/sources/install/koa/koa-routers.js +2 -2
  24. package/node_modules/@contrast/assess/lib/dataflow/sources/install/koa/{koa2.js → koa.js} +3 -3
  25. package/node_modules/@contrast/assess/lib/dataflow/sources/install/socket.io.js +80 -0
  26. package/node_modules/@contrast/assess/lib/index.d.ts +4 -3
  27. package/node_modules/@contrast/assess/lib/index.js +1 -1
  28. package/node_modules/@contrast/assess/lib/policy.js +2 -2
  29. package/node_modules/@contrast/assess/package.json +12 -12
  30. package/node_modules/@contrast/common/lib/constants.d.ts +12 -4
  31. package/node_modules/@contrast/common/lib/constants.js +16 -7
  32. package/node_modules/@contrast/common/lib/types.d.ts +5 -1
  33. package/node_modules/@contrast/common/package.json +1 -1
  34. package/node_modules/@contrast/config/lib/common.js +1 -0
  35. package/node_modules/@contrast/config/lib/options.js +7 -1
  36. package/node_modules/@contrast/config/package.json +3 -3
  37. package/node_modules/@contrast/core/package.json +5 -5
  38. package/node_modules/@contrast/deadzones/package.json +5 -5
  39. package/node_modules/@contrast/dep-hooks/lib/package-finder.d.ts +2 -2
  40. package/node_modules/@contrast/dep-hooks/lib/package-finder.js +3 -2
  41. package/node_modules/@contrast/dep-hooks/package.json +4 -4
  42. package/node_modules/@contrast/esm-hooks/README.md +2 -2
  43. package/node_modules/@contrast/esm-hooks/package.json +6 -6
  44. package/node_modules/@contrast/instrumentation/package.json +5 -5
  45. package/node_modules/@contrast/library-analysis/lib/install/library-reporting/dep.json +149 -149
  46. package/node_modules/@contrast/library-analysis/lib/install/library-reporting/index.js +2 -11
  47. package/node_modules/@contrast/library-analysis/lib/install/library-reporting/utils.js +2 -0
  48. package/node_modules/@contrast/library-analysis/lib/install/library-usage/index.js +3 -1
  49. package/node_modules/@contrast/library-analysis/lib/util.js +0 -2
  50. package/node_modules/@contrast/library-analysis/package.json +4 -4
  51. package/node_modules/@contrast/logger/package.json +3 -3
  52. package/node_modules/@contrast/metrics/package.json +6 -6
  53. package/node_modules/@contrast/patcher/package.json +2 -2
  54. package/node_modules/@contrast/protect/lib/error-handlers/index.js +1 -1
  55. package/node_modules/@contrast/protect/lib/error-handlers/install/{koa2.js → koa.js} +4 -4
  56. package/node_modules/@contrast/protect/lib/index.d.ts +1 -1
  57. package/node_modules/@contrast/protect/lib/input-analysis/index.js +2 -3
  58. package/node_modules/@contrast/protect/lib/input-analysis/install/koa-bodyparsers.js +92 -0
  59. package/node_modules/@contrast/protect/lib/input-analysis/install/{koa2.js → koa.js} +5 -5
  60. package/node_modules/@contrast/protect/package.json +11 -11
  61. package/node_modules/@contrast/reporter/lib/reporters/contrast-ui/endpoints/application-activity/translations.js +6 -10
  62. package/node_modules/@contrast/reporter/lib/reporters/contrast-ui/endpoints/routes-observed.js +4 -0
  63. package/node_modules/@contrast/reporter/lib/reporters/contrast-ui/endpoints/traces/index.d.ts +1 -1
  64. package/node_modules/@contrast/reporter/lib/reporters/contrast-ui/endpoints/traces/index.js +1 -1
  65. package/node_modules/@contrast/reporter/lib/reporters/contrast-ui/endpoints/traces/translations.d.ts +1 -1
  66. package/node_modules/@contrast/reporter/lib/reporters/contrast-ui/endpoints/traces/translations.js +22 -9
  67. package/node_modules/@contrast/reporter/lib/reporters/file.js +1 -1
  68. package/node_modules/@contrast/reporter/package.json +6 -6
  69. package/node_modules/@contrast/rewriter/package.json +5 -5
  70. package/node_modules/@contrast/route-coverage/lib/index.d.ts +0 -2
  71. package/node_modules/@contrast/route-coverage/lib/index.js +10 -1
  72. package/node_modules/@contrast/route-coverage/lib/install/express/express5.js +16 -1
  73. package/node_modules/@contrast/route-coverage/lib/install/fastify.js +25 -15
  74. package/node_modules/@contrast/route-coverage/lib/install/graphql.js +6 -1
  75. package/node_modules/@contrast/route-coverage/lib/install/koa.js +1 -1
  76. package/node_modules/@contrast/route-coverage/lib/install/socket.io.js +127 -0
  77. package/node_modules/@contrast/route-coverage/package.json +8 -8
  78. package/node_modules/@contrast/scopes/package.json +5 -5
  79. package/node_modules/@contrast/sec-obs/package.json +9 -9
  80. package/node_modules/@contrast/sources/lib/index.js +65 -22
  81. package/node_modules/@contrast/sources/lib/index.test.js +78 -33
  82. package/node_modules/@contrast/sources/lib/source-info.js +1 -10
  83. package/node_modules/@contrast/sources/package.json +3 -3
  84. package/node_modules/@contrast/telemetry/package.json +5 -5
  85. package/node_modules/@types/node/README.md +1 -1
  86. package/node_modules/@types/node/assert.d.ts +37 -2
  87. package/node_modules/@types/node/buffer.buffer.d.ts +9 -0
  88. package/node_modules/@types/node/buffer.d.ts +8 -4
  89. package/node_modules/@types/node/child_process.d.ts +65 -42
  90. package/node_modules/@types/node/cluster.d.ts +4 -5
  91. package/node_modules/@types/node/crypto.d.ts +1079 -338
  92. package/node_modules/@types/node/dgram.d.ts +9 -8
  93. package/node_modules/@types/node/diagnostics_channel.d.ts +0 -2
  94. package/node_modules/@types/node/dns.d.ts +1 -1
  95. package/node_modules/@types/node/events.d.ts +1 -1
  96. package/node_modules/@types/node/fs/promises.d.ts +39 -21
  97. package/node_modules/@types/node/fs.d.ts +104 -87
  98. package/node_modules/@types/node/globals.d.ts +2 -0
  99. package/node_modules/@types/node/globals.typedarray.d.ts +19 -0
  100. package/node_modules/@types/node/http.d.ts +66 -27
  101. package/node_modules/@types/node/http2.d.ts +178 -52
  102. package/node_modules/@types/node/https.d.ts +91 -62
  103. package/node_modules/@types/node/index.d.ts +2 -0
  104. package/node_modules/@types/node/inspector.d.ts +24 -0
  105. package/node_modules/@types/node/inspector.generated.d.ts +181 -0
  106. package/node_modules/@types/node/net.d.ts +12 -11
  107. package/node_modules/@types/node/os.d.ts +14 -3
  108. package/node_modules/@types/node/package.json +3 -3
  109. package/node_modules/@types/node/perf_hooks.d.ts +6 -8
  110. package/node_modules/@types/node/process.d.ts +12 -23
  111. package/node_modules/@types/node/readline/promises.d.ts +1 -1
  112. package/node_modules/@types/node/sea.d.ts +9 -0
  113. package/node_modules/@types/node/sqlite.d.ts +119 -10
  114. package/node_modules/@types/node/stream/consumers.d.ts +2 -2
  115. package/node_modules/@types/node/stream/web.d.ts +6 -55
  116. package/node_modules/@types/node/stream.d.ts +38 -23
  117. package/node_modules/@types/node/string_decoder.d.ts +2 -2
  118. package/node_modules/@types/node/test.d.ts +29 -3
  119. package/node_modules/@types/node/tls.d.ts +90 -66
  120. package/node_modules/@types/node/ts5.6/buffer.buffer.d.ts +10 -2
  121. package/node_modules/@types/node/ts5.6/globals.typedarray.d.ts +16 -0
  122. package/node_modules/@types/node/ts5.6/index.d.ts +2 -0
  123. package/node_modules/@types/node/ts5.7/index.d.ts +2 -0
  124. package/node_modules/@types/node/url.d.ts +2 -2
  125. package/node_modules/@types/node/util.d.ts +12 -3
  126. package/node_modules/@types/node/v8.d.ts +38 -5
  127. package/node_modules/@types/node/vm.d.ts +169 -88
  128. package/node_modules/@types/node/wasi.d.ts +1 -1
  129. package/node_modules/@types/node/web-globals/crypto.d.ts +32 -0
  130. package/node_modules/@types/node/web-globals/streams.d.ts +22 -0
  131. package/node_modules/@types/node/worker_threads.d.ts +76 -1
  132. package/node_modules/@types/node/zlib.d.ts +25 -24
  133. package/node_modules/axios/CHANGELOG.md +403 -357
  134. package/node_modules/axios/README.md +80 -49
  135. package/node_modules/axios/dist/axios.js +121 -46
  136. package/node_modules/axios/dist/axios.js.map +1 -1
  137. package/node_modules/axios/dist/axios.min.js +2 -2
  138. package/node_modules/axios/dist/axios.min.js.map +1 -1
  139. package/node_modules/axios/dist/browser/axios.cjs +126 -57
  140. package/node_modules/axios/dist/browser/axios.cjs.map +1 -1
  141. package/node_modules/axios/dist/esm/axios.js +126 -57
  142. package/node_modules/axios/dist/esm/axios.js.map +1 -1
  143. package/node_modules/axios/dist/esm/axios.min.js +2 -2
  144. package/node_modules/axios/dist/esm/axios.min.js.map +1 -1
  145. package/node_modules/axios/dist/node/axios.cjs +346 -97
  146. package/node_modules/axios/dist/node/axios.cjs.map +1 -1
  147. package/node_modules/axios/index.d.cts +4 -0
  148. package/node_modules/axios/index.d.ts +4 -0
  149. package/node_modules/axios/lib/adapters/adapters.js +85 -40
  150. package/node_modules/axios/lib/adapters/fetch.js +1 -1
  151. package/node_modules/axios/lib/adapters/http.js +220 -42
  152. package/node_modules/axios/lib/core/InterceptorManager.js +1 -1
  153. package/node_modules/axios/lib/core/mergeConfig.js +4 -4
  154. package/node_modules/axios/lib/env/data.js +1 -1
  155. package/node_modules/axios/lib/helpers/HttpStatusCode.js +6 -0
  156. package/node_modules/axios/lib/helpers/bind.js +7 -0
  157. package/node_modules/axios/lib/helpers/cookies.js +24 -13
  158. package/node_modules/axios/package.json +9 -4
  159. package/node_modules/detect-libc/lib/filesystem.js +1 -1
  160. package/node_modules/detect-libc/package.json +3 -1
  161. package/node_modules/node-abi/abi_registry.json +12 -2
  162. package/node_modules/node-abi/package.json +3 -6
  163. package/node_modules/semver/classes/range.js +1 -0
  164. package/node_modules/semver/classes/semver.js +19 -5
  165. package/node_modules/semver/internal/identifiers.js +4 -0
  166. package/node_modules/semver/package.json +3 -3
  167. package/node_modules/undici-types/agent.d.ts +1 -0
  168. package/node_modules/undici-types/diagnostics-channel.d.ts +0 -1
  169. package/node_modules/undici-types/errors.d.ts +5 -15
  170. package/node_modules/undici-types/eventsource.d.ts +6 -1
  171. package/node_modules/undici-types/index.d.ts +4 -1
  172. package/node_modules/undici-types/interceptors.d.ts +5 -0
  173. package/node_modules/undici-types/package.json +1 -1
  174. package/node_modules/undici-types/snapshot-agent.d.ts +5 -3
  175. package/node_modules/undici-types/webidl.d.ts +82 -21
  176. package/package.json +3 -3
  177. package/node_modules/@contrast/protect/lib/input-analysis/install/koa-body5.js +0 -63
  178. package/node_modules/@contrast/protect/lib/input-analysis/install/koa-bodyparser4.js +0 -64
@@ -36,63 +36,68 @@ module.exports = function (core) {
36
36
  const logger = core.logger.child({ name: 'contrast:assess' });
37
37
 
38
38
  /**
39
- * The around hook for `emit` that
40
- * invokes the protect service to do analysis when appropriate.
39
+ * The around hook for `emit` that handles tracking URL and header values.
40
+ * We track those when the event is 'request' or 'upgrade'. Also, for when
41
+ * event is 'request', we will also patch some ServerResponse methods. We
42
+ * currentl don't patch the raw socket for tracking when event is 'upgrade',
43
+ * sources instrumentation for websocket events happens per framework.
41
44
  */
42
45
  function around(next, data) {
43
46
  const [type] = data.args;
44
47
 
45
- if (type !== 'request') return next();
48
+ if (type !== 'request' && type !== 'upgrade') return next();
46
49
 
47
50
  try {
48
- const [, req, res] = data.args;
51
+ const [, req, resOrSocket] = data.args;
49
52
  const sourceContext = getSourceContext();
50
53
 
51
54
  if (!sourceContext?.policy) {
52
55
  return next();
53
56
  }
54
57
 
55
- patcher.patch(res, 'writeHead', {
56
- name: 'write-head',
57
- patchType,
58
- pre(data) {
59
- const obj = data.args[data.args.length - 1];
60
- if (!obj) return;
58
+ if (type == 'request') {
59
+ patcher.patch(resOrSocket, 'writeHead', {
60
+ name: 'write-head',
61
+ patchType,
62
+ pre(data) {
63
+ const obj = data.args[data.args.length - 1];
64
+ if (!obj) return;
61
65
 
62
- if (Array.isArray(obj)) {
63
- for (let i = 0; i < obj.length; i += 2) {
64
- const key = obj[i];
65
- const value = obj[i + 1];
66
+ if (Array.isArray(obj)) {
67
+ for (let i = 0; i < obj.length; i += 2) {
68
+ const key = obj[i];
69
+ const value = obj[i + 1];
66
70
 
67
- if (StringPrototypeToLowerCase.call(key) === 'content-type') {
68
- sourceContext.responseData.contentType = value;
71
+ if (StringPrototypeToLowerCase.call(key) === 'content-type') {
72
+ sourceContext.responseData.contentType = value;
73
+ }
69
74
  }
70
- }
71
- } else if (typeof obj === 'object') {
72
- for (const [key, value] of Object.entries(obj)) {
73
- if (StringPrototypeToLowerCase.call(key) === 'content-type') {
74
- sourceContext.responseData.contentType = value;
75
+ } else if (typeof obj === 'object') {
76
+ for (const [key, value] of Object.entries(obj)) {
77
+ if (StringPrototypeToLowerCase.call(key) === 'content-type') {
78
+ sourceContext.responseData.contentType = value;
79
+ }
75
80
  }
76
81
  }
77
82
  }
78
- }
79
- });
83
+ });
80
84
 
81
- if (!patcher.hooks.get(res?.setHeader)?.funcKeys.has(`${patchType}:set-header`)) {
82
- patcher.patch(res, 'setHeader', {
83
- name: 'set-header',
84
- patchType,
85
- pre(data) {
86
- const [name = '', value] = data.args;
87
- if (
88
- value &&
89
- StringPrototypeToLowerCase.call(name) === 'content-type' &&
90
- getSourceContext()
91
- ) {
92
- sourceContext.responseData.contentType = value;
85
+ if (!patcher.hooks.get(resOrSocket?.setHeader)?.funcKeys.has(`${patchType}:set-header`)) {
86
+ patcher.patch(resOrSocket, 'setHeader', {
87
+ name: 'set-header',
88
+ patchType,
89
+ pre(data) {
90
+ const [name = '', value] = data.args;
91
+ if (
92
+ value &&
93
+ StringPrototypeToLowerCase.call(name) === 'content-type' &&
94
+ getSourceContext()
95
+ ) {
96
+ sourceContext.responseData.contentType = value;
97
+ }
93
98
  }
94
- }
95
- });
99
+ });
100
+ }
96
101
  }
97
102
 
98
103
  const sourceName = 'ClientRequest';
@@ -143,7 +148,6 @@ module.exports = function (core) {
143
148
  }
144
149
  });
145
150
 
146
-
147
151
  //
148
152
  // now track the rawHeaders. headers are complicated because they appear
149
153
  // three times: headers, headersDistinct, and rawHeaders and we want to
@@ -20,7 +20,7 @@ const { callChildComponentMethodsSync } = require('@contrast/common');
20
20
  module.exports = function(core) {
21
21
  const koaSources = core.assess.dataflow.sources.koaInstrumentation = {};
22
22
 
23
- require('./koa2')(core);
23
+ require('./koa')(core);
24
24
  require('./koa-bodyparsers')(core);
25
25
  require('./koa-multer')(core);
26
26
  require('./koa-routers')(core);
@@ -30,58 +30,86 @@ module.exports = (core) => {
30
30
  },
31
31
  } = core;
32
32
 
33
- function install() {
34
- [['koa-body', '<7'], ['koa-bodyparser', '<5']].forEach(([name, version]) => {
35
- depHooks.resolve({ name, version }, (koaBody) => patcher.patch(koaBody, {
33
+ function postFn(name) {
34
+ return function(data) {
35
+ data.result = patcher.patch(data.result, {
36
36
  name,
37
37
  patchType,
38
- post(data) {
39
- data.result = patcher.patch(data.result, {
40
- name,
41
- patchType,
42
- pre(data) {
43
- const { funcKey } = data;
44
- const [ctx, origNext] = data.args;
45
- const sourceContext = getSourceContext();
46
-
47
- if (!sourceContext) return;
48
-
49
- if (sourceContext.parsedBody) {
50
- logger.trace({ funcKey }, 'values already tracked');
51
- return;
52
- }
53
-
54
- data.args[1] = async function contrastNext(origErr) {
55
- const contentType = scopes.sources.getStore()?.sourceInfo?.contentType;
56
- const inputType = contentType?.includes?.('/json')
57
- ? InputType.JSON_VALUE
58
- : typeof ctx.request.body == 'object'
59
- ? InputType.PARAMETER_VALUE
60
- : InputType.BODY;
61
-
62
- try {
63
- sources.handle({
64
- context: 'ctx.request.body',
65
- name,
66
- inputType,
67
- stacktraceOpts: {
68
- constructorOpt: contrastNext,
69
- },
70
- data: ctx.request.body,
71
- sourceContext
72
- });
73
-
74
- sourceContext.parsedBody = !!Object.keys(ctx.request.body).length;
75
- } catch (err) {
76
- logger.error({ err, inputType, funcKey }, 'unable to handle Koa source');
77
- }
78
-
79
- await origNext(origErr);
80
- };
38
+ pre(data) {
39
+ const { funcKey } = data;
40
+ const [ctx, origNext] = data.args;
41
+ const sourceContext = getSourceContext();
42
+
43
+ if (!sourceContext) return;
44
+
45
+ if (sourceContext.parsedBody) {
46
+ logger.trace({ funcKey }, 'values already tracked');
47
+ return;
48
+ }
49
+
50
+ data.args[1] = async function contrastNext(origErr) {
51
+ const contentType = scopes.sources.getStore()?.sourceInfo?.contentType;
52
+ const inputType = contentType?.includes?.('/json')
53
+ ? InputType.JSON_VALUE
54
+ : typeof ctx.request.body == 'object'
55
+ ? InputType.PARAMETER_VALUE
56
+ : InputType.BODY;
57
+
58
+ try {
59
+ sources.handle({
60
+ context: 'ctx.request.body',
61
+ name,
62
+ inputType,
63
+ stacktraceOpts: {
64
+ constructorOpt: contrastNext,
65
+ },
66
+ data: ctx.request.body,
67
+ sourceContext
68
+ });
69
+
70
+ sourceContext.parsedBody = !!Object.keys(ctx.request.body || {}).length;
71
+ } catch (err) {
72
+ logger.error({ err, inputType, funcKey }, 'unable to handle Koa source');
81
73
  }
82
- });
74
+
75
+ await origNext(origErr);
76
+ };
83
77
  }
84
- }));
78
+ });
79
+ };
80
+ }
81
+
82
+ function install() {
83
+
84
+ [['koa-body', '>=4 <6'], ['koa-bodyparser', '>=4 <5']].forEach(([name, version]) => {
85
+ depHooks.resolve({ name, version }, (koaBody) =>
86
+ patcher.patch(koaBody, {
87
+ name,
88
+ patchType,
89
+ post: postFn(name)
90
+ })
91
+ );
92
+ });
93
+
94
+ depHooks.resolve({ name: 'koa-body', version: '>=6 <7' }, (koaBody) =>
95
+ patcher.patch(koaBody, 'koaBody', {
96
+ name: 'koaBody',
97
+ patchType,
98
+ post: postFn('koa-body')
99
+ })
100
+ );
101
+
102
+ depHooks.resolve({ name: '@koa/bodyparser', version: '>=5 <7' }, (koaBody) => {
103
+ const patchedBodyParser = patcher.patch(koaBody.bodyParser, {
104
+ name: '@koa/bodyparser',
105
+ patchType,
106
+ post: postFn('@koa/bodyparser')
107
+ }
108
+ );
109
+ return {
110
+ default: patchedBodyParser,
111
+ bodyParser: patchedBodyParser
112
+ };
85
113
  });
86
114
  }
87
115
 
@@ -67,7 +67,7 @@ module.exports = (core) => {
67
67
  }
68
68
 
69
69
  function install() {
70
- [['koa-multer', '<2'], ['@koa/multer', '<4']].forEach(([name, version]) => {
70
+ [['koa-multer', '<2'], ['@koa/multer', '>=3 <5']].forEach(([name, version]) => {
71
71
  depHooks.resolve(
72
72
  { name, version }, (_export) => {
73
73
  const origMulter = _export;
@@ -31,11 +31,11 @@ module.exports = (core) => {
31
31
 
32
32
  // Patch `koa-router` and `@koa/router` to handle parsed params
33
33
  function install() {
34
- [['koa-router', '<14'], ['@koa/router', '<14']].forEach(([router, version]) => {
34
+ [['koa-router', '>=12 <15'], ['@koa/router', '>=12 <15']].forEach(([router, version]) => {
35
35
  depHooks.resolve(
36
36
  { name: router, version, file: 'lib/layer.js' },
37
37
  (layer) => {
38
- layer.prototype = patcher.patch(layer.prototype, 'params', {
38
+ patcher.patch(layer.prototype, 'params', {
39
39
  name: `[${router}].layer.prototype`,
40
40
  patchType,
41
41
  post({ orig, hooked, result, name, funcKey }) {
@@ -40,7 +40,7 @@ module.exports = (core) => {
40
40
  * registers a depHook for koa module instrumentation
41
41
  */
42
42
  function install() {
43
- depHooks.resolve({ name: 'koa', version: '>=2.3.0 <3' }, (Koa) => {
43
+ depHooks.resolve({ name: 'koa', version: '>=2.3.0 <4' }, (Koa) => {
44
44
  const createMiddleware = ({ name, funcKey }) => {
45
45
  const contrastStartMiddleware = function contrastStartMiddleware(ctx, next) {
46
46
  const sourceContext = getSourceContext();
@@ -101,9 +101,9 @@ module.exports = (core) => {
101
101
  });
102
102
  }
103
103
 
104
- const koa2Instrumentation = sources.koaInstrumentation.koa2 = {
104
+ const koaInstrumentation = sources.koaInstrumentation.koa = {
105
105
  install
106
106
  };
107
107
 
108
- return koa2Instrumentation;
108
+ return koaInstrumentation;
109
109
  };
@@ -0,0 +1,80 @@
1
+ /*
2
+ * Copyright: 2025 Contrast Security, Inc
3
+ * Contact: support@contrastsecurity.com
4
+ * License: Commercial
5
+
6
+ * NOTICE: This Software and the patented inventions embodied within may only be
7
+ * used as part of Contrast Security’s commercial offerings. Even though it is
8
+ * made available through public repositories, use of this Software is subject to
9
+ * the applicable End User Licensing Agreement found at
10
+ * https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
11
+ * between Contrast Security and the End User. The Software may not be reverse
12
+ * engineered, modified, repackaged, sold, redistributed or otherwise used in a
13
+ * way not consistent with the End User License Agreement.
14
+ */
15
+ 'use strict';
16
+
17
+ const { InputType, set } = require('@contrast/common');
18
+ const Core = require('@contrast/core/lib/ioc/core');
19
+ const { patchType } = require('../common');
20
+
21
+ const COMPONENT_NAME = 'assess.dataflow.sources.socketIoInstrumentation';
22
+
23
+ module.exports = Core.makeComponent({
24
+ name: COMPONENT_NAME,
25
+ factory: (core) => new SocketIOAssessSource(core),
26
+ });
27
+
28
+ class SocketIOAssessSource {
29
+ constructor(core) {
30
+ Object.defineProperty(this, 'core', { value: core });
31
+ set(core, COMPONENT_NAME, this);
32
+ }
33
+ /**
34
+ * Deploys socket.io instrumentation.
35
+ */
36
+ install() {
37
+ const {
38
+ depHooks,
39
+ patcher,
40
+ assess,
41
+ } = this.core;
42
+
43
+ depHooks.resolve(
44
+ { name: 'socket.io', version: '4' },
45
+ /**
46
+ * @param {import('socket.io-4')} xport the exported socket.io module
47
+ */
48
+ (xport) => {
49
+ patcher.patch(xport.Socket.prototype, 'dispatch', {
50
+ name: 'socket.io.Socket.prototype.dispatch',
51
+ patchType,
52
+ pre(data) {
53
+ if (!Array.isArray(data.args[0])) return;
54
+
55
+ const sourceContext = assess.getSourceContext();
56
+ if (!sourceContext) return;
57
+
58
+ const [eventName, ...params] = data.args[0];
59
+ assess.dataflow.sources.handle({
60
+ data: params,
61
+ name: 'socket.io.Socket.prototype.dispatch',
62
+ inputType: InputType.WEBSOCKET,
63
+ stacktraceOpts: { constructorOpt: data.hooked },
64
+ sourceContext,
65
+ onEvent(event, fieldName, pathName) {
66
+ event.context = `socket.io Socket.on("${eventName}", ...params)`;
67
+ event.args = [{
68
+ tracked: true,
69
+ value: `params.${pathName}`,
70
+ }];
71
+ },
72
+ });
73
+
74
+ data.args[0] = [eventName, ...params];
75
+ }
76
+ });
77
+ }
78
+ );
79
+ }
80
+ }
@@ -12,7 +12,7 @@
12
12
  * engineered, modified, repackaged, sold, redistributed or otherwise used in a
13
13
  * way not consistent with the End User License Agreement.
14
14
  */
15
- import { Rule, SessionConfigurationRule } from '@contrast/common';
15
+ import { Rule, ConfigurationRule } from '@contrast/common';
16
16
  import { Config } from '@contrast/config';
17
17
  import { Core as _Core } from '@contrast/core';
18
18
  import { Deadzones } from '@contrast/deadzones';
@@ -61,8 +61,9 @@ export interface SessionRuleState {
61
61
  }
62
62
 
63
63
  export interface RuleState {
64
- [SessionConfigurationRule.HTTPONLY]?: SessionRuleState,
65
- [SessionConfigurationRule.SECURE_FLAG_MISSING]?: SessionRuleState,
64
+ [ConfigurationRule.HTTPONLY]?: SessionRuleState,
65
+ [ConfigurationRule.SECURE_FLAG_MISSING]?: SessionRuleState,
66
+ [ConfigurationRule.GRAPHQL_INTROSPECTION]?: SessionRuleState,
66
67
  }
67
68
 
68
69
  export interface Assess {
@@ -70,7 +70,7 @@ module.exports = function assess(core) {
70
70
  require('./dataflow')(core);
71
71
  require('./crypto-analysis')(core);
72
72
  require('./response-scanning')(core);
73
- require('./session-configuration')(core);
73
+ require('./configuration-analysis')(core);
74
74
 
75
75
  // append async state to sources store when request-scope sources are created
76
76
  sources.addHook('onSource', (ctx) => {
@@ -21,7 +21,7 @@ const {
21
21
  InputType,
22
22
  Rule,
23
23
  ResponseScanningRule,
24
- SessionConfigurationRule,
24
+ ConfigurationRule,
25
25
  set,
26
26
  primordials: { ArrayPrototypeJoin, RegExpPrototypeTest }
27
27
  } = require('@contrast/common');
@@ -30,7 +30,7 @@ const { Core } = require('@contrast/core/lib/ioc/core');
30
30
  const ASSESS_RULES = Object.values({
31
31
  ...Rule,
32
32
  ...ResponseScanningRule,
33
- ...SessionConfigurationRule,
33
+ ...ConfigurationRule,
34
34
  });
35
35
  const BROAD_INPUT_EXCLUSION_TYPES = [
36
36
  ExclusionType.BODY,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrast/assess",
3
- "version": "1.64.0",
3
+ "version": "1.65.0",
4
4
  "description": "Contrast service providing framework-agnostic Assess support",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Contrast Security <nodejs@contrastsecurity.com> (https://www.contrastsecurity.com)",
@@ -20,18 +20,18 @@
20
20
  "test": "bash ../scripts/test.sh"
21
21
  },
22
22
  "dependencies": {
23
- "@contrast/common": "1.37.0",
24
- "@contrast/config": "1.53.0",
25
- "@contrast/core": "1.58.0",
26
- "@contrast/dep-hooks": "1.27.0",
23
+ "@contrast/common": "1.38.0",
24
+ "@contrast/config": "1.54.0",
25
+ "@contrast/core": "1.59.0",
26
+ "@contrast/dep-hooks": "1.28.0",
27
27
  "@contrast/distringuish": "^6.0.2",
28
- "@contrast/instrumentation": "1.37.0",
29
- "@contrast/logger": "1.31.0",
30
- "@contrast/patcher": "1.30.0",
31
- "@contrast/rewriter": "1.35.0",
32
- "@contrast/route-coverage": "1.50.0",
33
- "@contrast/scopes": "1.28.0",
34
- "@contrast/sources": "1.4.0",
28
+ "@contrast/instrumentation": "1.38.0",
29
+ "@contrast/logger": "1.32.0",
30
+ "@contrast/patcher": "1.31.0",
31
+ "@contrast/rewriter": "1.36.0",
32
+ "@contrast/route-coverage": "1.51.0",
33
+ "@contrast/scopes": "1.29.0",
34
+ "@contrast/sources": "1.5.0",
35
35
  "semver": "^7.6.0"
36
36
  }
37
37
  }
@@ -6,7 +6,7 @@ export declare enum Event {
6
6
  ASSESS_DATAFLOW_FINDING = "assess-dataflow-findings",
7
7
  ASSESS_DATAFLOW_SAFE_POSITIVE = "assess-dataflow-safe-positive",
8
8
  ASSESS_RESPONSE_SCANNING_FINDING = "assess-response-scanning-findings",
9
- ASSESS_SESSION_CONFIGURATION_FINDING = "assess-session-configuration-findings",
9
+ ASSESS_CONFIGURATION_FINDING = "assess-configuration-findings",
10
10
  ASSESS_CRYPTO_ANALYSIS_FINDING = "assess-crypto-analysis-finding",
11
11
  LIBRARY = "library",
12
12
  LIBRARY_USAGE = "library-usage",
@@ -60,9 +60,10 @@ export declare enum ResponseScanningRule {
60
60
  XCONTENTTYPE_HEADER_MISSING = "xcontenttype-header-missing",
61
61
  XXSPROTECTION_HEADER_DISABLED = "xxssprotection-header-disabled"
62
62
  }
63
- export declare enum SessionConfigurationRule {
63
+ export declare enum ConfigurationRule {
64
64
  HTTPONLY = "httponly",
65
- SECURE_FLAG_MISSING = "secure-flag-missing"
65
+ SECURE_FLAG_MISSING = "secure-flag-missing",
66
+ GRAPHQL_INTROSPECTION = "graphql-introspection"
66
67
  }
67
68
  export declare enum InputType {
68
69
  UNDEFINED_TYPE = "UNDEFINED_TYPE",
@@ -86,7 +87,8 @@ export declare enum InputType {
86
87
  METHOD = "METHOD",
87
88
  REQUEST = "REQUEST",
88
89
  URL_PARAMETER = "URL_PARAMETER",
89
- UNKNOWN = "UNKNOWN"
90
+ UNKNOWN = "UNKNOWN",
91
+ WEBSOCKET = "WEBSOCKET"
90
92
  }
91
93
  export declare enum ExclusionType {
92
94
  BODY = "BODY",
@@ -96,6 +98,12 @@ export declare enum ExclusionType {
96
98
  QUERYSTRING = "QUERYSTRING",
97
99
  URL = "URL"
98
100
  }
101
+ export declare enum RouteType {
102
+ HTTP = "HTTP",
103
+ MESSAGE_BROKER = "MESSAGE_BROKER",
104
+ MIDDLEWARE = "MIDDLEWARE",
105
+ RPC = "RPC"
106
+ }
99
107
  export declare enum DataflowTag {
100
108
  XML_ENCODED = "XML_ENCODED",
101
109
  XML_DECODED = "XML_DECODED",
@@ -14,7 +14,7 @@
14
14
  * way not consistent with the End User License Agreement.
15
15
  */
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.URI_REGEXES = exports.symbols = exports.agentLibIDListTypes = exports.FS_METHODS = exports.BLOCKING_MODES = exports.ServerEnvironment = exports.DataflowTag = exports.ExclusionType = exports.InputType = exports.SessionConfigurationRule = exports.ResponseScanningRule = exports.Rule = exports.ProtectRuleMode = exports.Event = void 0;
17
+ exports.URI_REGEXES = exports.symbols = exports.agentLibIDListTypes = exports.FS_METHODS = exports.BLOCKING_MODES = exports.ServerEnvironment = exports.DataflowTag = exports.RouteType = exports.ExclusionType = exports.InputType = exports.ConfigurationRule = exports.ResponseScanningRule = exports.Rule = exports.ProtectRuleMode = exports.Event = void 0;
18
18
  var Event;
19
19
  (function (Event) {
20
20
  // lifecycle
@@ -26,7 +26,7 @@ var Event;
26
26
  Event["ASSESS_DATAFLOW_FINDING"] = "assess-dataflow-findings";
27
27
  Event["ASSESS_DATAFLOW_SAFE_POSITIVE"] = "assess-dataflow-safe-positive";
28
28
  Event["ASSESS_RESPONSE_SCANNING_FINDING"] = "assess-response-scanning-findings";
29
- Event["ASSESS_SESSION_CONFIGURATION_FINDING"] = "assess-session-configuration-findings";
29
+ Event["ASSESS_CONFIGURATION_FINDING"] = "assess-configuration-findings";
30
30
  Event["ASSESS_CRYPTO_ANALYSIS_FINDING"] = "assess-crypto-analysis-finding";
31
31
  Event["LIBRARY"] = "library";
32
32
  Event["LIBRARY_USAGE"] = "library-usage";
@@ -85,11 +85,12 @@ var ResponseScanningRule;
85
85
  ResponseScanningRule["XCONTENTTYPE_HEADER_MISSING"] = "xcontenttype-header-missing";
86
86
  ResponseScanningRule["XXSPROTECTION_HEADER_DISABLED"] = "xxssprotection-header-disabled";
87
87
  })(ResponseScanningRule || (exports.ResponseScanningRule = ResponseScanningRule = {}));
88
- var SessionConfigurationRule;
89
- (function (SessionConfigurationRule) {
90
- SessionConfigurationRule["HTTPONLY"] = "httponly";
91
- SessionConfigurationRule["SECURE_FLAG_MISSING"] = "secure-flag-missing";
92
- })(SessionConfigurationRule || (exports.SessionConfigurationRule = SessionConfigurationRule = {}));
88
+ var ConfigurationRule;
89
+ (function (ConfigurationRule) {
90
+ ConfigurationRule["HTTPONLY"] = "httponly";
91
+ ConfigurationRule["SECURE_FLAG_MISSING"] = "secure-flag-missing";
92
+ ConfigurationRule["GRAPHQL_INTROSPECTION"] = "graphql-introspection";
93
+ })(ConfigurationRule || (exports.ConfigurationRule = ConfigurationRule = {}));
93
94
  var InputType;
94
95
  (function (InputType) {
95
96
  InputType["UNDEFINED_TYPE"] = "UNDEFINED_TYPE";
@@ -114,6 +115,7 @@ var InputType;
114
115
  InputType["REQUEST"] = "REQUEST";
115
116
  InputType["URL_PARAMETER"] = "URL_PARAMETER";
116
117
  InputType["UNKNOWN"] = "UNKNOWN";
118
+ InputType["WEBSOCKET"] = "WEBSOCKET";
117
119
  })(InputType || (exports.InputType = InputType = {}));
118
120
  var ExclusionType;
119
121
  (function (ExclusionType) {
@@ -124,6 +126,13 @@ var ExclusionType;
124
126
  ExclusionType["QUERYSTRING"] = "QUERYSTRING";
125
127
  ExclusionType["URL"] = "URL";
126
128
  })(ExclusionType || (exports.ExclusionType = ExclusionType = {}));
129
+ var RouteType;
130
+ (function (RouteType) {
131
+ RouteType["HTTP"] = "HTTP";
132
+ RouteType["MESSAGE_BROKER"] = "MESSAGE_BROKER";
133
+ RouteType["MIDDLEWARE"] = "MIDDLEWARE";
134
+ RouteType["RPC"] = "RPC";
135
+ })(RouteType || (exports.RouteType = RouteType = {}));
127
136
  var DataflowTag;
128
137
  (function (DataflowTag) {
129
138
  DataflowTag["XML_ENCODED"] = "XML_ENCODED";
@@ -1,6 +1,6 @@
1
1
  import { EventEmitter } from 'events';
2
2
  import { ServerResponse } from 'node:http';
3
- import { Event, ProtectRuleMode, Rule } from './constants';
3
+ import { Event, ProtectRuleMode, RouteType, Rule } from './constants';
4
4
  export interface Installable {
5
5
  install(...args: any[]): void | Promise<void>;
6
6
  uninstall?(): void | Promise<void>;
@@ -335,6 +335,10 @@ export interface RouteInfo {
335
335
  * @example "get"
336
336
  */
337
337
  method?: string;
338
+ /**
339
+ * The type of route that is being reported. Default should be RouteType.HTTP.
340
+ */
341
+ type: RouteType;
338
342
  /**
339
343
  * URL for a route.
340
344
  * @example "prefix/route/path"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrast/common",
3
- "version": "1.37.0",
3
+ "version": "1.38.0",
4
4
  "description": "Shared constants and utilities for all Contrast Agent modules",
5
5
  "license": "UNLICENSED",
6
6
  "author": "Contrast Security <nodejs@contrastsecurity.com> (https://www.contrastsecurity.com)",
@@ -106,6 +106,7 @@ const mappings = {
106
106
  }
107
107
  },
108
108
  'assess.probabilistic_sampling.window_ms': (remoteData) => remoteData.assess?.sampling?.window_ms,
109
+ 'assess.report_middleware_routes': (remoteData) => remoteData.assess?.report_middleware_routes,
109
110
  'assess.stacktraces': (remoteData) => remoteData.assess?.report_stacktraces,
110
111
  'agent.logger.level': coerceLowerCase('logger.level'),
111
112
  'agent.logger.path': (remoteData) => remoteData.logger?.path,
@@ -699,7 +699,13 @@ Example - \`label1, label2, label3\``,
699
699
  fn: split,
700
700
  desc: 'Define a list of Protect rules to disable in the agent. The rules must be formatted as a comma-delimited list.',
701
701
  },
702
-
702
+ {
703
+ name: 'assess.report_middleware_routes',
704
+ arg: '[false]',
705
+ default: false,
706
+ fn: castBoolean,
707
+ desc: 'Set to `true` to report both discovered and observed routes for middleware to the Contrast backend.',
708
+ },
703
709
  {
704
710
  name: 'assess.safe_positives.enable',
705
711
  arg: '[false]',
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrast/config",
3
- "version": "1.53.0",
3
+ "version": "1.54.0",
4
4
  "description": "An API for discovering Contrast agent configuration data",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Contrast Security <nodejs@contrastsecurity.com> (https://www.contrastsecurity.com)",
@@ -20,8 +20,8 @@
20
20
  "test": "bash ../scripts/test.sh"
21
21
  },
22
22
  "dependencies": {
23
- "@contrast/common": "1.37.0",
24
- "@contrast/core": "1.58.0",
23
+ "@contrast/common": "1.38.0",
24
+ "@contrast/core": "1.59.0",
25
25
  "deepmerge": "^4.3.1",
26
26
  "yaml": "^2.2.2"
27
27
  }