@contrast/agent 4.16.2 → 4.18.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 (147) hide show
  1. package/esm.mjs +21 -11
  2. package/lib/assess/policy/propagators.json +4 -0
  3. package/lib/assess/policy/signatures.json +5 -0
  4. package/lib/assess/propagators/fastify-static/allowed-path.js +85 -0
  5. package/lib/assess/sources/index.js +26 -5
  6. package/lib/cli-rewriter/index.js +1 -1
  7. package/lib/contrast.js +1 -1
  8. package/lib/core/config/options.js +14 -1
  9. package/lib/core/config/util.js +39 -11
  10. package/lib/core/rewrite/index.js +2 -2
  11. package/lib/protect/service.js +2 -0
  12. package/lib/util/trace-util.js +5 -4
  13. package/node_modules/@colors/colors/LICENSE +26 -0
  14. package/node_modules/@colors/colors/README.md +219 -0
  15. package/node_modules/@colors/colors/examples/normal-usage.js +83 -0
  16. package/node_modules/@colors/colors/examples/safe-string.js +80 -0
  17. package/node_modules/@colors/colors/index.d.ts +136 -0
  18. package/node_modules/@colors/colors/lib/colors.js +211 -0
  19. package/node_modules/@colors/colors/lib/custom/trap.js +46 -0
  20. package/node_modules/@colors/colors/lib/custom/zalgo.js +110 -0
  21. package/node_modules/@colors/colors/lib/extendStringPrototype.js +110 -0
  22. package/node_modules/@colors/colors/lib/index.js +13 -0
  23. package/node_modules/@colors/colors/lib/maps/america.js +10 -0
  24. package/node_modules/@colors/colors/lib/maps/rainbow.js +12 -0
  25. package/node_modules/@colors/colors/lib/maps/random.js +11 -0
  26. package/node_modules/@colors/colors/lib/maps/zebra.js +5 -0
  27. package/node_modules/@colors/colors/lib/styles.js +95 -0
  28. package/node_modules/@colors/colors/lib/system/has-flag.js +35 -0
  29. package/node_modules/@colors/colors/lib/system/supports-colors.js +151 -0
  30. package/node_modules/@colors/colors/package.json +49 -0
  31. package/node_modules/@colors/colors/safe.d.ts +48 -0
  32. package/node_modules/@colors/colors/safe.js +10 -0
  33. package/node_modules/@colors/colors/themes/generic-logging.js +12 -0
  34. package/node_modules/@dabh/diagnostics/README.md +16 -16
  35. package/node_modules/@dabh/diagnostics/package.json +9 -9
  36. package/node_modules/color/README.md +9 -0
  37. package/node_modules/color/index.js +4 -1
  38. package/node_modules/color/package.json +8 -8
  39. package/node_modules/color-string/README.md +6 -2
  40. package/node_modules/color-string/index.js +21 -13
  41. package/node_modules/color-string/package.json +4 -4
  42. package/node_modules/colorspace/package.json +5 -5
  43. package/node_modules/fecha/dist/fecha.min.js +1 -1
  44. package/node_modules/fecha/dist/fecha.min.js.map +1 -0
  45. package/node_modules/fecha/lib/fecha.d.ts +2 -2
  46. package/node_modules/fecha/lib/fecha.js +35 -18
  47. package/node_modules/fecha/lib/fecha.js.map +1 -0
  48. package/node_modules/fecha/lib/fecha.umd.js +35 -18
  49. package/node_modules/fecha/lib/fecha.umd.js.map +1 -0
  50. package/node_modules/fecha/package.json +9 -10
  51. package/node_modules/fecha/src/fecha.ts +524 -0
  52. package/node_modules/logform/.eslintrc +1 -1
  53. package/node_modules/logform/CHANGELOG.md +24 -0
  54. package/node_modules/logform/README.md +15 -17
  55. package/node_modules/logform/browser.js +3 -1
  56. package/node_modules/logform/cli.js +1 -1
  57. package/node_modules/logform/colorize.js +2 -2
  58. package/node_modules/logform/dist/browser.js +8 -2
  59. package/node_modules/logform/dist/cli.js +2 -2
  60. package/node_modules/logform/dist/colorize.js +5 -5
  61. package/node_modules/logform/dist/errors.js +1 -1
  62. package/node_modules/logform/dist/format.js +9 -5
  63. package/node_modules/logform/dist/index.js +53 -20
  64. package/node_modules/logform/dist/json.js +7 -6
  65. package/node_modules/logform/dist/logstash.js +1 -1
  66. package/node_modules/logform/dist/pad-levels.js +4 -4
  67. package/node_modules/logform/dist/printf.js +1 -1
  68. package/node_modules/logform/dist/simple.js +1 -1
  69. package/node_modules/logform/dist/splat.js +2 -2
  70. package/node_modules/logform/dist/uncolorize.js +1 -1
  71. package/node_modules/logform/errors.js +1 -1
  72. package/node_modules/logform/index.d.ts +36 -0
  73. package/node_modules/logform/index.js +19 -20
  74. package/node_modules/logform/json.js +7 -7
  75. package/node_modules/logform/logstash.js +1 -1
  76. package/node_modules/logform/package.json +10 -9
  77. package/node_modules/logform/simple.js +1 -1
  78. package/node_modules/logform/uncolorize.js +1 -1
  79. package/node_modules/safe-stable-stringify/CHANGELOG.md +75 -0
  80. package/node_modules/safe-stable-stringify/LICENSE +21 -0
  81. package/node_modules/safe-stable-stringify/esm/package.json +4 -0
  82. package/node_modules/safe-stable-stringify/esm/wrapper.js +6 -0
  83. package/node_modules/safe-stable-stringify/index.d.ts +18 -0
  84. package/node_modules/safe-stable-stringify/index.js +618 -0
  85. package/node_modules/safe-stable-stringify/package.json +69 -0
  86. package/node_modules/safe-stable-stringify/readme.md +170 -0
  87. package/node_modules/safe-stable-stringify/tsconfig.json +22 -0
  88. package/node_modules/winston/LICENSE +18 -18
  89. package/node_modules/winston/README.md +1231 -1230
  90. package/node_modules/winston/dist/winston/common.js +10 -10
  91. package/node_modules/winston/dist/winston/config/index.js +17 -17
  92. package/node_modules/winston/dist/winston/container.js +46 -46
  93. package/node_modules/winston/dist/winston/create-logger.js +28 -24
  94. package/node_modules/winston/dist/winston/exception-handler.js +49 -49
  95. package/node_modules/winston/dist/winston/exception-stream.js +27 -27
  96. package/node_modules/winston/dist/winston/logger.js +152 -138
  97. package/node_modules/winston/dist/winston/profiler.js +22 -22
  98. package/node_modules/winston/dist/winston/rejection-handler.js +54 -54
  99. package/node_modules/winston/dist/winston/tail-file.js +14 -14
  100. package/node_modules/winston/dist/winston/transports/console.js +31 -31
  101. package/node_modules/winston/dist/winston/transports/file.js +101 -101
  102. package/node_modules/winston/dist/winston/transports/http.js +119 -41
  103. package/node_modules/winston/dist/winston/transports/index.js +17 -17
  104. package/node_modules/winston/dist/winston/transports/stream.js +24 -24
  105. package/node_modules/winston/dist/winston.js +91 -97
  106. package/node_modules/winston/index.d.ts +213 -193
  107. package/node_modules/winston/lib/winston/common.js +61 -61
  108. package/node_modules/winston/lib/winston/config/index.d.ts +99 -98
  109. package/node_modules/winston/lib/winston/config/index.js +35 -35
  110. package/node_modules/winston/lib/winston/container.js +114 -114
  111. package/node_modules/winston/lib/winston/create-logger.js +104 -104
  112. package/node_modules/winston/lib/winston/exception-handler.js +245 -245
  113. package/node_modules/winston/lib/winston/exception-stream.js +54 -54
  114. package/node_modules/winston/lib/winston/logger.js +676 -667
  115. package/node_modules/winston/lib/winston/profiler.js +51 -51
  116. package/node_modules/winston/lib/winston/rejection-handler.js +251 -251
  117. package/node_modules/winston/lib/winston/tail-file.js +124 -124
  118. package/node_modules/winston/lib/winston/transports/console.js +117 -117
  119. package/node_modules/winston/lib/winston/transports/file.js +695 -695
  120. package/node_modules/winston/lib/winston/transports/http.js +267 -202
  121. package/node_modules/winston/lib/winston/transports/index.d.ts +103 -100
  122. package/node_modules/winston/lib/winston/transports/index.js +56 -56
  123. package/node_modules/winston/lib/winston/transports/stream.js +63 -63
  124. package/node_modules/winston/lib/winston.js +176 -182
  125. package/node_modules/winston/node_modules/winston-transport/.babelrc +3 -0
  126. package/node_modules/winston/node_modules/winston-transport/.eslintrc +7 -0
  127. package/node_modules/winston/node_modules/winston-transport/.gitattributes +1 -0
  128. package/node_modules/winston/node_modules/winston-transport/.nyc_output/c3d7ddb9-cc26-466b-a4f6-993ad69e86f6.json +1 -0
  129. package/node_modules/winston/node_modules/winston-transport/.nyc_output/processinfo/c3d7ddb9-cc26-466b-a4f6-993ad69e86f6.json +1 -0
  130. package/node_modules/winston/node_modules/winston-transport/.nyc_output/processinfo/index.json +1 -0
  131. package/node_modules/winston/node_modules/winston-transport/CHANGELOG.md +126 -0
  132. package/node_modules/winston/node_modules/winston-transport/LICENSE +22 -0
  133. package/node_modules/winston/node_modules/winston-transport/README.md +50 -0
  134. package/node_modules/winston/node_modules/winston-transport/dist/index.js +215 -0
  135. package/node_modules/winston/node_modules/winston-transport/dist/legacy.js +116 -0
  136. package/node_modules/winston/node_modules/winston-transport/index.d.ts +39 -0
  137. package/node_modules/winston/node_modules/winston-transport/index.js +215 -0
  138. package/node_modules/winston/node_modules/winston-transport/legacy.js +119 -0
  139. package/node_modules/winston/node_modules/winston-transport/package.json +56 -0
  140. package/node_modules/winston/package.json +76 -75
  141. package/package.json +9 -6
  142. package/node_modules/@dabh/diagnostics/example.png +0 -0
  143. package/node_modules/color-string/CHANGELOG.md +0 -18
  144. package/node_modules/colorspace/test.js +0 -14
  145. package/node_modules/fecha/CHANGELOG.md +0 -67
  146. package/node_modules/logform/.travis.yml +0 -17
  147. package/node_modules/winston/CHANGELOG.md +0 -560
