@contrast/agent 4.12.1 → 4.13.1

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 (57) hide show
  1. package/bootstrap.js +2 -3
  2. package/esm.mjs +9 -35
  3. package/lib/assess/membrane/debraner.js +0 -2
  4. package/lib/assess/membrane/index.js +1 -3
  5. package/lib/assess/models/base-event.js +1 -1
  6. package/lib/assess/models/tag-range/util.js +1 -2
  7. package/lib/assess/policy/util.js +3 -2
  8. package/lib/assess/propagators/JSON/stringify.js +6 -11
  9. package/lib/assess/propagators/ajv/conditionals.js +0 -3
  10. package/lib/assess/propagators/ajv/json-schema-type-evaluators.js +5 -4
  11. package/lib/assess/propagators/ajv/refs.js +1 -2
  12. package/lib/assess/propagators/ajv/schema-context.js +2 -3
  13. package/lib/assess/propagators/path/common.js +38 -29
  14. package/lib/assess/propagators/path/resolve.js +1 -0
  15. package/lib/assess/propagators/sequelize/utils.js +1 -2
  16. package/lib/assess/propagators/v8/init-hooks.js +0 -1
  17. package/lib/assess/sinks/dynamo.js +65 -30
  18. package/lib/assess/static/hardcoded.js +3 -3
  19. package/lib/assess/static/read-findings-from-cache.js +40 -0
  20. package/lib/assess/technologies/index.js +12 -13
  21. package/lib/cli-rewriter/index.js +65 -6
  22. package/lib/core/config/options.js +6 -0
  23. package/lib/core/config/util.js +15 -33
  24. package/lib/core/exclusions/input.js +6 -1
  25. package/lib/core/express/index.js +2 -4
  26. package/lib/core/logger/debug-logger.js +2 -2
  27. package/lib/core/stacktrace.js +2 -1
  28. package/lib/hooks/http.js +81 -81
  29. package/lib/hooks/require.js +1 -0
  30. package/lib/instrumentation.js +17 -0
  31. package/lib/protect/analysis/aho-corasick.js +1 -1
  32. package/lib/protect/errors/handler-async-errors.js +66 -0
  33. package/lib/protect/input-analysis.js +7 -13
  34. package/lib/protect/listeners.js +27 -23
  35. package/lib/protect/rules/base-scanner/index.js +2 -2
  36. package/lib/protect/rules/bot-blocker/bot-blocker-rule.js +4 -2
  37. package/lib/protect/rules/cmd-injection/cmdinjection-rule.js +57 -2
  38. package/lib/protect/rules/cmd-injection-semantic-chained-commands/cmd-injection-semantic-chained-commands-rule.js +31 -2
  39. package/lib/protect/rules/cmd-injection-semantic-dangerous-paths/cmd-injection-semantic-dangerous-paths-rule.js +32 -2
  40. package/lib/protect/rules/index.js +42 -21
  41. package/lib/protect/rules/ip-denylist/ip-denylist-rule.js +2 -2
  42. package/lib/protect/rules/nosqli/nosql-injection-rule.js +104 -39
  43. package/lib/protect/rules/path-traversal/path-traversal-rule.js +3 -0
  44. package/lib/protect/rules/rule-factory.js +6 -7
  45. package/lib/protect/rules/signatures/signature.js +3 -0
  46. package/lib/protect/rules/sqli/sql-injection-rule.js +98 -5
  47. package/lib/protect/rules/sqli/sql-scanner/labels.json +0 -3
  48. package/lib/protect/rules/xss/reflected-xss-rule.js +3 -3
  49. package/lib/protect/sample-aggregator.js +65 -57
  50. package/lib/protect/service.js +709 -104
  51. package/lib/reporter/models/app-activity/sample.js +6 -0
  52. package/lib/reporter/speedracer/unknown-connection-state.js +20 -32
  53. package/lib/reporter/translations/to-protobuf/settings/assess-features.js +4 -6
  54. package/lib/reporter/ts-reporter.js +1 -1
  55. package/lib/util/get-file-type.js +43 -0
  56. package/package.json +10 -11
  57. package/perf-logs.js +2 -5
package/bootstrap.js CHANGED
@@ -47,9 +47,8 @@ Module.runMain = async function (...args) {
47
47
  loader.logTime(appStartTime, 'application');
48
48
  loader.logTime(startTime, 'agent & application');
49
49
  } catch (err) {
50
- // eslint-disable-next-line no-console
51
50
  console.error(err);
52
- // eslint-disable-next-line no-process-exit
53
- process.exit(-1);
51
+ process.exit(-1); // eslint-disable-line no-process-exit
52
+
54
53
  }
