@contrast/agent 4.10.4 → 4.11.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.
package/bin/VERSION CHANGED
@@ -1 +1 @@
1
- 2.28.12
1
+ 2.28.13
Binary file
Binary file
Binary file
package/esm.mjs CHANGED
@@ -24,13 +24,45 @@ if (enabled) {
24
24
  await loader.resetArgs(process.argv[0], process.argv[1]);
25
25
  const { readFile } = require('fs').promises;
26
26
 
27
+ const path = require('path');
27
28
  const agent = require(`./lib/agent.js`);
28
29
  const logger = require(`./lib/core/logger/index.js`)('contrast:esm-loaders');
29
30
  const rewriter = require(`./lib/core/rewrite/index.js`)(agent);
30
31
  const helpers = require(`./lib/hooks/module/helpers.js`);
32
+ const parent = require('parent-package-json');
31
33
 
32
34
  const loadedFromCache = new Set();
33
35
 
36
+ function getType(url) {
37
+ const {protocol, pathname} = new URL(url);
38
+
39
+ let parentType = 'commonjs';
40
+ try {
41
+ parentType = parent(pathname).parse().type;
42
+ } catch (err) {
43
+ // Node assumes `commonjs ` if there's no `type` set in package.json
44
+ }
45
+
46
+ if (protocol === 'node:') {
47
+ return 'builtin';
48
+ }
49
+ if (protocol === 'file:') {
50
+ const ext = path.extname(pathname);
51
+ if (
52
+ ext === '.mjs' ||
53
+ (ext === '.js' && parentType === 'module')
54
+ ){
55
+ return 'module';
56
+ }
57
+ else if (
58
+ ext === '.cjs' ||
59
+ (ext === '.js' && parentType !== 'module')
60
+ ){
61
+ return 'commonjs';
62
+ }
63
+ }
64
+ return 'unknown';
65
+ }
34
66
  /**
35
67
  * The `getSource` hook is used to provide a custom method for retrieving source
36
68
  * code. In our case, we check for previously rewritten ESM files in our cache
@@ -110,15 +142,25 @@ export async function transformSource(source, context, defaultTransformSource) {
110
142
  * @returns {Promise<{ format: string, source: string | SharedArrayBuffer | Uint8Array }>}
111
143
  */
112
144
  export async function load(url, context, defaultLoad) {
145
+ const type = getType(url);
146
+
147
+ if (type === 'builtin' || type === 'unknown') {
148
+ logger.debug(
149
+ 'Skipping rewrite for %s module %s, loading original code',
150
+ type,
151
+ url
152
+ );
153
+ return defaultLoad(url, context, defaultLoad);
154
+ }
155
+
113
156
  const filename = fileURLToPath(url);
114
157
 
115
158
  try {
116
159
  const cached = helpers.find(agent, filename);
117
160
  const source = cached || await readFile(filename, 'utf8');
118
- const result = rewriter.rewriteFile(source, filename, { sourceType: 'module' });
161
+ const result = rewriter.rewriteFile(source, filename, { sourceType: type === 'commonjs' ? 'script' : 'module' });
119
162
  helpers.cacheWithSourceMap(agent, filename, result);
120
- return { format: context.format, source: result.code };
121
-
163
+ return { format: type, source: result.code };
122
164
  } catch (err) {
123
165
  logger.error(
124
166
  'Failed to load rewritten code for %s, err: %o, rewritten code %s, loading original code.',
@@ -12,10 +12,12 @@ Copyright: 2022 Contrast Security, Inc
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
+ 'use strict';
16
+
15
17
  const requireHook = require('../../../hooks/require');
16
18
  const patcher = require('../../../hooks/patcher');
17
19
  const {
18
- PATCH_TYPES: { ASSESS_PROPAGATOR }
20
+ PATCH_TYPES: { ASSESS_PROPAGATOR },
19
21
  } = require('../../../constants');
20
22
  const tracker = require('../../../tracker');
21
23
  const agent = require('../../../agent');
@@ -23,18 +25,15 @@ const agent = require('../../../agent');
23
25
  requireHook.resolve(
24
26
  { name: 'joi', file: 'lib/types/any.js', version: '>=17.0.0' },
25
27
  (object) => {
26
- if (
27
- !agent.config ||
28
- (agent.config && !agent.config.agent.trust_custom_validators)
29
- ) {
30
- return;
31
- }
28
+ if (!agent.config) return;
32
29
 
33
30
  patcher.patch(object._definition.rules.custom, 'validate', {
34
31
  name: 'joi.any.custom.validate',
35
32
  patchType: ASSESS_PROPAGATOR,
36
33
  alwaysRun: true,
37
34
  post(data) {
35
+ if (!agent.config.agent.trust_custom_validators) return;
36
+
38
37
  if (data.result && typeof data.result === 'string') {
39
38
  tracker.untrack(data.result);
40
39
  }
@@ -42,7 +41,7 @@ requireHook.resolve(
42
41
  if (data.args[0] && typeof data.args[0] === 'string') {
43
42
  tracker.untrack(data.args[0]);
44
43
  }
45
- }
44
+ },
46
45
  });
47
- }
46
+ },
48
47
  );
@@ -12,10 +12,12 @@ Copyright: 2022 Contrast Security, Inc
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
+ 'use strict';
16
+
15
17
  const requireHook = require('../../../hooks/require');
16
18
  const patcher = require('../../../hooks/patcher');
17
19
  const {
18
- PATCH_TYPES: { ASSESS_PROPAGATOR }
20
+ PATCH_TYPES: { ASSESS_PROPAGATOR },
19
21
  } = require('../../../constants');
20
22
  const tracker = require('../../../tracker');
21
23
  const agent = require('../../../agent');
@@ -40,22 +42,19 @@ const traverseObjectAndUntrack = (object, incomingInput, result) => {
40
42
  requireHook.resolve(
41
43
  { name: 'joi', file: 'lib/types/object.js', version: '>=17.0.0' },
42
44
  (object) => {
43
- if (
44
- !agent.config ||
45
- (agent.config && !agent.config.agent.trust_custom_validators)
46
- ) {
47
- return;
48
- }
45
+ if (!agent.config) return;
49
46
 
50
47
  patcher.patch(object.__proto__, 'validateAsync', {
51
48
  name: 'joi.object.validateAsync',
52
49
  patchType: ASSESS_PROPAGATOR,
53
50
  alwaysRun: true,
54
51
  post(data) {
52
+ if (!agent.config.agent.trust_custom_validators) return;
53
+
55
54
  data.result.then((result) =>
56
- traverseObjectAndUntrack(data.obj, data.args[0], result)
55
+ traverseObjectAndUntrack(data.obj, data.args[0], result),
57
56
  );
58
- }
57
+ },
59
58
  });
60
- }
59
+ },
61
60
  );
@@ -18,7 +18,7 @@ const _ = require('lodash');
18
18
  const requireHook = require('../../../hooks/require');
19
19
  const patcher = require('../../../hooks/patcher');
20
20
  const {
21
- PATCH_TYPES: { ASSESS_PROPAGATOR }
21
+ PATCH_TYPES: { ASSESS_PROPAGATOR },
22
22
  } = require('../../../constants');
23
23
  const tracker = require('../../../tracker');
24
24
  const { PropagationEvent, Signature, CallContext } = require('../../models');
@@ -42,7 +42,7 @@ function instrumentJoiString(string) {
42
42
  const { event } = trackingData;
43
43
  trackingData.tagRanges = tagRangeUtil.add(
44
44
  trackingData.tagRanges,
45
- new TagRange(0, data.args[0].length - 1, 'string-type-checked')
45
+ new TagRange(0, data.args[0].length - 1, 'string-type-checked'),
46
46
  );
47
47
  trackingData.event = new PropagationEvent({
48
48
  context: new CallContext(data),
@@ -50,29 +50,32 @@ function instrumentJoiString(string) {
50
50
  tagRanges: trackingData.tagRanges,
51
51
  source: 'P',
52
52
  target: 'A',
53
- parents: [event]
53
+ parents: [event],
54
54
  });
55
55
  }
56
- }
56
+ },
57
57
  });