package/esm.mjs CHANGED
@@ -14,21 +14,22 @@ Copyright: 2022 Contrast Security, Inc
14
14
  */
15
15
  import { fileURLToPath } from 'url';
16
16
  import { createRequire } from 'module';
17
- const require = createRequire(import.meta.url);
17
+ import { promises as fs } from 'fs';
18
18
 
19
+ const require = createRequire(import.meta.url);
19
20
  const loader = require('./agent-loader.js');
21
+
20
22
  const { enabled } = await loader.init(process.argv);
21
23
  if (enabled) {
22
24
  await loader.bootstrap(process.argv);
23
25
  }
24
26
  await loader.resetArgs(process.argv[0], process.argv[1]);
25
- const { readFile } = require('fs').promises;
26
27
 
27
- const agent = require(`./lib/agent.js`);
28
- const logger = require(`./lib/core/logger/index.js`)('contrast:esm-loaders');
29
- const rewriter = require(`./lib/core/rewrite/index.js`)(agent);
30
- const helpers = require(`./lib/hooks/module/helpers.js`);
31
- const getType = require(`./lib/util/get-file-type.js`);
28
+ const agent = require('./lib/agent.js');
29
+ const logger = require('./lib/core/logger/index.js')('contrast:esm-loaders');
30
+ const rewriter = require('./lib/core/rewrite/index.js')(agent);
31
+ const helpers = require('./lib/hooks/module/helpers.js');
32
+ const getType = require('./lib/util/get-file-type.js');
32
33
 