55
54
  };
package/esm.mjs CHANGED
@@ -24,45 +24,14 @@ 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');
28
27
  const agent = require(`./lib/agent.js`);
29
28
  const logger = require(`./lib/core/logger/index.js`)('contrast:esm-loaders');
30
29
  const rewriter = require(`./lib/core/rewrite/index.js`)(agent);
31
30
  const helpers = require(`./lib/hooks/module/helpers.js`);
32
- const parent = require('parent-package-json');
31
+ const getType = require(`./lib/util/get-file-type.js`);
33
32
 
34
33
  const loadedFromCache = new Set();
35
34
 
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
- }
66
35
  /**
67
36
  * The `getSource` hook is used to provide a custom method for retrieving source
68
37
  * code. In our case, we check for previously rewritten ESM files in our cache
@@ -156,10 +125,15 @@ export async function load(url, context, defaultLoad) {
156
125
  const filename = fileURLToPath(url);
157
126
 
158
127
  try {
128
+ let result;
159
129
  const cached = helpers.find(agent, filename);
160
- const source = cached || await readFile(filename, 'utf8');
161
- const result = rewriter.rewriteFile(source, filename, { sourceType: type === 'commonjs' ? 'script' : 'module' });
162
- helpers.cacheWithSourceMap(agent, filename, result);
130
+ if (cached) {
131
+ result = { code: cached };
132
+ } else {
133
+ const source = await readFile(filename, 'utf8');
134
+ result = rewriter.rewriteFile(source, filename, { sourceType: type === 'commonjs' ? 'script' : 'module' });
135
+ helpers.cacheWithSourceMap(agent, filename, result);
136
+ }
163
137
  return { format: type, source: result.code };
164
138
  } catch (err) {
165
139
  logger.error(
@@ -14,8 +14,6 @@ Copyright: 2022 Contrast Security, Inc
14
14
  */
15
15
  'use strict';
16
16
 
17
- /* eslint-disable prettier/prettier */
18
-
19
17
  const { PROXY_TARGET } = require('../../constants');
20
18
 
21
19
  class Debraner {
@@ -152,12 +152,10 @@ class Membrane {
152
152
  }
153
153
 
154
154
  includes(object) {
155
- // eslint-disable-next-line prettier/prettier
156
155
  return this.members.has(object) || this.members.has(Membrane.unwrap(object));
157
156
  }
158
157
 
159
158
  getMapping(object) {
160
- // eslint-disable-next-line prettier/prettier
161
159
  return this.members.get(object) || this.members.get(Membrane.unwrap(object));
162
160
  }
163
161
 
@@ -422,7 +420,7 @@ function copyMetadata(tar, prop, metadata) {
422
420
  });
423
421
 