58
58
 
59
- if (agent.config.agent.trust_custom_validators) {
60
- patcher.patch(string.__proto__, 'validateAsync', {
61
- name: 'joi.string.validateAsync',
62
- patchType: ASSESS_PROPAGATOR,
63
- alwaysRun: true,
64
- post(data) {
65
- if (!data.obj.$_terms.externals.length) return;
66
- data.result.then((result) => {
67
- tracker.untrack(data.args[0]);
68
- tracker.untrack(result);
69
- });
70
- }
71
- });
72
- }
59
+ patcher.patch(string.__proto__, 'validateAsync', {
60
+ name: 'joi.string.validateAsync',
61
+ patchType: ASSESS_PROPAGATOR,
62
+ alwaysRun: true,
63
+ post(data) {
64
+ if (
65
+ !data.obj.$_terms.externals.length ||
66
+ !agent.config.agent.trust_custom_validators
67
+ )
68
+ return;
69
+
70
+ data.result.then((result) => {
71
+ tracker.untrack(data.args[0]);
72
+ tracker.untrack(result);
73
+ });
74
+ },
75
+ });
73
76
  }
74
77
 
75
78
  requireHook.resolve(
76
79
  { name: 'joi', file: 'lib/types/string.js', version: '>=17.0.0' },
77
- instrumentJoiString
80
+ instrumentJoiString,
78
81
  );
