@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.
- package/bootstrap.js +2 -3
- package/esm.mjs +9 -35
- package/lib/assess/membrane/debraner.js +0 -2
- package/lib/assess/membrane/index.js +1 -3
- package/lib/assess/models/base-event.js +1 -1
- package/lib/assess/models/tag-range/util.js +1 -2
- package/lib/assess/policy/util.js +3 -2
- package/lib/assess/propagators/JSON/stringify.js +6 -11
- package/lib/assess/propagators/ajv/conditionals.js +0 -3
- package/lib/assess/propagators/ajv/json-schema-type-evaluators.js +5 -4
- package/lib/assess/propagators/ajv/refs.js +1 -2
- package/lib/assess/propagators/ajv/schema-context.js +2 -3
- package/lib/assess/propagators/path/common.js +38 -29
- package/lib/assess/propagators/path/resolve.js +1 -0
- package/lib/assess/propagators/sequelize/utils.js +1 -2
- package/lib/assess/propagators/v8/init-hooks.js +0 -1
- package/lib/assess/sinks/dynamo.js +65 -30
- package/lib/assess/static/hardcoded.js +3 -3
- package/lib/assess/static/read-findings-from-cache.js +40 -0
- package/lib/assess/technologies/index.js +12 -13
- package/lib/cli-rewriter/index.js +65 -6
- package/lib/core/config/options.js +6 -0
- package/lib/core/config/util.js +15 -33
- package/lib/core/exclusions/input.js +6 -1
- package/lib/core/express/index.js +2 -4
- package/lib/core/logger/debug-logger.js +2 -2
- package/lib/core/stacktrace.js +2 -1
- package/lib/hooks/http.js +81 -81
- package/lib/hooks/require.js +1 -0
- package/lib/instrumentation.js +17 -0
- package/lib/protect/analysis/aho-corasick.js +1 -1
- package/lib/protect/errors/handler-async-errors.js +66 -0
- package/lib/protect/input-analysis.js +7 -13
- package/lib/protect/listeners.js +27 -23
- package/lib/protect/rules/base-scanner/index.js +2 -2
- package/lib/protect/rules/bot-blocker/bot-blocker-rule.js +4 -2
- package/lib/protect/rules/cmd-injection/cmdinjection-rule.js +57 -2
- package/lib/protect/rules/cmd-injection-semantic-chained-commands/cmd-injection-semantic-chained-commands-rule.js +31 -2
- package/lib/protect/rules/cmd-injection-semantic-dangerous-paths/cmd-injection-semantic-dangerous-paths-rule.js +32 -2
- package/lib/protect/rules/index.js +42 -21
- package/lib/protect/rules/ip-denylist/ip-denylist-rule.js +2 -2
- package/lib/protect/rules/nosqli/nosql-injection-rule.js +104 -39
- package/lib/protect/rules/path-traversal/path-traversal-rule.js +3 -0
- package/lib/protect/rules/rule-factory.js +6 -7
- package/lib/protect/rules/signatures/signature.js +3 -0
- package/lib/protect/rules/sqli/sql-injection-rule.js +98 -5
- package/lib/protect/rules/sqli/sql-scanner/labels.json +0 -3
- package/lib/protect/rules/xss/reflected-xss-rule.js +3 -3
- package/lib/protect/sample-aggregator.js +65 -57
- package/lib/protect/service.js +709 -104
- package/lib/reporter/models/app-activity/sample.js +6 -0
- package/lib/reporter/speedracer/unknown-connection-state.js +20 -32
- package/lib/reporter/translations/to-protobuf/settings/assess-features.js +4 -6
- package/lib/reporter/ts-reporter.js +1 -1
- package/lib/util/get-file-type.js +43 -0
- package/package.json +10 -11
- 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-
|
|
53
|
-
|
|
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
|
|
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
|
-
|
|
161
|
-
|
|
162
|
-
|
|
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(
|
|
@@ -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) {
|
|
@@ -158,7 +158,7 @@ function trim(list, start, stop) {
|
|
|
158
158
|
return trimmedList;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
219
|
-
|
|
220
|
-
|
|
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 (
|
|
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[
|
|
248
|
+
if (resultMeta.str[segmentOffset + segmentValue.length] === '.') {
|
|
237
249
|
accumulator.fileDotSeparator = 1;
|
|
238
250
|
}
|
|
239
|
-
|
|
240
|
-
|
|
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 =
|
|
284
|
-
|
|
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,
|
|
294
|
-
argMeta.offset = calculateNewOffset(argMeta.offset,
|
|
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(
|
|
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
|
-
|
|
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-
|
|
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');
|