424
422
  if (!nm.path) {
425
- nm.path = prop || `''`;
423
+ nm.path = prop || "''";
426
424
  } else if (nm.isArray) {
427
425
  nm.path += `[${prop}]`;
428
426
  } else if (prop) {
@@ -83,7 +83,7 @@ class BaseEvent {
83
83
  this.parents = sortEvents(this.parents);
84
84
 
85
85
  this.parents.forEach((p) => {
86
- if (!set.has(p)) {
86
+ if (p && !set.has(p)) {
87
87
  set = p.getAllParents(set);
88
88
  set.add(p);
89
89
  }
@@ -158,7 +158,7 @@ function trim(list, start, stop) {
158
158
  return trimmedList;
159
159
  }
160
160
 
161
- /* eslint-disable complexity */
161
+ // eslint-disable-next-line complexity
162
162
  function trimInPlace(list, start, stop) {
163
163
  if (start < 0) {
164
164
  logger.debug(
@@ -205,7 +205,6 @@ function trimInPlace(list, start, stop) {
205
205
  }
206
206
  }
207
207
  }
208
- /* eslint-enable complexity */
209
208
 
210
209
  /**
211
210
  * Returns a filtered lists of TagRanges by type
@@ -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
  /**
16
18
  * Contains helper functions used to manage the policy
17
19
  * Management of hooked functions that are defined in assess policies(e.g. deadzone.json, propagators.json, rules.json)
@@ -184,7 +186,6 @@ utils.patch = function(obj, path, props, hookOptions) {
184
186
  // this triggers, it /should/ be patched anyways.
185
187
  const refs = new WeakSet();
186
188
 
187
- /* eslint-disable complexity */
188
189
  /**
189
190
  * Recursively patch all exports on objects and classes
190
191
  * note cyclomatic check disabled because there's no place to break
@@ -195,6 +196,7 @@ const refs = new WeakSet();
195
196
  * @param {number} depth current recursion depth
196
197
  * @returns {Object|function} returns original reference but patched
197
198
  */
199
+ // eslint-disable-next-line complexity
198
200
  utils.patchRecursive = function(obj, hookOptions, depth) {
199
201
  let protoNeedsPatch = false;
200
202
  let propertyNames; // scoped value so that this doesn't need to be called twice.
@@ -242,7 +244,6 @@ utils.patchRecursive = function(obj, hookOptions, depth) {
242
244
 
243
245
  return obj;
244
246
  };
245
- /* eslint-enable complexity */
246
247
 
247
248
  /**
248
249
  * Patches either global module or a resolved
@@ -44,14 +44,12 @@ const patcher = require('../../../hooks/patcher');
44
44
  const { PATCH_TYPES } = require('../../../constants');
45
45
 
46
46
  function makeCanary() {
47
- /* eslint-disable prettier/prettier */
48
47
  return crypto
49
- .randomBytes(12)
50
- .toString('base64')
51
- // map regex special chars to other chars
52
- .replace(/\+/g, '%')
53
- .replace(/\//g, '#');
54
- /* eslint-enable prettier/prettier */
48
+ .randomBytes(12)
49
+ .toString('base64')
50
+ // map regex special chars to other chars
51
+ .replace(/\+/g, '%')
52
+ .replace(/\//g, '#');
55
53
  }
56
54
 
57
55
  // read canary as if the word was "marker". it's just a string inserted into the values
@@ -233,8 +231,7 @@ module.exports.handle = function() {
233
231
  if (isString(value)) {
234
232
  // make skeletal version of valProperties with only the tagRanges prop.
235
233
  data.metadata[id] =
236
- // eslint-disable-next-line prettier/prettier
237
- { tagRanges: [new TagRange(0, value.length - 1, '')] };
234
+ { tagRanges: [new TagRange(0, value.length - 1, '')] };
238
235
  value = `${canary}${id}~${value}`;
239
236
  id++;
240
237
  }
@@ -333,7 +330,6 @@ module.exports.handle = function() {
333
330
  // this check is required only for tests, i believe. sourceEvents should
334
331
  // always exist, even if an empty array, for production code.
335
332
  if (metadata.sourceEvents && !metadata.sourceEvents.length) {
336
- // eslint-disable-next-line prettier/prettier
337
333
  const { sourceEvents, braned } = data.metadata;
338
334
  if (braned) {
339
335
  sourceEvents.push(
@@ -381,7 +377,6 @@ module.exports.handle = function() {
381
377
  // we only find our marker at the start of a string value.
382
378
  canaryReplacementDiff += m.length - 1;
383
379
  for (const tr of metadata[id].tagRanges) {
384
- // eslint-disable-next-line prettier/prettier
385
380
  tagRanges.push(new TagRange(tr.start + offset, tr.stop + offset, tr.tag));
386
381
  }
387
382
 
@@ -31,7 +31,6 @@ function executeConditionals(schema) {
31
31
  // if the conditional has a validator to check its schema, do it.
32
32
  if (conditional.validator) {
33
33
  if (!conditional.validator(schema[key])) {
34
- // eslint-disable-next-line prettier/prettier
35
34
  this.logger.trace(`conditional schema ${key} not valid`);
36
35
  continue;
37
36
  }
@@ -44,7 +43,6 @@ function executeConditionals(schema) {
44
43
  }
45
44
 
46
45
  if ('if' in schema) {
47
- // eslint-disable-next-line prettier/prettier
48
46
  valid = handleIfThenElse.call(this, schema.if, schema.then, schema.else) && valid;
49
47
  }
50
48
 
@@ -158,7 +156,6 @@ const conditionalDispatch = new Map([
158
156
  ['allOf', { method: handleAllOf, validator: nonEmptyArray }]
159
157
  ]);
160
158
 
161
- /* eslint-enable prettier/prettier */
162
159
  const conditionals = [...conditionalDispatch.keys()];
163
160
 
164
161
  module.exports = {
@@ -32,12 +32,11 @@ function t_boolean(schema, ctx) {
32
32
  return typeof ctx.data === 'boolean';
33
33
  }
34
34
 
35
- /* eslint-disable complexity */
36
35
  //
37
36
  // type: number, integer
38
37
  //
38
+ // eslint-disable-next-line complexity
39
39
  function t_number(schema, ctx) {
40
- /* eslint-disable prettier/prettier */
41
40
 
42
41
  // ajv's number evaluation order
43
42
  // integer (if type: integer)
@@ -83,7 +82,6 @@ function t_number(schema, ctx) {
83
82
  if ('multipleOf' in schema && (ctx.data / schema.multipleOf) % 1 !== 0) {
84
83
  valid = false;
85
84
  }
86
- /* eslint-enable prettier/prettier */
87
85
 
88
86
  return valid;
89
87
  }
@@ -91,6 +89,7 @@ function t_number(schema, ctx) {
91
89
  //
92
90
  // type: string
93
91
  //
92
+ // eslint-disable-next-line complexity
94
93
  function t_string(schema, ctx) {
95
94
  // ajv's string evaluation order
96
95
  // maxLength
@@ -134,6 +133,7 @@ function t_string(schema, ctx) {
134
133
  //
135
134
  // type: array
136
135
  //
136
+ // eslint-disable-next-line complexity
137
137
  function t_array(schema, ctx) {
138
138
  if (!Array.isArray(ctx.data)) {
139
139
  return false;
@@ -248,6 +248,7 @@ function elementsAreUnique(data) {
248
248
  //
249
249
  // type: object
250
250
  //
251
+ // eslint-disable-next-line complexity
251
252
  function t_object(schema, ctx) {
252
253
  if (typeof ctx.data !== 'object') {
253
254
  return false;
@@ -431,6 +432,7 @@ function* matching(patternProps, prop, ctx) {
431
432
  //
432
433
  // type: object helper
433
434
  //
435
+ // eslint-disable-next-line complexity
434
436
  function evaluateObjectDependencies(schema, ctx) {
435
437
  const deps = schema.dependencies;
436
438
  let valid = true;
@@ -455,7 +457,6 @@ function evaluateObjectDependencies(schema, ctx) {
455
457
  }
456
458
  // it's an array! if key is present in this.data then all the properties
457
459
  // enumerated in the array (they're strings) must be present in this.data.
458
- // eslint-disable-next-line prettier/prettier
459
460
  if (key in ctx.data && !dep.every((requiredProp) => requiredProp in ctx.data)) {
460
461
  // allErrors: true - check ajv's handling
461
462
  valid = false;
@@ -40,7 +40,7 @@ const { objectWalk, objectOnlyWalk } = require('./object-walk');
40
40
  // when userSchema sees '#/$defs/street' it tries to dereference it as a *local* reference
41
41
  // because it has lost the addressSchema context.
42
42
  //
43
- /* eslint-disable complexity */
43
+ // eslint-disable-next-line complexity
44
44
  function evalInRefSchema(ref) {
45
45
  const ctx = this;
46
46
  const ix = ref.indexOf('#');
@@ -194,7 +194,6 @@ function findNoHashRef(ref, ctx) {
194
194
  // yes, really.
195
195
 
196
196
  // try simple path replacement first.
197
- // eslint-disable-next-line node/no-deprecated-api
198
197
  const urlParts = url.parse(ref);
199
198
  if (schemaUrl && !urlParts.host && urlParts.path === ref) {
200
199
  const newRef = `${schemaUrl.origin}/${ref}`;
@@ -19,8 +19,6 @@ const { evalInRefSchema } = require('./refs');
19
19
  const fastDeepEqual = require('fast-deep-equal');
20
20
  const { objectWalk } = require('./object-walk');
21
21
 
22
- /* eslint-disable complexity */
23
-
24
22
  class SchemaContext {
25
23
  constructor(shadow, schema, object, key, options) {
26
24
  const schemaName = schema.$id || '';
@@ -107,6 +105,7 @@ class SchemaContext {
107
105
  * @param {object} ctx context for the evaluation, as defined above in evaluate().
108
106
  * @returns {boolean} validation result
109
107
  */
108
+ // eslint-disable-next-line complexity
110
109
  evaluate(schema) {
111
110
  this.inferredType = false;
112
111
  // don't do any validation of strings if the schema is boolean. while
@@ -165,6 +164,7 @@ class SchemaContext {
165
164
  return false;
166
165
  }
167
166
 
167
+ // eslint-disable-next-line complexity
168
168
  typeSpecificEval(schema) {
169
169
  const { type } = this;
170
170
 
@@ -374,7 +374,6 @@ class SchemaContext {
374
374
 
375
375
  const t = require('./json-schema-type-evaluators');
376
376
 
377
- /* eslint-disable prettier/prettier */
378
377
  // map each JSON Schema type to the method name for it
379
378
  SchemaContext.typeDispatch = new Map([
380
379
  ['null', { method: t.null, enumerator: 'scalarEnum' }],
@@ -59,23 +59,31 @@ function splitString(str, win32) {
59
59
  * @param {number} offset offset of full arg from result of path.resolve
60
60
  * @param {string} segment path segment from one of the args to path.resolve
61
61
  */
62
- function getSegmentOffset({ str, evaluator }, offset, segment, win32) {
62
+ // eslint-disable-next-line complexity
63
+ function getSegmentOffset({ meta: { str, evaluator }, offset, segment, win32, validateAgainstResult }) {
63
64
  // as the segments in each arg and in the result get traversed,
64
65
  // winnow away the string to ensure we are finding the proper
65
66
  // segment within the path
66
67
  const substr = str.substring(offset);
67
- let segmentOffset = substr.indexOf(segment);
68
+ const { sep } = path[win32 ? 'win32' : 'posix'];
69
+ let segmentOffset;
70
+ // Sometimes the segment starts with a separator, but the path method removes the initial separator if the path is not absolute
71
+ if (validateAgainstResult && segment.startsWith(sep) && offset == 0 && !['\\', '/', '.'].includes(substr[0]) && !['\\', '/'].includes(segment)) {
72
+ segment = segment.slice(1);
73
+ }
74
+ segmentOffset = substr.indexOf(segment);
75
+
68
76
  // If tracking separators, evaluator will fail on extensions
69
77
  if (substr === `.${segment}`) {
70
- return segmentOffset + offset;
78
+ return { offset: segmentOffset + offset, value: segment };
71
79
  }
80
+
72
81
  // Adjust offset if the segment does not start with a separator
73
- const { sep } = path[win32 ? 'win32' : 'posix'];
74
82
  if (substr.startsWith(sep) && !segment.startsWith(sep)) {
75
83
  segmentOffset--;
76
84
  }
77
85
 
78
- return evaluator(segmentOffset) ? segmentOffset + offset : -1;
86
+ return { offset: evaluator(segmentOffset) ? segmentOffset + offset : -1, value: segment };
79
87
  }
80
88
 
81
89
  /**
@@ -215,15 +223,19 @@ function filterSegmentsAndCalculateOffset(
215
223
  additionalOffset = hasChange ? (sepAdded ? 1 : -1) : 0;
216
224
  }
217
225
 
218
- const offset = getSegmentOffset(
219
- resultMeta,
220
- accumulator.offset + additionalOffset + accumulator.fileDotSeparator,
226
+
227
+ const validatedSegment = getSegmentOffset({
228
+ meta: resultMeta,
229
+ offset: accumulator.offset + additionalOffset + accumulator.fileDotSeparator,
221
230
  segment,
222
- win32
223
- );
231
+ win32,
232
+ validateAgainstResult: true
233
+ });
234
+
235
+ const { offset: segmentOffset, value: segmentValue } = validatedSegment;
224
236
 
225
237
  // no reason to proceed if segment is not in final result
226
- if (offset === -1) {
238
+ if (segmentOffset === -1) {
227
239
  if (hasChange) {
228
240
  additionalOffset = 0;
229
241
  accumulator.isModified = false;
@@ -233,12 +245,11 @@ function filterSegmentsAndCalculateOffset(
233
245
  }
234
246
 
235
247
  // in case we have a file we need to increment the offset
236
- if (resultMeta.str[offset + segment.length] === '.') {
248
+ if (resultMeta.str[segmentOffset + segmentValue.length] === '.') {
237
249
  accumulator.fileDotSeparator = 1;
238
250
  }
239
-
240
- validSegments.push(segment);
241
- accumulator.offset = calculateNewOffset(accumulator.offset, segment);
251
+ validSegments.push(validatedSegment);
252
+ accumulator.offset = calculateNewOffset(accumulator.offset, segmentValue);
242
253
  accumulator.isModified = true;
243
254
 
244
255
  return accumulator;
@@ -280,26 +291,20 @@ function adjustTagsToPart(resultMeta, argMeta, win32, data, index) {
280
291
  resultMeta.offset += additionalOffset;
281
292
 
282
293
  return segments.reduce((newTags, segment) => {
283
- const offset = getSegmentOffset(
284
- resultMeta,
285
- resultMeta.offset,
286
- segment,
287
- win32
288
- );
289
-
290
- const argOffset = getSegmentOffset(argMeta, argMeta.offset, segment, win32);
294
+ const { offset, value: segmentValue } = segment;
295
+ const { offset: argOffset } = getSegmentOffset({ meta: argMeta, offset: argMeta.offset, segment: segmentValue, win32, validateAgainstResult: false });
291
296
 
292
297
  // updating the offset
293
- resultMeta.offset = calculateNewOffset(resultMeta.offset, segment);
294
- argMeta.offset = calculateNewOffset(argMeta.offset, segment);
298
+ resultMeta.offset = calculateNewOffset(resultMeta.offset, segmentValue);
299
+ argMeta.offset = calculateNewOffset(argMeta.offset, segmentValue);
295
300
 
296
301
  // in case we have a file we need to increment the offset
297
- if (resultMeta.str[offset + segment.length] === '.') {
302
+ if (resultMeta.str[offset + segment.value.length] === '.') {
298
303
  resultMeta.offset += 1;
299
304
  }
300
305
 
301
306
  tagRanges.forEach((tag) => {
302
- if (!isWithinTag(segment, argOffset, tag)) return;
307
+ if (!isWithinTag(segmentValue, argOffset, tag)) return;
303
308
 
304
309
  const start = adjustStart({
305
310
  tag,
@@ -310,7 +315,7 @@ function adjustTagsToPart(resultMeta, argMeta, win32, data, index) {
310
315
  tag,
311
316
  argOffset,
312
317
  offset,
313
- segment
318
+ segment: segmentValue
314
319
  });
315
320
 
316
321
  newTags.push(new TagRange(start, stop, tag.tag));
@@ -327,6 +332,7 @@ function propagate({ resultMeta, data, win32 }) {
327
332
 
328
333
  data.args.forEach((arg, index) => {
329
334
  const argData = tracker.getData(arg);
335
+
330
336
  maybeUpdateResultMeta({ resultMeta, index, arg });
331
337
 
332
338
  const argMeta = {
@@ -354,7 +360,10 @@ function propagate({ resultMeta, data, win32 }) {
354
360
  }
355
361
 
356
362
  function getResultMeta(data, method) {
357
- const offset = path.win32.isAbsolute(data.args[0]) ? 0 : process.cwd().length;
363
+ let offset = 0;
364
+ if (method === 'resolve' && !path.win32.isAbsolute(data.args[0])) {
365
+ offset = process.cwd().length;
366
+ }
358
367
 
359
368
  return {
360
369
  method: `path.${method}`,
@@ -19,6 +19,7 @@ const patcher = require('../../../hooks/patcher');
19
19
  const { PATCH_TYPES } = require('../../../constants');
20
20
  const { propagate, absolutePath, getResultMeta } = require('./common');
21
21
 
22
+
22
23
  /**
23
24
  * Entry point to propagator provider
24
25
  * This instruments path.resolve on
@@ -30,8 +30,7 @@ module.exports.isTracked = function isTracked(value) {
30
30
  * Function to get sql-string export. Caches the export on first call.
31
31
  */
32
32
  module.exports.getSequelizeString = function() {
33
- // eslint-disable-next-line node/no-unpublished-require
34
- const data = require('sequelize/lib/sql-string');
33
+ const data = require('sequelize/lib/sql-string'); // eslint-disable-line node/no-unpublished-require
35
34
  module.exports.getSequelizeString = () => data;
36
35
  return data;
37
36
  };
@@ -14,7 +14,6 @@ Copyright: 2022 Contrast Security, Inc
14
14
  */
15
15
  'use strict';
16
16
 
17
- // eslint-disable-next-line no-unused-vars
18
17
  const logger = require('../../../core/logger')('contrast:v8:propagator');
19
18
  const tracker = require('../../../tracker');
20
19
  const patcher = require('../../../hooks/patcher');