@@ -67,7 +67,7 @@ class Handler {
67
67
 
68
68
  patchRethinkDb(rethinkdb) {
69
69
  const self = this;
70
- patcher.patch(rethinkdb, 'table', {
70
+ patcher.patch(rethinkdb, 'db', {
71
71
  name: moduleName,
72
72
  patchType: PATCH_TYPES.ASSESS_SINK,
73
73
  alwaysRun: true,
@@ -13,6 +13,7 @@ Copyright: 2022 Contrast Security, Inc
13
13
  way not consistent with the End User License Agreement.
14
14
  */
15
15
  'use strict';
16
+
16
17
  const logger = require('../logger')('contrast:arch-component');
17
18
  const agentEmitter = require('../../agent-emitter');
18
19
  const { PATCH_TYPES } = require('../../constants');
@@ -31,11 +32,14 @@ ModuleHook.resolve({ name: 'aws-sdk' }, (AWS) => {
31
32
  vendor: 'DynamoDB',
32
33
  url: new URL(`${endpoint.protocol}//${endpoint.hostname}`).toString(),
33
34
  remoteHost: '',
34
- remotePort: endpoint.port
35
+ remotePort: endpoint.port,
35
36
  });
36
37
  } catch (err) {
37
- logger.warn('unable to report DynamoDB architecture component\n', err);
38
+ logger.warn(
39
+ 'unable to report DynamoDB architecture component, err: %o',
40
+ err,
41
+ );
38
42
  }
39
- }
43
+ },
40
44
  });
41
45
  });
@@ -13,6 +13,7 @@ Copyright: 2022 Contrast Security, Inc
13
13
  way not consistent with the End User License Agreement.
14
14
  */
15
15
  'use strict';
16
+
16
17
  const logger = require('../logger')('contrast:arch-component');
17
18
  const agentEmitter = require('../../agent-emitter');
18
19
  const { PATCH_TYPES } = require('../../constants');
@@ -24,7 +25,7 @@ function emitArchitectureComponent(endpoint) {
24
25
  vendor: 'DynamoDB',
25
26
  url: new URL(`${endpoint.protocol}//${endpoint.hostname}`).toString(),
26
27
  remoteHost: '',
27
- remotePort: endpoint.port
28
+ remotePort: endpoint.port,
28
29
  });
29
30
  }
30
31
 
@@ -37,8 +38,11 @@ ModuleHook.resolve({ name: '@aws-sdk/client-dynamodb' }, (AWS) => {
37
38
  try {
38
39
  this.config.endpoint().then(emitArchitectureComponent);
39
40
  } catch (err) {
40
- logger.warn('unable to report DynamoDB architecture component\n', err);
41
+ logger.warn(
42
+ 'unable to report DynamoDB architecture component, err: %o',
43
+ err,
44
+ );
41
45
  }
42
- }
46
+ },
43
47
  });
44
48
  });
@@ -12,6 +12,8 @@ Copyright: 2022 Contrast Security, Inc
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
+ 'use strict';
16
+
15
17
  require('./mongodb');
16
18
  require('./mysql');
17
19
  require('./sqlite3');
@@ -33,7 +33,7 @@ ModuleHook.resolve(
33
33
  }
34
34
 
35
35
  // We should report only when connection is successful
36
- ctx.result.then(function(client) {
36
+ ctx.result.then(function (client) {
37
37
  try {
38
38
  const { servers = [] } = ctx.obj.s && ctx.obj.s.options;
39
39
  for (const server of servers) {
@@ -41,17 +41,17 @@ ModuleHook.resolve(
41
41
  vendor: 'MongoDB',
42
42
  url: `mongodb://${server.host}:${server.port}`,
43
43
  remoteHost: '',
44
- remotePort: server.port
44
+ remotePort: server.port,
45
45
  });
46
46
  }
47
47
  } catch (err) {
48
48
  logger.warn(
49
- 'unable to report MongoDB architecture component\n%o',
50
- err
49
+ 'unable to report MongoDB architecture component, err: %o',
50
+ err,
51
51
  );
52
52
  }
53
53
  });
54
- }
54
+ },
55
55
  });
56
- }
56
+ },
57
57
  );
@@ -42,19 +42,22 @@ ModuleHook.resolve(
42
42
  vendor: 'MySQL',
43
43
  url: new URL(url).toString(),
44
44
  remoteHost: '',
45
- remotePort: !this.config.socketPath ? this.config.port : -1
45
+ remotePort: !this.config.socketPath ? this.config.port : -1,
46
46
  });
47
47
  } catch (err) {
48
48
  logger.warn(
49
- 'unable to report MySQL architecture component\n',
50
- err
49
+ 'unable to report MySQL architecture component, err: %o',
50
+ err,
51
51
  );
52
52
  }
53
53
  })