33
34
  const loadedFromCache = new Set();
34
35
 
@@ -46,6 +47,8 @@ const loadedFromCache = new Set();
46
47
  * @returns {Promise<{ source: string | SharedArrayBuffer | Uint8Array }>}
47
48
  */
48
49
  export async function getSource(url, context, defaultGetSource) {
50
+ if (!enabled) return defaultGetSource(url, context, defaultGetSource);
51
+
49
52
  const filename = fileURLToPath(url);
50
53
  logger.debug('getSource %s', filename);
51
54
  try {
@@ -78,6 +81,9 @@ export async function getSource(url, context, defaultGetSource) {
78
81
  * @returns {Promise<{ source: string | SharedArrayBuffer | Uint8Array }>}
79
82
  */
80
83
  export async function transformSource(source, context, defaultTransformSource) {
84
+ if (!enabled)
85
+ return defaultTransformSource(source, context, defaultTransformSource);
86
+
81
87
  const filename = fileURLToPath(context.url);
82
88
  logger.debug('transformSource %s', filename);
83
89
  let result;
@@ -99,11 +105,11 @@ export async function transformSource(source, context, defaultTransformSource) {
99
105
  }
100
106
 
101
107
  /**
102
- * For Node 16 and above, the 'getFormat', 'getSource' and 'transformSource' have been
108
+ * For Node 16 and above, the 'getFormat', 'getSource' and 'transformSource' have been
103
109
  * consolidated into one 'load' hook. The logic is similar to that of transformSource
104
110
  * except that the source is not provided and must be either read in from the file provided
105
111
  * or accessed from the cache.
106
- *
112
+ *
107
113
  * @see https://nodejs.org/dist/latest-v16.x/docs/api/esm.html#loadurl-context-defaultload
108
114
  * @param {string} url
109
115
  * @param {{ format: string, url: string }} context
@@ -111,6 +117,8 @@ export async function transformSource(source, context, defaultTransformSource) {
111
117
  * @returns {Promise<{ format: string, source: string | SharedArrayBuffer | Uint8Array }>}
112
118
  */
113
119
  export async function load(url, context, defaultLoad) {
120
+ if (!enabled) return defaultLoad(url, context, defaultLoad);
121
+
114
122
  const type = getType(url);
115
123
 
116
124
  if (type === 'builtin' || type === 'unknown') {
@@ -130,8 +138,10 @@ export async function load(url, context, defaultLoad) {
130
138
  if (cached) {
131
139
  result = { code: cached };
132
140
  } else {
133
- const source = await readFile(filename, 'utf8');
134
- result = rewriter.rewriteFile(source, filename, { sourceType: type === 'commonjs' ? 'script' : 'module' });
141
+ const source = await fs.readFile(filename, 'utf8');
142
+ result = rewriter.rewriteFile(source, filename, {
143
+ sourceType: type === 'commonjs' ? 'script' : 'module',
144
+ });
135
145
  helpers.cacheWithSourceMap(agent, filename, result);
136
146
  }
137
147
  return { format: type, source: result.code };
@@ -532,6 +532,10 @@
532
532
  "v8": {
533
533
  "enabled": true,
534
534
  "override": "./propagators/v8/init-hooks.js"
535
+ },
536
+ "fastify-plugin": {
537
+ "enabled": true,
538
+ "override": "./propagators/fastify-static/allowed-path.js"
535
539
  }
536
540
  }
537
541
  }
@@ -1367,6 +1367,11 @@
1367
1367
  "moduleName": "Number",
1368
1368
  "methodName": "isNaN",
1369
1369
  "isModule": false
1370
+ },
1371
+ "fastify-static.allowedPath": {
1372
+ "moduleName": "fastify-static",
1373
+ "methodName": "allowedPath",
1374
+ "isModule": false
1370
1375
  }
1371
1376
  }
1372
1377
  }
@@ -0,0 +1,85 @@
1
+ /**
2
+ Copyright: 2022 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 logger = require('../../../core/logger')('contrast:validator:propagator');
18
+ const patcher = require('../../../hooks/patcher');
19
+ const requireHook = require('../../../hooks/require');
20
+ const { PATCH_TYPES } = require('../../../constants');
21
+ const agent = require('../../../agent');
22
+ const tracker = require('../../../tracker');
23
+ const tagRangeUtil = require('../../models/tag-range/util');
24
+ const TagRange = require('../../models/tag-range');
25
+ const { CallContext, PropagationEvent, Signature } = require('../../models');
26
+
27
+ module.exports.handle = function handle() {
28
+ requireHook.resolve(
29
+ { name: 'fastify-plugin', file: 'plugin' },
30
+ (fastifyPlugin) => (patcher.patch(fastifyPlugin, {
31
+ name: 'fastify-plugin',
32
+ patchType: PATCH_TYPES.ASSESS_PROPAGATOR,
33
+ alwaysRun: true,
34
+ pre: ({ args }) => {
35
+ if ((typeof args[0] == 'function') && args[1] && (args[1].name === 'fastify-static')) {
36
+ const fastifyStatic = args[0];
37
+
38
+ args[0] = patcher.patch(fastifyStatic, {
39
+ name: 'fastify-static',
40
+ patchType: PATCH_TYPES.ASSESS_PROPAGATOR,
41
+ alwaysRun: true,
42
+ pre: ({ args: preArgs }) => {
43
+ if (preArgs[1] && preArgs[1].allowedPath) {
44
+ const { allowedPath } = preArgs[1];
45
+
46
+ preArgs[1].allowedPath = patcher.patch(allowedPath, {
47
+ name: 'allowed-path',
48
+ patchType: PATCH_TYPES.ASSESS_PROPAGATOR,
49
+ alwaysRun: true,
50
+ post: (data) => {
51
+ if (data.result && agent.config.assess.trust_custom_validators) {
52
+ const trackingData = tracker.getData(data.args[0]);
53
+
54
+ if (trackingData) {
55
+ logger.trace('hooking fastify-static/index');
56
+ tagRangeUtil.addInPlace(
57
+ trackingData.tagRanges,
58
+ new TagRange(0, data.args[0].length - 1, 'exclusion:path-traversal')
59
+ );
60
+ tagRangeUtil.removeInPlace(trackingData.tagRanges, ['untrusted']);
61
+
62
+ const context = new CallContext(data);
63
+ const event = new PropagationEvent({
64
+ context,
65
+ signature: new Signature('fastify-static.allowedPath'),
66
+ tagRanges: trackingData.tagRanges,
67
+ source: 'O',
68
+ target: 'R'
69
+ });
70
+
71
+ event.parents.push(trackingData.event);
72
+ trackingData.event = event;
73
+ }
74
+ }
75
+ }
76
+ });
77
+ }
78
+ }
79
+ });
80
+ }
81
+ },
82
+ }))
83
+
84
+ );
85
+ };
@@ -55,6 +55,25 @@ sources.track = function(type, parent, key, membrane) {
55
55
  parent[key] = membrane.wrap(object, metadata);
56
56
  };
57
57
 
58
+ /**
59
+ * Chooses a strategy for tracking the source events
60
+ * @param {any} config Current configuration for the agent
61
+ * @param {Logger} logger A logger instance
62
+ * @returns {Boolean} whether lazy tracking is enabled or not
63
+ */
64
+ sources.getLazyTrackingConfig = function(config, logger) {
65
+ if (config._default['agent.traverse_and_track']) {
66
+ return config.assess.enable_lazy_tracking;
67
+ }
68
+ if (config._default['assess.enable_lazy_tracking']) {
69
+ logger.error('agent.traverse_and_track option is deprecated. Please use assess.enable_lazy_tracking from now on. It\'s value should be the opposite of this one');
70
+ return !config.agent.traverse_and_track;
71
+ }
72
+
73
+ logger.error('Conflicting options set: `agent.traverse_and_track` and `assess.enable_lazy_tracking`. `agent.traverse_and_track` is deprecated, so `assess.enable_lazy_tracking` takes precedence');
74
+ return config.assess.enable_lazy_tracking;
75
+ };
76
+
58
77
  /**
59
78
  * Registers an event to add URL and input exclusions to async storage if they
60
79
  * pertain to the current request path. Also registers all the source events
@@ -62,8 +81,10 @@ sources.track = function(type, parent, key, membrane) {
62
81
  * object in a membrane
63
82
  */
64
83
  sources.registerListeners = function({ config, exclusions }) {
84
+ const isLazyTrackingEnabled = sources.getLazyTrackingConfig(config, logger);
85
+
65
86
  agentEmitter.on('assess.body', (obj, prop) => {
66
- if (!config.agent.traverse_and_track) {
87
+ if (isLazyTrackingEnabled) {
67
88
  return sources.handleSourceEvent(config, exclusions, BODY, obj, prop);
68
89
  }
69
90
 
@@ -77,7 +98,7 @@ sources.registerListeners = function({ config, exclusions }) {
77
98
  });
78
99
  });
79
100
  agentEmitter.on('assess.headers', (obj, prop) => {
80
- if (!config.agent.traverse_and_track) {
101
+ if (isLazyTrackingEnabled) {
81
102
  return sources.handleSourceEvent(config, exclusions, HEADER, obj, prop);
82
103
  }
83
104
 
@@ -89,7 +110,7 @@ sources.registerListeners = function({ config, exclusions }) {
89
110
  });
90
111
  });
91
112
  agentEmitter.on('assess.params', (obj, prop) => {
92
- if (!config.agent.traverse_and_track) {
113
+ if (isLazyTrackingEnabled) {
93
114
  return sources.handleSourceEvent(
94
115
  config,
95
116
  exclusions,
@@ -107,7 +128,7 @@ sources.registerListeners = function({ config, exclusions }) {
107
128
  });
108
129
  });
109
130
  agentEmitter.on('assess.query', (obj, prop) => {
110
- if (!config.agent.traverse_and_track) {
131
+ if (isLazyTrackingEnabled) {
111
132
  return sources.handleSourceEvent(
112
133
  config,
113
134
  exclusions,
@@ -126,7 +147,7 @@ sources.registerListeners = function({ config, exclusions }) {
126
147
  });
127
148
 
128
149
  agentEmitter.on('assess.cookies', (obj, prop) => {
129
- if (!config.agent.traverse_and_track) {
150
+ if (isLazyTrackingEnabled) {
130
151
  return sources.handleSourceEvent(config, exclusions, COOKIE, obj, prop);
131
152
  }
132
153
 
@@ -215,7 +215,7 @@ class CLIRewriter {
215
215
 
216
216
  const content = await readFile(filename, 'utf8');
217
217
  const rewriteData = this.rewriter.rewriteFile(content, filename, {
218
- sourceType: type
218
+ sourceType: type === 'commonjs' ? 'script' : 'module'
219
219
  });
220
220
 
221
221
  if (rewriteData.code) {
package/lib/contrast.js CHANGED
@@ -223,7 +223,7 @@ contrastAgent.prepare = function(...args) {
223
223
  // optionally enable metric collection
224
224
  require('./core/metrics').configure(config);
225
225
 
226
- if (agent.cluster.isPrimary) {
226
+ if (config.enable && agent.cluster.isPrimary) {
227
227
  contrastAgent.showBanner();
228
228
  }
229
229
 
@@ -476,7 +476,13 @@ const agent = [
476
476
  name: 'agent.traverse_and_track',
477
477
  arg: '<traverse-and-track>',
478
478
  default: false,
479
- desc: 'source membrane alternative',
479
+ fn: (val, logger) => {
480
+ if (val) {
481
+ logger.error('agent.traverse_and_track option is deprecated. Please use assess.enable_lazy_tracking from now on. It\'s value should be the opposite of this one');
482
+ }
483
+ return val;
484
+ },
485
+ desc: 'source membrane alternative (DEPRECATED)',
480
486
  },
481
487
  {
482
488
  name: 'agent.polling.app_activity_ms',
@@ -747,6 +753,13 @@ const assess = [
747
753
  arg: '<tags>',
748
754
  desc: 'comma-separated list of tags to apply to each application vulnerability reported by the agent',
749
755
  },
756
+ {
757
+ name: 'assess.enable_lazy_tracking',
758
+ arg: '[true]',
759
+ default: true,
760
+ fn: castBoolean,
761
+ desc: 'When set to `false` won\'t track the source events lazily but will track the first up to 250 source events',
762
+ },
750
763
  ];
751
764
 
752
765
  const protect = [
@@ -72,8 +72,8 @@ class Config {
72
72
  assess: {},
73
73
  protect: {},
74
74
  server: {},
75
- dev: {}
76
- }
75
+ dev: {},
76
+ },
77
77
  };
78
78
  }
79
79
 
@@ -146,9 +146,10 @@ class Config {
146
146
  * @return {string|void} path, if valid
147
147
  */
148
148
  function checkConfigPath() {
149
- const configDir = os.platform() === 'win32'
150
- ? `${process.env['ProgramData']}\\contrast`
151
- : '/etc/contrast';
149
+ const configDir =
150
+ os.platform() === 'win32'
151
+ ? `${process.env['ProgramData']}\\contrast`
152
+ : '/etc/contrast';
152
153
 
153
154
  for (const dir of [process.cwd(), configDir]) {
154
155
  const checkPath = path.resolve(dir, 'contrast_security.yaml');
@@ -159,7 +160,6 @@ function checkConfigPath() {
159
160
  return;
160
161
  }
161
162
 
162
-
163
163
  /**
164
164
  * @param {Object} cliOptions
165
165
  * @param {string} cliOptions.script
@@ -202,7 +202,7 @@ function readConfig(cliOptions, logger) {
202
202
  // parse yaml and JSON separately.
203
203
  try {
204
204
  config = yaml.parse(fileContents, {
205
- prettyErrors: true
205
+ prettyErrors: true,
206
206
  });
207
207
  } catch (e) {
208
208
  logger.error(
@@ -264,7 +264,7 @@ function mergeCliOptions(cliOptions, logger) {
264
264
  enum: optEnum,
265
265
  fn = _.identity,
266
266
  name,
267
- required
267
+ required,
268
268
  } = option;
269
269
 
270
270
  const env = process.env[option.env];
@@ -294,7 +294,7 @@ function mergeCliOptions(cliOptions, logger) {
294
294
  // set from default
295
295
  if (value === undefined) {
296
296
  if (required) {
297
- logger.error('Missing required option \'%s\'', name);
297
+ logger.error("Missing required option '%s'", name);
298
298
  return options;
299
299
  }
300
300
 
@@ -307,10 +307,38 @@ function mergeCliOptions(cliOptions, logger) {
307
307
  }, new Config());
308
308
  }
309
309
 
310
+ /**
311
+ * When you run an appliaction with pm2 on cluster mode, pm2 attaches the
312
+ * process.env to a property pm2_env(only for the agent since we start it with -r flag), so
313
+ * the function checks if there is pm2_env property and merge contrast
314
+ * related properties to process.env
315
+ */
316
+ function mergePM2Envs() {
317
+ if (!process.env.pm2_env) return;
318
+
319
+ const pm2_env = JSON.parse(process.env.pm2_env);
320
+
321
+ const contrastEnvs = ['DEBUG', 'PGHOST', 'PGPORT'];
322
+ const objectEntries = Object.entries(pm2_env.env)
323
+ .concat(Object.entries(pm2_env))
324
+ .concat(['DEBUG', 'PGHOST', 'PGPORT']);
325
+
326
+ objectEntries.forEach(([key, value]) => {
327
+ if (
328
+ !process.env[key] &&
329
+ (key.toLocaleLowerCase().includes('contrast') ||
330
+ contrastEnvs.includes(key))
331
+ ) {
332
+ process.env[key] = value;
333
+ }
334
+ });
335
+ }
336
+
310
337
  util.Config = Config;
311
338
  util.setup = function setup(cliOptions, logger) {
312
- const mergedCliOptions = mergeCliOptions(cliOptions, logger);
339
+ mergePM2Envs();
313
340
 
341
+ const mergedCliOptions = mergeCliOptions(cliOptions, logger);
314
342
  mergedCliOptions.script = cliOptions.script;
315
343
  mergedCliOptions.configFile = cliOptions.configFile;
316
344
  mergedCliOptions.validate();
@@ -323,7 +351,7 @@ util.logConfig = function logConfig(mergedConfig, logger) {
323
351
  'Current Configuration: %s',
324
352
  stringify(mergedConfig._flat, {
325
353
  replacer: (k, v) => (v == undefined ? null : v),
326
- space: 2
354
+ space: 2,
327
355
  })
328
356
  );
329
357
  };
@@ -27,7 +27,7 @@ const BinaryExpression = require('./binary-expression');
27
27
  const CallExpression = require('./call-expression');
28
28
  const CatchClause = require('./catch-clause');
29
29
  const functionWrap = require('./function-wrap');
30
- const ImportDeclaration = require('./import-declaration');
30
+ // const ImportDeclaration = require('./import-declaration');
31
31
  const isContrastMethod = require('./is-contrast-method');
32
32
  const logRewrite = require('./log');
33
33
  const MemberExpression = require('./member-expression');
@@ -106,7 +106,7 @@ class Rewriter {
106
106
  BinaryExpression,
107
107
  CallExpression,
108
108
  CatchClause,
109
- ImportDeclaration,
109
+ // ImportDeclaration, disabled since we're not yet utilizing this.
110
110
  MemberExpression,
111
111
  ObjectProperty,
112
112
  SwitchStatement,
@@ -202,9 +202,11 @@ class ProtectService {
202
202
  headers: req.rawHeaders.map((h, ix) => (ix & 1 ? h : h.toLowerCase()))
203
203
  };
204
204
 
205
+ arg.uriPath = req.url;
205
206
  const questionMark = req.url.indexOf('?');
206
207
  if (questionMark >= 0) {
207
208
  arg.queries = req.url.slice(questionMark + 1);
209
+ arg.uriPath = req.url.slice(0, questionMark);
208
210
  }
209
211
 
210
212
  const findings = this.agentLib.scoreRequestConnect(rules, arg, evalOptions);
@@ -46,12 +46,13 @@ function getRequest(agent, ruleId) {
46
46
  }
47
47
 
48
48
  const ruleCount = context.rules[ruleId];
49
-
50
49
  const { sampling } = agent.config.assess;
51
- if (sampling && sampling.enable && ruleCount < sampling.baseline) {
52
- context.rules[ruleId]++;
53
- return request;
50
+ if (sampling && sampling.enable && ruleCount >= sampling.baseline) {
51
+ return;
54
52
  }
53
+
54
+ context.rules[ruleId]++;
55
+ return request;
55
56
  }
56
57
 
57
58
  /**
@@ -0,0 +1,26 @@
1
+ MIT License
2
+
3
+ Original Library
4
+ - Copyright (c) Marak Squires
5
+
6
+ Additional Functionality
7
+ - Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
8
+ - Copyright (c) DABH (https://github.com/DABH)
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in
18
+ all copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26
+ THE SOFTWARE.