@contrast/agent 4.10.1 → 4.10.5
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 +1 -1
- package/bin/linux/contrast-service +0 -0
- package/bin/mac/contrast-service +0 -0
- package/bin/windows/contrast-service.exe +0 -0
- package/bootstrap.js +2 -2
- package/esm.mjs +45 -3
- package/lib/core/express/index.js +34 -29
- package/lib/core/logger/debug-logger.js +4 -3
- package/lib/core/rewrite/binary-expression.js +1 -2
- package/lib/core/rewrite/callees.js +3 -2
- package/lib/core/rewrite/catch-clause.js +4 -2
- package/lib/core/rewrite/import-declaration.js +2 -2
- package/lib/core/rewrite/index.js +1 -0
- package/lib/core/rewrite/injections.js +1 -3
- package/lib/core/rewrite/rewrite-log.js +5 -8
- package/lib/util/traverse.js +40 -9
- package/package.json +9 -7
package/bin/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.28.
|
|
1
|
+
2.28.13
|
|
Binary file
|
package/bin/mac/contrast-service
CHANGED
|
Binary file
|
|
Binary file
|
package/bootstrap.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
/**
|
|
3
2
|
Copyright: 2022 Contrast Security, Inc
|
|
4
3
|
Contact: support@contrastsecurity.com
|
|
@@ -13,6 +12,7 @@ Copyright: 2022 Contrast Security, Inc
|
|
|
13
12
|
engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
14
13
|
way not consistent with the End User License Agreement.
|
|
15
14
|
*/
|
|
15
|
+
'use strict';
|
|
16
16
|
|
|
17
17
|
const startTime = process.hrtime();
|
|
18
18
|
|
|
@@ -25,7 +25,7 @@ const orig = Module.runMain;
|
|
|
25
25
|
* process before invoking the main
|
|
26
26
|
* script from cli
|
|
27
27
|
*/
|
|
28
|
-
Module.runMain = async function(...args) {
|
|
28
|
+
Module.runMain = async function (...args) {
|
|
29
29
|
const { isMainThread } = require('worker_threads');
|
|
30
30
|
|
|
31
31
|
try {
|
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:
|
|
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.',
|
|
@@ -26,7 +26,7 @@ const { isString } = require('../../util/is-string');
|
|
|
26
26
|
const { emitSendEvent } = require('../../hooks/frameworks/common');
|
|
27
27
|
const {
|
|
28
28
|
prototype: { decorateRequest },
|
|
29
|
-
setFrameworkRequest
|
|
29
|
+
setFrameworkRequest,
|
|
30
30
|
} = require('../../hooks/frameworks/base');
|
|
31
31
|
const ExpressRequest = require('../../reporter/models/frameworks/express-request');
|
|
32
32
|
|
|
@@ -40,7 +40,7 @@ const {
|
|
|
40
40
|
INPUT_TYPES,
|
|
41
41
|
SINK_TYPES,
|
|
42
42
|
MW_PATH,
|
|
43
|
-
LAYER_STACK
|
|
43
|
+
LAYER_STACK,
|
|
44
44
|
} = constants;
|
|
45
45
|
const { EVENTS } = Helpers;
|
|
46
46
|
|
|
@@ -111,14 +111,14 @@ class ExpressFramework {
|
|
|
111
111
|
agentEmitter.emit(
|
|
112
112
|
EVENTS.REQUEST_SEND,
|
|
113
113
|
data.args[0],
|
|
114
|
-
SINK_TYPES.RESPONSE_BODY
|
|
114
|
+
SINK_TYPES.RESPONSE_BODY,
|
|
115
115
|
);
|
|
116
116
|
|
|
117
|
-
const body = data.args
|
|
117
|
+
const [body] = data.args;
|
|
118
118
|
if (isString(body)) {
|
|
119
119
|
emitSendEvent(body.valueOf());
|
|
120
120
|
}
|
|
121
|
-
}
|
|
121
|
+
},
|
|
122
122
|
});
|
|
123
123
|
|
|
124
124
|
patcher.patch(express.response, 'push', {
|
|
@@ -128,14 +128,14 @@ class ExpressFramework {
|
|
|
128
128
|
agentEmitter.emit(
|
|
129
129
|
EVENTS.REQUEST_SEND,
|
|
130
130
|
data.args[0],
|
|
131
|
-
SINK_TYPES.RESPONSE_BODY
|
|
131
|
+
SINK_TYPES.RESPONSE_BODY,
|
|
132
132
|
);
|
|
133
133
|
|
|
134
|
-
const body = data.args
|
|
134
|
+
const [body] = data.args;
|
|
135
135
|
if (isString(body)) {
|
|
136
136
|
emitSendEvent(body.valueOf());
|
|
137
137
|
}
|
|
138
|
-
}
|
|
138
|
+
},
|
|
139
139
|
});
|
|
140
140
|
|
|
141
141
|
patcher.patch(express.response, 'end', {
|
|
@@ -145,9 +145,9 @@ class ExpressFramework {
|
|
|
145
145
|
agentEmitter.emit(
|
|
146
146
|
EVENTS.REQUEST_SEND,
|
|
147
147
|
data.args[0],
|
|
148
|
-
SINK_TYPES.RESPONSE_BODY
|
|
148
|
+
SINK_TYPES.RESPONSE_BODY,
|
|
149
149
|
);
|
|
150
|
-
}
|
|
150
|
+
},
|
|
151
151
|
});
|
|
152
152
|
|
|
153
153
|
patcher.patch(express.Router, 'use', {
|
|
@@ -157,7 +157,7 @@ class ExpressFramework {
|
|
|
157
157
|
pre: self.injectContrastMiddleware.bind(self),
|
|
158
158
|
post: (wrapCtx) => {
|
|
159
159
|
agentEmitter.emit(EVENTS.ROUTER_USE, self, wrapCtx);
|
|
160
|
-
}
|
|
160
|
+
},
|
|
161
161
|
});
|
|
162
162
|
|
|
163
163
|
patcher.patch(express.Router, 'route', {
|
|
@@ -166,7 +166,7 @@ class ExpressFramework {
|
|
|
166
166
|
alwaysRun: true,
|
|
167
167
|
post: (wrapCtx) => {
|
|
168
168
|
agentEmitter.emit(EVENTS.ROUTER_ROUTE, self, wrapCtx);
|
|
169
|
-
}
|
|
169
|
+
},
|
|
170
170
|
});
|
|
171
171
|
|
|
172
172
|
LC_HTTP_VERBS.forEach((verb) => {
|
|
@@ -177,7 +177,7 @@ class ExpressFramework {
|
|
|
177
177
|
pre: self.injectContrastMiddleware.bind(self),
|
|
178
178
|
post: (wrapCtx) => {
|
|
179
179
|
agentEmitter.emit(EVENTS.ROUTER_METHOD, self, wrapCtx, verb);
|
|
180
|
-
}
|
|
180
|
+
},
|
|
181
181
|
});
|
|
182
182
|
});
|
|
183
183
|
|
|
@@ -188,7 +188,7 @@ class ExpressFramework {
|
|
|
188
188
|
pre: self.injectContrastMiddleware.bind(self),
|
|
189
189
|
post: (wrapCtx) => {
|
|
190
190
|
agentEmitter.emit(EVENTS.ROUTER_METHOD, self, wrapCtx, 'all');
|
|
191
|
-
}
|
|
191
|
+
},
|
|
192
192
|
});
|
|
193
193
|
|
|
194
194
|
patcher.patch(express.application, 'use', {
|
|
@@ -198,7 +198,7 @@ class ExpressFramework {
|
|
|
198
198
|
pre: self.injectContrastMiddleware.bind(self),
|
|
199
199
|
post: (wrapCtx) => {
|
|
200
200
|
agentEmitter.emit(EVENTS.APP_USE, self, wrapCtx);
|
|
201
|
-
}
|
|
201
|
+
},
|
|
202
202
|
});
|
|
203
203
|
|
|
204
204
|
LC_HTTP_VERBS.forEach((verb) => {
|
|
@@ -209,7 +209,7 @@ class ExpressFramework {
|
|
|
209
209
|
pre: self.injectContrastMiddleware.bind(self),
|
|
210
210
|
post: (wrapCtx) => {
|
|
211
211
|
agentEmitter.emit(EVENTS.APP_METHOD, self, wrapCtx, verb);
|
|
212
|
-
}
|
|
212
|
+
},
|
|
213
213
|
});
|
|
214
214
|
});
|
|
215
215
|
|
|
@@ -220,7 +220,7 @@ class ExpressFramework {
|
|
|
220
220
|
pre: self.injectContrastMiddleware.bind(self),
|
|
221
221
|
post: (wrapCtx) => {
|
|
222
222
|
agentEmitter.emit(EVENTS.APP_METHOD, self, wrapCtx, 'all');
|
|
223
|
-
}
|
|
223
|
+
},
|
|
224
224
|
});
|
|
225
225
|
|
|
226
226
|
agentEmitter.on(HTTP_EVENTS.SERVER_CREATE, this.onServerCreate.bind(this));
|
|
@@ -238,7 +238,7 @@ class ExpressFramework {
|
|
|
238
238
|
if (!app || !app.defaultConfiguration) {
|
|
239
239
|
logger.error(
|
|
240
240
|
`non-express application mistakenly registered`,
|
|
241
|
-
new Error().stack
|
|
241
|
+
new Error().stack,
|
|
242
242
|
);
|
|
243
243
|
return;
|
|
244
244
|
}
|
|
@@ -305,7 +305,7 @@ class ExpressFramework {
|
|
|
305
305
|
EVENTS.REQUEST_READY,
|
|
306
306
|
req,
|
|
307
307
|
res,
|
|
308
|
-
INPUT_TYPES.QUERYSTRING
|
|
308
|
+
INPUT_TYPES.QUERYSTRING,
|
|
309
309
|
);
|
|
310
310
|
next();
|
|
311
311
|
}, 'query');
|
|
@@ -322,6 +322,14 @@ class ExpressFramework {
|
|
|
322
322
|
next();
|
|
323
323
|
}, 'rawParser');
|
|
324
324
|
|
|
325
|
+
// ... bodyParser in Sails Framework ............................
|
|
326
|
+
this.useAfter(function ContrastBodyParsed(req, res, next) {
|
|
327
|
+
if (req._sails && req.body) {
|
|
328
|
+
agentEmitter.emit(EVENTS.BODY_PARSED, req, res, INPUT_TYPES.BODY);
|
|
329
|
+
}
|
|
330
|
+
next();
|
|
331
|
+
}, '_parseHTTPBody');
|
|
332
|
+
|
|
325
333
|
this.useAfter(function ContrastTextBodyParsed(req, res, next) {
|
|
326
334
|
agentEmitter.emit(EVENTS.BODY_PARSED, req, res, INPUT_TYPES.BODY);
|
|
327
335
|
next();
|
|
@@ -329,7 +337,7 @@ class ExpressFramework {
|
|
|
329
337
|
|
|
330
338
|
this.useAfter(function ContrastBodyParsed(req, res, next) {
|
|
331
339
|
agentEmitter.emit(EVENTS.BODY_PARSED, req, res, {
|
|
332
|
-
type: INPUT_TYPES.BODY
|
|
340
|
+
type: INPUT_TYPES.BODY,
|
|
333
341
|
});
|
|
334
342
|
next();
|
|
335
343
|
}, 'urlencodedParser');
|
|
@@ -345,7 +353,7 @@ class ExpressFramework {
|
|
|
345
353
|
EVENTS.COOKIES_PARSED,
|
|
346
354
|
req,
|
|
347
355
|
res,
|
|
348
|
-
INPUT_TYPES.COOKIE_VALUE
|
|
356
|
+
INPUT_TYPES.COOKIE_VALUE,
|
|
349
357
|
);
|
|
350
358
|
|
|
351
359
|
next();
|
|
@@ -395,7 +403,7 @@ class ExpressFramework {
|
|
|
395
403
|
patchType: PATCH_TYPES.SOURCE,
|
|
396
404
|
pre(data) {
|
|
397
405
|
req[LAYER_STACK].pop();
|
|
398
|
-
}
|
|
406
|
+
},
|
|
399
407
|
});
|
|
400
408
|
if (req.query) {
|
|
401
409
|
decorateRequest({ query: req.query });
|
|
@@ -406,11 +414,11 @@ class ExpressFramework {
|
|
|
406
414
|
EVENTS.PARAM_PARSED,
|
|
407
415
|
req,
|
|
408
416
|
res,
|
|
409
|
-
INPUT_TYPES.URL_PARAMETER
|
|
417
|
+
INPUT_TYPES.URL_PARAMETER,
|
|
410
418
|
);
|
|
411
419
|
|
|
412
420
|
decorateRequest({
|
|
413
|
-
parameters: req.params
|
|
421
|
+
parameters: req.params,
|
|
414
422
|
});
|
|
415
423
|
}
|
|
416
424
|
|
|
@@ -422,21 +430,18 @@ class ExpressFramework {
|
|
|
422
430
|
|
|
423
431
|
Whatever the core issue is, it doesn't appear to have any effects
|
|
424
432
|
elsewhere in any of our Express/Kraken framework support.
|
|
425
|
-
|
|
426
|
-
BODY_PARSED event is emitted to support Sails framework
|
|
427
433
|
*/
|
|
428
434
|
if (req.body) {
|
|
429
435
|
decorateRequest({ body: req.body });
|
|
430
|
-
agentEmitter.emit(EVENTS.BODY_PARSED, req, res, req.body);
|
|
431
436
|
}
|
|
432
|
-
}
|
|
437
|
+
},
|
|
433
438
|
});
|
|
434
439
|
}
|
|
435
440
|
}
|
|
436
441
|
|
|
437
442
|
useAfter(fn, after) {
|
|
438
443
|
this.handlers[after] = {
|
|
439
|
-
post: fn
|
|
444
|
+
post: fn,
|
|
440
445
|
};
|
|
441
446
|
}
|
|
442
447
|
|
|
@@ -108,9 +108,10 @@ class DebugLogFactory {
|
|
|
108
108
|
|
|
109
109
|
// We always log to a file, but check whether we should log to stdout
|
|
110
110
|
if (
|
|
111
|
-
|
|
112
|
-
!
|
|
113
|
-
|
|
111
|
+
this.loggerPath &&
|
|
112
|
+
(!this.stdout ||
|
|
113
|
+
!process.env.DEBUG ||
|
|
114
|
+
!/(^|,\s*)contrast:.+/.test(process.env.DEBUG))
|
|
114
115
|
) {
|
|
115
116
|
this.mute = true;
|
|
116
117
|
}
|
|
@@ -15,7 +15,6 @@ Copyright: 2022 Contrast Security, Inc
|
|
|
15
15
|
'use strict';
|
|
16
16
|
|
|
17
17
|
const t = require('@babel/types');
|
|
18
|
-
const _ = require('lodash');
|
|
19
18
|
|
|
20
19
|
/**
|
|
21
20
|
* Wraps binary expressions in one of the following: `ContrastMethods.__add`,
|
|
@@ -30,7 +29,7 @@ const _ = require('lodash');
|
|
|
30
29
|
* @param {import('.').State} state
|
|
31
30
|
*/
|
|
32
31
|
module.exports = function BinaryExpression(path, state) {
|
|
33
|
-
const spec =
|
|
32
|
+
const spec = state.specs.find(({ token }) => token === path.node.operator);
|
|
34
33
|
if (
|
|
35
34
|
!spec ||
|
|
36
35
|
!state.callees[spec.name] ||
|
|
@@ -15,7 +15,6 @@ Copyright: 2022 Contrast Security, Inc
|
|
|
15
15
|
'use strict';
|
|
16
16
|
|
|
17
17
|
const { expression } = require('@babel/template');
|
|
18
|
-
const _ = require('lodash');
|
|
19
18
|
|
|
20
19
|
/**
|
|
21
20
|
* @typedef {Object} Spec
|
|
@@ -132,7 +131,9 @@ module.exports = function createCallees(agent) {
|
|
|
132
131
|
const callees = specs.reduce(
|
|
133
132
|
(memo, spec) =>
|
|
134
133
|
(assessMode && spec.modes.assess) || (protectMode && spec.modes.protect)
|
|
135
|
-
?
|
|
134
|
+
? Object.assign(memo, {
|
|
135
|
+
[spec.name]: calleeBuilder({ name: spec.name })
|
|
136
|
+
})
|
|
136
137
|
: memo,
|
|
137
138
|
{}
|
|
138
139
|
);
|
|
@@ -13,7 +13,6 @@ Copyright: 2022 Contrast Security, Inc
|
|
|
13
13
|
way not consistent with the End User License Agreement.
|
|
14
14
|
*/
|
|
15
15
|
const { statement } = require('@babel/template');
|
|
16
|
-
const _ = require('lodash');
|
|
17
16
|
|
|
18
17
|
const logStatementBuilder = statement(
|
|
19
18
|
`if (global.CONTRAST_LOG) {
|
|
@@ -38,7 +37,10 @@ const logStatementBuilder = statement(
|
|
|
38
37
|
* @param {import('.').State} state
|
|
39
38
|
*/
|
|
40
39
|
module.exports = function CatchClause(path, state) {
|
|
41
|
-
|
|
40
|
+
const { config } = state.agent;
|
|
41
|
+
if (!config || !config.agent.node.enable_catch_log) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
42
44
|
|
|
43
45
|
path.node.param = path.node.param || path.scope.generateUidIdentifier('err');
|
|
44
46
|
path
|
|
@@ -15,7 +15,6 @@ Copyright: 2022 Contrast Security, Inc
|
|
|
15
15
|
'use strict';
|
|
16
16
|
|
|
17
17
|
const t = require('@babel/types');
|
|
18
|
-
const _ = require('lodash');
|
|
19
18
|
|
|
20
19
|
const IMPORT_META_URL_MEMBER_EXPRESSION = t.memberExpression(
|
|
21
20
|
t.memberExpression(t.identifier('import'), t.identifier('meta')),
|
|
@@ -49,7 +48,8 @@ module.exports = function ImportDeclaration(path, state) {
|
|
|
49
48
|
|
|
50
49
|
path.insertAfter(
|
|
51
50
|
specifiers.map((importSpec) => {
|
|
52
|
-
const spec =
|
|
51
|
+
const spec = state.specs.find(({ type }) => type === importSpec.type);
|
|
52
|
+
|
|
53
53
|
if (!spec || !state.callees[spec.name]) return;
|
|
54
54
|
|
|
55
55
|
const args = [importSpec.local];
|
|
@@ -14,7 +14,6 @@ Copyright: 2022 Contrast Security, Inc
|
|
|
14
14
|
*/
|
|
15
15
|
'use strict';
|
|
16
16
|
|
|
17
|
-
const _ = require('lodash');
|
|
18
17
|
const logger = require('../logger')('contrast:rewrite:injections');
|
|
19
18
|
const patcher = require('../../hooks/patcher');
|
|
20
19
|
const { PATCH_TYPES } = require('../../constants');
|
|
@@ -161,8 +160,7 @@ module.exports = {
|
|
|
161
160
|
* @returns {Injection[]}
|
|
162
161
|
*/
|
|
163
162
|
getEnabled() {
|
|
164
|
-
return
|
|
165
|
-
injections,
|
|
163
|
+
return Object.values(injections).reduce(
|
|
166
164
|
(enabled, injection) =>
|
|
167
165
|
injection.enabled() ? [...enabled, injection] : enabled,
|
|
168
166
|
[]
|
|
@@ -13,7 +13,6 @@ Copyright: 2022 Contrast Security, Inc
|
|
|
13
13
|
way not consistent with the End User License Agreement.
|
|
14
14
|
*/
|
|
15
15
|
'use strict';
|
|
16
|
-
const _ = require('lodash');
|
|
17
16
|
|
|
18
17
|
/**
|
|
19
18
|
* Helper class that provides some means of optimizing the rewrite process.
|
|
@@ -32,11 +31,9 @@ module.exports = class RewriteLog {
|
|
|
32
31
|
this._tokenMatches = specs.reduce(
|
|
33
32
|
(matches, spec) =>
|
|
34
33
|
callees[spec.name]
|
|
35
|
-
?
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
!spec.token || 0 <= codeString.indexOf(spec.token)
|
|
39
|
-
)
|
|
34
|
+
? Object.assign(matches, {
|
|
35
|
+
[spec.name]: !spec.token || 0 <= codeString.indexOf(spec.token)
|
|
36
|
+
})
|
|
40
37
|
: matches,
|
|
41
38
|
{}
|
|
42
39
|
);
|
|
@@ -60,7 +57,7 @@ module.exports = class RewriteLog {
|
|
|
60
57
|
* if we need to even rewrite the code at all.
|
|
61
58
|
*/
|
|
62
59
|
foundTokens() {
|
|
63
|
-
return
|
|
60
|
+
return Object.values(this._tokenMatches).some(Boolean);
|
|
64
61
|
}
|
|
65
62
|
|
|
66
63
|
/**
|
|
@@ -72,6 +69,6 @@ module.exports = class RewriteLog {
|
|
|
72
69
|
* make changes, we can just return original code.
|
|
73
70
|
*/
|
|
74
71
|
rewritesOccurred() {
|
|
75
|
-
return !this.aborted &&
|
|
72
|
+
return !this.aborted && Object.values(this._tokensRewritten).some(Boolean);
|
|
76
73
|
}
|
|
77
74
|
};
|
package/lib/util/traverse.js
CHANGED
|
@@ -59,7 +59,7 @@ class Path extends Stack {
|
|
|
59
59
|
|
|
60
60
|
super.push({
|
|
61
61
|
key,
|
|
62
|
-
array
|
|
62
|
+
array,
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
65
|
}
|
|
@@ -74,7 +74,16 @@ class Visitor {
|
|
|
74
74
|
this.cache = new WeakSet();
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
visit(key, value) {
|
|
77
|
+
visit(key, value, isMaxDepthReached) {
|
|
78
|
+
if (isMaxDepthReached) {
|
|
79
|
+
this.updateStacks(
|
|
80
|
+
{ counter: this.counter, path: this.path },
|
|
81
|
+
null,
|
|
82
|
+
null,
|
|
83
|
+
isMaxDepthReached,
|
|
84
|
+
);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
78
87
|
// skip circular objects
|
|
79
88
|
if (typeof value === 'object' && value !== null) {
|
|
80
89
|
if (this.cache.has(value)) {
|
|
@@ -96,7 +105,11 @@ class Visitor {
|
|
|
96
105
|
return newVal || value;
|
|
97
106
|
}
|
|
98
107
|
|
|
99
|
-
updateStacks(stacks, key, value) {
|
|
108
|
+
updateStacks(stacks, key, value, isMaxDepthReached) {
|
|
109
|
+
if (isMaxDepthReached) {
|
|
110
|
+
stacks.counter.pop();
|
|
111
|
+
stacks.path.pop();
|
|
112
|
+
}
|
|
100
113
|
// We're decending into the object, so here we're
|
|
101
114
|
// just building up the stacks.
|
|
102
115
|
|
|
@@ -123,7 +136,7 @@ class Visitor {
|
|
|
123
136
|
return this.updateStacks(
|
|
124
137
|
{ counter: this.counter, path: this.path },
|
|
125
138
|
key,
|
|
126
|
-
value
|
|
139
|
+
value,
|
|
127
140
|
);
|
|
128
141
|
}
|
|
129
142
|
return;
|
|
@@ -136,16 +149,34 @@ function traverse(obj, fn, visitor, maxDepth) {
|
|
|
136
149
|
maxDepth = visitor;
|
|
137
150
|
visitor = undefined;
|
|
138
151
|
}
|
|
139
|
-
|
|
140
152
|
visitor =
|
|
141
153
|
visitor ||
|
|
142
|
-
new Visitor(function(key, value, depth, paths) {
|
|
154
|
+
new Visitor(function (key, value, depth, paths) {
|
|
143
155
|
fn(key, value, depth, paths);
|
|
144
156
|
}, maxDepth);
|
|
145
157
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
158
|
+
traverseObject(obj, visitor, maxDepth);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function traverseObject(obj, visitor, remainingDepth = Infinity) {
|
|
162
|
+
if (!obj) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (visitor.path.length() < 1) {
|
|
166
|
+
visitor.visit('', obj);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// This is done just to reset the stack, without changing the current impletion
|
|
170
|
+
if (remainingDepth == 0) {
|
|
171
|
+
visitor.visit(null, null, true);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
Object.entries(obj).forEach(([key, value]) => {
|
|
176
|
+
visitor.visit(key, value);
|
|
177
|
+
if (value && typeof value === 'object') {
|
|
178
|
+
traverseObject(value, visitor, remainingDepth - 1);
|
|
179
|
+
}
|
|
149
180
|
});
|
|
150
181
|
}
|
|
151
182
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contrast/agent",
|
|
3
|
-
"version": "4.10.
|
|
3
|
+
"version": "4.10.5",
|
|
4
4
|
"description": "Node.js security instrumentation by Contrast Security",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"security",
|
|
@@ -113,12 +113,14 @@
|
|
|
113
113
|
"devDependencies": {
|
|
114
114
|
"@aws-sdk/client-dynamodb": "^3.39.0",
|
|
115
115
|
"@bmacnaughton/string-generator": "^1.0.0",
|
|
116
|
-
"@contrast/eslint-config": "^2.0
|
|
116
|
+
"@contrast/eslint-config": "^2.2.0",
|
|
117
117
|
"@contrast/fake-module": "file:test/mock/contrast-fake",
|
|
118
118
|
"@contrast/screener-service": "^1.12.9",
|
|
119
119
|
"@hapi/boom": "file:test/mock/boom",
|
|
120
120
|
"@hapi/hapi": "file:test/mock/hapi",
|
|
121
121
|
"@ls-lint/ls-lint": "^1.8.1",
|
|
122
|
+
"@typescript-eslint/eslint-plugin": "^5.10.2",
|
|
123
|
+
"@typescript-eslint/parser": "^5.10.2",
|
|
122
124
|
"ajv": "^8.5.0",
|
|
123
125
|
"ast-types": "^0.12.4",
|
|
124
126
|
"aws-sdk": "file:test/mock/aws-sdk",
|
|
@@ -135,11 +137,11 @@
|
|
|
135
137
|
"dustjs-linkedin": "^3.0.1",
|
|
136
138
|
"ejs": "^3.1.6",
|
|
137
139
|
"escape-html": "^1.0.3",
|
|
138
|
-
"eslint": "^8.
|
|
139
|
-
"eslint-config-prettier": "^
|
|
140
|
-
"eslint-plugin-mocha": "^
|
|
140
|
+
"eslint": "^8.8.0",
|
|
141
|
+
"eslint-config-prettier": "^8.3.0",
|
|
142
|
+
"eslint-plugin-mocha": "^10.0.3",
|
|
141
143
|
"eslint-plugin-node": "^11.1.0",
|
|
142
|
-
"eslint-plugin-prettier": "^
|
|
144
|
+
"eslint-plugin-prettier": "^4.0.0",
|
|
143
145
|
"express": "file:test/mock/express",
|
|
144
146
|
"fetch-cookie": "^0.11.0",
|
|
145
147
|
"form-data": "^3.0.0",
|
|
@@ -168,7 +170,7 @@
|
|
|
168
170
|
"nyc": "^15.1.0",
|
|
169
171
|
"pg": "file:test/mock/pg",
|
|
170
172
|
"pino": "^6.7.0",
|
|
171
|
-
"prettier": "^
|
|
173
|
+
"prettier": "^2.5.1",
|
|
172
174
|
"proxyquire": "^2.1.0",
|
|
173
175
|
"qs": "^6.9.4",
|
|
174
176
|
"rethinkdb": "file:test/mock/rethinkdb",
|