54
54
  .catch((err) => {
55
- logger.warn('unable to report MySQL architecture component\n', err);
55
+ logger.warn(
56
+ 'unable to report MySQL architecture component, err: %o',
57
+ err,
58
+ );
56
59
  });
57
- }
60
+ },
58
61
  });
59
- }
62
+ },
60
63
  );
@@ -13,6 +13,7 @@ Copyright: 2022 Contrast Security, Inc
13
13
  way not consistent with the End User License Agreement.
14
14
  */
15
15
  'use strict';
16
+
16
17
  const patcher = require('../../hooks/patcher');
17
18
  const ModuleHook = require('../../hooks/require');
18
19
  const agentEmitter = require('../../agent-emitter');
@@ -29,10 +30,8 @@ ModuleHook.resolve({ name: 'pg', file: 'lib/client.js' }, (pgClient) =>
29
30
  waitToConnect(wrapCtx)
30
31
  .then(() => {
31
32
  try {
32
- const {
33
- host = process.env.PGHOST,
34
- port = process.env.PGPORT
35
- } = wrapCtx.result;
33
+ const { host = process.env.PGHOST, port = process.env.PGPORT } =
34
+ wrapCtx.result;
36
35
 
37
36
  if (!host) {
38
37
  return;
@@ -51,21 +50,21 @@ ModuleHook.resolve({ name: 'pg', file: 'lib/client.js' }, (pgClient) =>
51
50
  agentEmitter.emit('architectureComponent', {
52
51
  vendor: 'PostgreSQL',
53
52
  remotePort: port || 0,
54
- url: new URL(url).toString()
53
+ url: new URL(url).toString(),
55
54
  });
56
55
  } catch (err) {
57
56
  logger.warn(
58
- 'unable to report PostgreSQL architecture component\n%o',
59
- err
57
+ 'unable to report PostgreSQL architecture component, err: %o',
58
+ err,
60
59
  );
61
60
  }
62
61
  })
63
62
  .catch((err) => {
64
63
  logger.warn(
65
- 'unable to report PostgreSQL architecture component\n%o',
66
- err
64
+ 'unable to report PostgreSQL architecture component, err: %o',
65
+ err,
67
66
  );
68
67
  });
69
- }
70
- })
68
+ },
69
+ }),
71
70
  );
@@ -36,7 +36,7 @@ ModuleHook.resolve({ name: 'rethinkdb' }, (rethinkdb) => {
36
36
  agentEmitter.emit('architectureComponent', {
37
37
  vendor: 'RethinkDB',
38
38
  url,
39
- remotePort: res.port
39
+ remotePort: res.port,
40
40
  });
41
41
  } else {
42
42
  logger.warn('unable to open RethinkDB connection');
@@ -44,10 +44,10 @@ ModuleHook.resolve({ name: 'rethinkdb' }, (rethinkdb) => {
44
44
  })
45
45
  .catch((err) => {
46
46
  logger.warn(
47
- 'unable to report RethinkDB architecture component\n%o',
48
- err
47
+ 'unable to report RethinkDB architecture component, err: %o',
48
+ err,
49
49
  );
50
50
  });
51
- }
51
+ },
52
52
  });
53
53
  });
@@ -31,11 +31,14 @@ ModuleHook.resolve({ name: 'sqlite3' }, (sqlite3) => {
31
31
  vendor: 'SQLite3',
32
32
  url: wrapCtx.args[0],
33
33
  remoteHost: '',
34
- remotePort: 0
34
+ remotePort: 0,
35
35
  });
36
36
  } catch (err) {
37
- logger.warn('unable to report SQLite3 architecture component\n%o', err);
37
+ logger.warn(
38
+ 'unable to report SQLite3 architecture component, err: %o',
39
+ err,
40
+ );
38
41
  }
39
- }
42
+ },
40
43
  });
41
44
  });
@@ -12,6 +12,8 @@ Copyright: 2022 Contrast Security, Inc
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
+ 'use strict';
16
+
15
17
  const MYSQL = 'mysql.connect.arch_component';
16
18
  const POSTGRES = 'pg.Client.arch_component';
17
19
 
@@ -19,7 +21,7 @@ module.exports = function waitToConnect(ctx, count = 0) {
19
21
  return new Promise((resolve, reject) => {
20
22
  const maxAttempts = 10 * 60; // i.e., 1 min.
21
23
  const checkConnection = setInterval(
22
- function(ctx, resolve, reject) {
24
+ function (ctx, resolve, reject) {
23
25
  if (count >= maxAttempts) {
24
26
  clearInterval(checkConnection);
25
27
  reject();
@@ -43,7 +45,7 @@ module.exports = function waitToConnect(ctx, count = 0) {
43
45
  100,
44
46
  ctx,
45
47
  resolve,
46
- reject
48
+ reject,
47
49
  );
48
50
  });
49
51
  };