@contrast/agent 4.25.2 → 4.25.4
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/lib/assess/express/sinks/xss.js +1 -1
- package/lib/assess/fastify/sinks/unvalidated-redirect.js +1 -1
- package/lib/assess/fastify/sinks/xss.js +2 -2
- package/lib/assess/hapi/sinks/unvalidated-redirect.js +1 -1
- package/lib/assess/hapi/sinks/xss.js +1 -1
- package/lib/assess/koa/sinks/unvalidated-redirect.js +1 -1
- package/lib/assess/koa/sinks/xss.js +1 -1
- package/lib/assess/loopback4/sinks/xss.js +1 -1
- package/lib/assess/membrane/deserialization-membrane.js +1 -1
- package/lib/assess/membrane/source-membrane.js +2 -2
- package/lib/assess/models/call-context.js +123 -162
- package/lib/assess/propagators/JSON/stringify.js +3 -2
- package/lib/assess/propagators/array-prototype-join.js +1 -1
- package/lib/assess/propagators/common.js +2 -2
- package/lib/assess/propagators/fastify-static/allowed-path.js +1 -1
- package/lib/assess/propagators/handlebars-escape-expresssion.js +1 -1
- package/lib/assess/propagators/joi/boolean.js +1 -1
- package/lib/assess/propagators/joi/number.js +1 -1
- package/lib/assess/propagators/joi/string-base.js +1 -1
- package/lib/assess/propagators/joi/string-schema.js +1 -1
- package/lib/assess/propagators/manager.js +1 -1
- package/lib/assess/propagators/mongoose/helpers.js +3 -1
- package/lib/assess/propagators/mongoose/string.js +1 -1
- package/lib/assess/propagators/number.js +1 -1
- package/lib/assess/propagators/path/basename.js +2 -2
- package/lib/assess/propagators/path/dirname.js +2 -2
- package/lib/assess/propagators/path/extname.js +2 -2
- package/lib/assess/propagators/querystring/escape.js +1 -1
- package/lib/assess/propagators/querystring/parse.js +2 -3
- package/lib/assess/propagators/querystring/stringify.js +3 -3
- package/lib/assess/propagators/querystring/unescape.js +2 -2
- package/lib/assess/propagators/sequelize/sql-string-escape.js +1 -1
- package/lib/assess/propagators/sequelize/sql-string-format-named-parameters.js +1 -1
- package/lib/assess/propagators/sequelize/sql-string-format.js +1 -1
- package/lib/assess/propagators/string-prototype-replace.js +10 -11
- package/lib/assess/propagators/string-prototype-split.js +6 -6
- package/lib/assess/propagators/string-prototype-trim.js +3 -3
- package/lib/assess/propagators/template-escape.js +2 -2
- package/lib/assess/propagators/templates.js +1 -1
- package/lib/assess/propagators/url/utils.js +1 -1
- package/lib/assess/propagators/v8/init-hooks.js +1 -1
- package/lib/assess/propagators/validator/init-hooks.js +2 -2
- package/lib/assess/restify/session.js +3 -1
- package/lib/assess/restify/sinks/unvalidated-redirect.js +1 -1
- package/lib/assess/restify/sinks/xss.js +1 -1
- package/lib/assess/sinks/common.js +2 -1
- package/lib/assess/sinks/dustjs-linkedin-xss.js +1 -1
- package/lib/assess/sinks/dynamo.js +1 -1
- package/lib/assess/sinks/hapi-16-xss.js +1 -1
- package/lib/assess/sinks/libxmljs-xxe.js +1 -1
- package/lib/assess/sinks/mongodb.js +2 -2
- package/lib/assess/sinks/rethinkdb-nosql-injection.js +2 -2
- package/lib/assess/sources/event-handler.js +2 -2
- package/lib/assess/spdy/sinks/xss.js +1 -1
- package/lib/core/hapi/utils.js +3 -2
- package/lib/core/stacktrace.js +5 -2
- package/lib/hooks/express-session.js +1 -1
- package/lib/list-installed.js +1 -1
- package/package.json +1 -1
|
@@ -80,7 +80,7 @@ class FastifyRedirectSink {
|
|
|
80
80
|
const url = typeof code === 'string' ? code : data.args[1];
|
|
81
81
|
|
|
82
82
|
if (isVulnerable({ input: url, disallowedTags, requiredTags })) {
|
|
83
|
-
const ctxt =
|
|
83
|
+
const ctxt = CallContext.create({
|
|
84
84
|
obj: Reply,
|
|
85
85
|
args: [url],
|
|
86
86
|
result: url
|
|
@@ -209,13 +209,13 @@ class FastifyXssSink {
|
|
|
209
209
|
const replyState = AsyncStorage.get(KEYS.FASTIFY_REPLY_SEND_STATE);
|
|
210
210
|
// If the handler called Reply.send with a vuln report that stack. Otherwise just report the current stack
|
|
211
211
|
const ctxt = replyState
|
|
212
|
-
?
|
|
212
|
+
? CallContext.create({
|
|
213
213
|
obj: replyState.reply,
|
|
214
214
|
args: [replyState.payload],
|
|
215
215
|
result: null,
|
|
216
216
|
stacktrace: replyState.stack
|
|
217
217
|
})
|
|
218
|
-
:
|
|
218
|
+
: CallContext.create({
|
|
219
219
|
obj: data.obj,
|
|
220
220
|
args: [payload],
|
|
221
221
|
result: null,
|
|
@@ -98,7 +98,7 @@ class KoaXssSink {
|
|
|
98
98
|
const { _cs_stack } = ctx;
|
|
99
99
|
// The CallContext instance will use _cs_stack function if defined,
|
|
100
100
|
// otherwise will generate one based on stackOpts
|
|
101
|
-
const ctxt =
|
|
101
|
+
const ctxt = CallContext.create({
|
|
102
102
|
obj: ctx.response,
|
|
103
103
|
args: [body],
|
|
104
104
|
result: body,
|
|
@@ -149,7 +149,7 @@ module.exports = class SourceMembrane extends Membrane {
|
|
|
149
149
|
makeCallContext(object, constructorOpt) {
|
|
150
150
|
// capture the source of all the properties now, not when a string is
|
|
151
151
|
// referenced.
|
|
152
|
-
const context =
|
|
152
|
+
const context = CallContext.create({
|
|
153
153
|
obj: 'IncomingMessage',
|
|
154
154
|
args: [''],
|
|
155
155
|
result: object,
|
|
@@ -202,7 +202,7 @@ module.exports = class SourceMembrane extends Membrane {
|
|
|
202
202
|
*/
|
|
203
203
|
setTrackingData(trackResult, metadata) {
|
|
204
204
|
const { str: tracked, props: trackData } = trackResult;
|
|
205
|
-
const context =
|
|
205
|
+
const context = CallContext.create({
|
|
206
206
|
obj: 'IncomingMessage',
|
|
207
207
|
args: [metadata.path],
|
|
208
208
|
result: tracked,
|
|
@@ -13,9 +13,9 @@ 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 _ = require('lodash');
|
|
17
18
|
const util = require('util');
|
|
18
|
-
const CleanStack = require('../../util/clean-stack');
|
|
19
19
|
const tracker = require('../../tracker');
|
|
20
20
|
const stackFactory = require('../../core/stacktrace').singleton;
|
|
21
21
|
const { PROXY_TARGET } = require('../../../lib/constants');
|
|
@@ -25,147 +25,26 @@ const { toUntrackedString } = require('../utils');
|
|
|
25
25
|
/**
|
|
26
26
|
* Holds information about the call context of a function
|
|
27
27
|
*/
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
* Create a CallContext.
|
|
31
|
-
*
|
|
32
|
-
* @param {Object} obj - the 'this' for the finding
|
|
33
|
-
* @param {Array} args - arguments passed to the function
|
|
34
|
-
* @param {*} result - return value
|
|
35
|
-
* @param {CallSite[]} stack - the callstack for the event
|
|
36
|
-
*/
|
|
37
|
-
constructor(...rest) {
|
|
38
|
-
if (rest.length === 1 && rest[0] !== undefined) {
|
|
39
|
-
this.init(rest[0]);
|
|
40
|
-
} else {
|
|
41
|
-
this.initLegacy(...rest);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Initialize from parameterized constructor option.
|
|
47
|
-
* @param {object} data constructor params
|
|
48
|
-
*/
|
|
49
|
-
init(data) {
|
|
50
|
-
const {
|
|
51
|
-
obj = {},
|
|
52
|
-
args = [],
|
|
53
|
-
result,
|
|
54
|
-
stackOpts = {
|
|
55
|
-
constructorOpt: data.hooked,
|
|
56
|
-
prependFrames: null
|
|
57
|
-
}
|
|
58
|
-
} = data;
|
|
59
|
-
|
|
60
|
-
const stacktrace =
|
|
61
|
-
data.stacktrace ||
|
|
62
|
-
stackFactory.createSnapshot({
|
|
63
|
-
constructorOpt: stackOpts.constructorOpt
|
|
64
|
-
});
|
|
65
|
-
|
|
28
|
+
class CallContext {
|
|
29
|
+
constructor({ obj = {}, args = [], result }) {
|
|
66
30
|
this.obj = obj;
|
|
67
31
|
this.args = args;
|
|
68
32
|
this.result = result;
|
|
69
|
-
|
|
70
|
-
Object.defineProperty(this, 'stack', {
|
|
71
|
-
get() {
|
|
72
|
-
if (!this._stack) {
|
|
73
|
-
this._stack = stacktrace();
|
|
74
|
-
}
|
|
75
|
-
return this._stack;
|
|
76
|
-
},
|
|
77
|
-
set(value) {
|
|
78
|
-
this._stack = value;
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Initialize from array of constructor options. This will go away once all
|
|
85
|
-
* callers use params e.g. `ApplicaitonContext` will need conversion.
|
|
86
|
-
* @param {array} rest array of constructor args
|
|
87
|
-
*/
|
|
88
|
-
initLegacy(...rest) {
|
|
89
|
-
const obj = rest[0] || {};
|
|
90
|
-
const args = rest[1] || [];
|
|
91
|
-
const result = rest[2];
|
|
92
|
-
const stack = rest[3];
|
|
93
|
-
this.obj = obj;
|
|
94
|
-
this.args = args;
|
|
95
|
-
this.result = result;
|
|
96
|
-
decorateCallContext(this, stack || new CleanStack());
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
static isTracked(str) {
|
|
100
|
-
if (tracker.getData(str)) {
|
|
101
|
-
return true;
|
|
102
|
-
}
|
|
103
|
-
return !!(str && typeof str === 'object' && str[PROXY_TARGET]);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
static hasTrackedArg(arg, iteration = 0) {
|
|
107
|
-
if (tracker.getData(arg)) {
|
|
108
|
-
return true;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (arg && typeof arg === 'object') {
|
|
112
|
-
|
|
113
|
-
for (const key in arg) {
|
|
114
|
-
if (tracker.getData(arg[key])) {
|
|
115
|
-
return true;
|
|
116
|
-
}
|
|
117
|
-
if (arg[key] && typeof arg[key] === 'object' && iteration < 100) {
|
|
118
|
-
return CallContext.hasTrackedArg(arg[key], iteration += 1);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return false;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// eslint-disable-next-line complexity
|
|
126
|
-
static getDisplayRange(arg, orgArg = arg, iteration = 0) {
|
|
127
|
-
if (tracker.getData(arg)) {
|
|
128
|
-
return new TagRange(0, arg.length - 1, 'untrusted');
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (arg && typeof arg === 'object') {
|
|
132
|
-
for (const key in arg) {
|
|
133
|
-
if (arg[key] && typeof arg[key] === 'object' && iteration < 5) {
|
|
134
|
-
const nestedDisplayRange = CallContext.getDisplayRange(arg[key], orgArg, iteration += 1);
|
|
135
|
-
if (!_.isEmpty(nestedDisplayRange)) {
|
|
136
|
-
return nestedDisplayRange;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
const trackedData = tracker.getData(arg[key]);
|
|
140
|
-
if (trackedData && trackedData.tagRanges.length > 0) {
|
|
141
|
-
const { start, stop } = trackedData.tagRanges[0];
|
|
142
|
-
const offset = Array.isArray(orgArg) ? 2 : 0;
|
|
143
|
-
const taintedString = arg[key].substring(start, stop + 1);
|
|
144
|
-
const taintRangeStart = CallContext.valueString(orgArg).indexOf(taintedString) + offset;
|
|
145
|
-
if (taintRangeStart === -1) {
|
|
146
|
-
// If tracked string is not in the abbreviated stringified obj, disable highlighting
|
|
147
|
-
return new TagRange(0, 0, 'disable-highlighting');
|
|
148
|
-
}
|
|
149
|
-
return new TagRange(taintRangeStart, taintRangeStart + taintedString.length - 1, 'untrusted');
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
return {};
|
|
154
33
|
}
|
|
155
34
|
|
|
156
35
|
set result(result) {
|
|
157
|
-
this.__result =
|
|
158
|
-
this.resultTracked =
|
|
36
|
+
this.__result = valueString(result);
|
|
37
|
+
this.resultTracked = isTracked(result);
|
|
159
38
|
}
|
|
160
39
|
get result() {
|
|
161
40
|
return this.__result;
|
|
162
41
|
}
|
|
163
42
|
|
|
164
43
|
set args(args) {
|
|
165
|
-
this.__args = args.map(
|
|
166
|
-
this.argsTracked = args.map((arg) =>
|
|
167
|
-
this.hasArgsTracked = args.map((arg) =>
|
|
168
|
-
this.argsDisplayRanges = args.map((arg) =>
|
|
44
|
+
this.__args = args.map(valueString);
|
|
45
|
+
this.argsTracked = args.map((arg) => isTracked(arg));
|
|
46
|
+
this.hasArgsTracked = args.map((arg) => hasTrackedArg(arg));
|
|
47
|
+
this.argsDisplayRanges = args.map((arg) => getDisplayRange(arg));
|
|
169
48
|
}
|
|
170
49
|
|
|
171
50
|
get args() {
|
|
@@ -173,53 +52,135 @@ module.exports = class CallContext {
|
|
|
173
52
|
}
|
|
174
53
|
|
|
175
54
|
set obj(obj) {
|
|
176
|
-
this.__obj =
|
|
177
|
-
this.objTracked =
|
|
55
|
+
this.__obj = valueString(obj);
|
|
56
|
+
this.objTracked = isTracked(obj);
|
|
178
57
|
}
|
|
179
58
|
get obj() {
|
|
180
59
|
return this.__obj;
|
|
181
60
|
}
|
|
61
|
+
}
|
|
182
62
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
*/
|
|
190
|
-
static valueString(value) {
|
|
191
|
-
if (_.isString(value)) {
|
|
192
|
-
return toUntrackedString(value);
|
|
193
|
-
}
|
|
63
|
+
function isTracked(str) {
|
|
64
|
+
if (tracker.getData(str)) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
return !!(str && typeof str === 'object' && str[PROXY_TARGET]);
|
|
68
|
+
}
|
|
194
69
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
70
|
+
function hasTrackedArg(arg, iteration = 0) {
|
|
71
|
+
if (tracker.getData(arg)) {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
198
74
|
|
|
199
|
-
|
|
75
|
+
if (arg && typeof arg === 'object') {
|
|
200
76
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
.inspect(value)
|
|
205
|
-
.replace(/(\n|\s+)/g, (match) => (match === '\n' ? '' : ' '));
|
|
206
|
-
if (str.length > 50) {
|
|
207
|
-
str = str.substring(0, 50);
|
|
208
|
-
str += '...';
|
|
77
|
+
for (const key in arg) {
|
|
78
|
+
if (tracker.getData(arg[key])) {
|
|
79
|
+
return true;
|
|
209
80
|
}
|
|
81
|
+
if (arg[key] && typeof arg[key] === 'object' && iteration < 100) {
|
|
82
|
+
return hasTrackedArg(arg[key], iteration += 1);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// eslint-disable-next-line complexity
|
|
90
|
+
function getDisplayRange(arg, orgArg = arg, iteration = 0) {
|
|
91
|
+
if (tracker.getData(arg)) {
|
|
92
|
+
return new TagRange(0, arg.length - 1, 'untrusted');
|
|
93
|
+
}
|
|
210
94
|
|
|
211
|
-
|
|
95
|
+
if (arg && typeof arg === 'object') {
|
|
96
|
+
for (const key in arg) {
|
|
97
|
+
if (arg[key] && typeof arg[key] === 'object' && iteration < 5) {
|
|
98
|
+
const nestedDisplayRange = getDisplayRange(arg[key], orgArg, iteration += 1);
|
|
99
|
+
if (!_.isEmpty(nestedDisplayRange)) {
|
|
100
|
+
return nestedDisplayRange;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const trackedData = tracker.getData(arg[key]);
|
|
104
|
+
if (trackedData && trackedData.tagRanges.length > 0) {
|
|
105
|
+
const { start, stop } = trackedData.tagRanges[0];
|
|
106
|
+
const offset = Array.isArray(orgArg) ? 2 : 0;
|
|
107
|
+
const taintedString = arg[key].substring(start, stop + 1);
|
|
108
|
+
const taintRangeStart = valueString(orgArg).indexOf(taintedString) + offset;
|
|
109
|
+
if (taintRangeStart === -1) {
|
|
110
|
+
// If tracked string is not in the abbreviated stringified obj, disable highlighting
|
|
111
|
+
return new TagRange(0, 0, 'disable-highlighting');
|
|
112
|
+
}
|
|
113
|
+
return new TagRange(taintRangeStart, taintRangeStart + taintedString.length - 1, 'untrusted');
|
|
114
|
+
}
|
|
212
115
|
}
|
|
213
|
-
return type;
|
|
214
116
|
}
|
|
215
|
-
};
|
|
117
|
+
return {};
|
|
118
|
+
}
|
|
216
119
|
|
|
217
120
|
/**
|
|
218
|
-
*
|
|
219
|
-
*
|
|
121
|
+
* Returns either the value of a string passed into it, or the constructor
|
|
122
|
+
* name for an object passed into it.
|
|
123
|
+
* @static
|
|
124
|
+
* @param {*} value
|
|
125
|
+
* @return {string}
|
|
220
126
|
*/
|
|
221
|
-
|
|
127
|
+
function valueString(value) {
|
|
128
|
+
if (_.isString(value)) {
|
|
129
|
+
return toUntrackedString(value);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (_.isNumber(value)) {
|
|
133
|
+
return value.toString();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const type = _.get(value, 'constructor.name', 'null');
|
|
137
|
+
|
|
138
|
+
if ((type === 'Object' || type === 'Array') && value) {
|
|
139
|
+
// make string representation uniform with no new lines and consistent spaces
|
|
140
|
+
let str = util
|
|
141
|
+
.inspect(value)
|
|
142
|
+
.replace(/(\n|\s+)/g, (match) => (match === '\n' ? '' : ' '));
|
|
143
|
+
if (str.length > 50) {
|
|
144
|
+
str = str.substring(0, 50);
|
|
145
|
+
str += '...';
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return str;
|
|
149
|
+
}
|
|
150
|
+
return type;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function create(params) {
|
|
154
|
+
const instance = new CallContext(params);
|
|
155
|
+
const snapshot = params.stacktrace || stackFactory.createSnapshot({
|
|
156
|
+
constructorOpt: params.hooked
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
let stack;
|
|
160
|
+
|
|
161
|
+
// If this occurs within the constructor it will leak all references within
|
|
162
|
+
// the snapshot's closure.
|
|
222
163
|
Object.defineProperty(instance, 'stack', {
|
|
223
|
-
|
|
164
|
+
enumerable: true,
|
|
165
|
+
configurable: true,
|
|
166
|
+
get() {
|
|
167
|
+
if (!stack) {
|
|
168
|
+
stack = snapshot();
|
|
169
|
+
}
|
|
170
|
+
return stack;
|
|
171
|
+
},
|
|
172
|
+
set(value) {
|
|
173
|
+
stack = value;
|
|
174
|
+
}
|
|
224
175
|
});
|
|
176
|
+
|
|
177
|
+
return instance;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
module.exports = {
|
|
181
|
+
create,
|
|
182
|
+
valueString,
|
|
183
|
+
hasTrackedArg,
|
|
184
|
+
isTracked,
|
|
185
|
+
getDisplayRange
|
|
225
186
|
};
|
|
@@ -250,6 +250,7 @@ module.exports.handle = function() {
|
|
|
250
250
|
data.args = [input, contrastReplacer, space];
|
|
251
251
|
},
|
|
252
252
|
|
|
253
|
+
// eslint-disable-next-line complexity
|
|
253
254
|
post(data) {
|
|
254
255
|
if (!data.metadata.propagate) {
|
|
255
256
|
return data.result;
|
|
@@ -300,7 +301,7 @@ module.exports.handle = function() {
|
|
|
300
301
|
|
|
301
302
|
customSources.push(
|
|
302
303
|
new SourceEvent({
|
|
303
|
-
context:
|
|
304
|
+
context: CallContext.create({
|
|
304
305
|
obj,
|
|
305
306
|
args: data.args,
|
|
306
307
|
result: data.result,
|
|
@@ -341,7 +342,7 @@ module.exports.handle = function() {
|
|
|
341
342
|
}
|
|
342
343
|
|
|
343
344
|
props.event = new PropagationEvent({
|
|
344
|
-
context:
|
|
345
|
+
context: CallContext.create(data),
|
|
345
346
|
signature: sig,
|
|
346
347
|
tagRanges: props.tagRanges,
|
|
347
348
|
source: 'P',
|
|
@@ -149,7 +149,7 @@ function createEvent(
|
|
|
149
149
|
srcType = 'P';
|
|
150
150
|
}
|
|
151
151
|
const signature = new Signature('Array.prototype.join');
|
|
152
|
-
const context =
|
|
152
|
+
const context = CallContext.create(data);
|
|
153
153
|
const event = new PropagationEvent({
|
|
154
154
|
context,
|
|
155
155
|
signature,
|
|
@@ -94,7 +94,7 @@ const findPropagatorInPolicy = (method) => {
|
|
|
94
94
|
*/
|
|
95
95
|
const createEvent = ({ tagRanges, method, parents }, data) => {
|
|
96
96
|
const signature = new Signature(method);
|
|
97
|
-
const context =
|
|
97
|
+
const context = CallContext.create(data);
|
|
98
98
|
const prop = findPropagatorInPolicy(method);
|
|
99
99
|
return new PropagationEvent({
|
|
100
100
|
context,
|
|
@@ -118,7 +118,7 @@ const trackResult = (metadata, data) => {
|
|
|
118
118
|
const tracked = tracker.track(data.result);
|
|
119
119
|
if (tracked) {
|
|
120
120
|
tracked.props.tagRanges = metadata.tagRanges;
|
|
121
|
-
tracked.props.event = createEvent(metadata, data);
|
|
121
|
+
tracked.props.event = createEvent(metadata, data);
|
|
122
122
|
data.result = tracked.str;
|
|
123
123
|
}
|
|
124
124
|
}
|
|
@@ -59,7 +59,7 @@ module.exports.handle = function handle() {
|
|
|
59
59
|
);
|
|
60
60
|
tagRangeUtil.removeInPlace(trackingData.tagRanges, ['untrusted']);
|
|
61
61
|
|
|
62
|
-
const context =
|
|
62
|
+
const context = CallContext.create(data);
|
|
63
63
|
const event = new PropagationEvent({
|
|
64
64
|
context,
|
|
65
65
|
signature: new Signature('fastify-static.allowedPath'),
|
|
@@ -55,7 +55,7 @@ function patchUtilsExport(utilsExport) {
|
|
|
55
55
|
);
|
|
56
56
|
|
|
57
57
|
const event = new PropagationEvent({
|
|
58
|
-
context:
|
|
58
|
+
context: CallContext.create(data),
|
|
59
59
|
parents: [trackData.event],
|
|
60
60
|
signature: new Signature(
|
|
61
61
|
'handlebars/dist/cjs/handlebars/utils.escapeExpression'
|
|
@@ -50,7 +50,7 @@ function instrumentJoiBoolean(boolean) {
|
|
|
50
50
|
new TagRange(0, data.args[0].length - 1, 'alphanum-space-hyphen')
|
|
51
51
|
);
|
|
52
52
|
trackingData.event = new PropagationEvent({
|
|
53
|
-
context:
|
|
53
|
+
context: CallContext.create(data),
|
|
54
54
|
signature: new Signature('joi.boolean.coerce'),
|
|
55
55
|
tagRanges: trackingData.tagRanges,
|
|
56
56
|
source: 'P',
|
|
@@ -49,7 +49,7 @@ function instrumentJoiNumber(number) {
|
|
|
49
49
|
new TagRange(0, data.args[0].length - 1, 'limited-chars')
|
|
50
50
|
);
|
|
51
51
|
trackingData.event = new PropagationEvent({
|
|
52
|
-
context:
|
|
52
|
+
context: CallContext.create(data),
|
|
53
53
|
signature: new Signature('joi.number.coerce'),
|
|
54
54
|
tagRanges: trackingData.tagRanges,
|
|
55
55
|
source: 'P',
|
|
@@ -87,7 +87,7 @@ function instrumentJoiString(string) {
|
|
|
87
87
|
new TagRange(0, input.length - 1, 'string-type-checked')
|
|
88
88
|
);
|
|
89
89
|
trackingData.event = new PropagationEvent({
|
|
90
|
-
context:
|
|
90
|
+
context: CallContext.create(data),
|
|
91
91
|
signature: new Signature('joi.string.validate'),
|
|
92
92
|
tagRanges: trackingData.tagRanges,
|
|
93
93
|
source: 'P',
|
|
@@ -179,7 +179,7 @@ function createPropagationEvent({
|
|
|
179
179
|
}) {
|
|
180
180
|
const { event: lastEvent } = trackedArgsData;
|
|
181
181
|
|
|
182
|
-
const context =
|
|
182
|
+
const context = CallContext.create(data);
|
|
183
183
|
const signature = new Signature(`joi.string.${joiMethod}`);
|
|
184
184
|
|
|
185
185
|
const event = new PropagationEvent({
|
|
@@ -84,7 +84,7 @@ module.exports = function Propagator(agent, propagationDescriptor) {
|
|
|
84
84
|
const sourceMeta = getSourcesMetadata(sources);
|
|
85
85
|
const { tagRanges: sourceTagRanges, events: sourceEvents } = sourceMeta;
|
|
86
86
|
const sig = new Signature(signature);
|
|
87
|
-
const ctxt =
|
|
87
|
+
const ctxt = CallContext.create(data);
|
|
88
88
|
const event = new PropagationEvent({
|
|
89
89
|
context: ctxt,
|
|
90
90
|
signature: sig,
|
|
@@ -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 TagRange = require('../../models/tag-range');
|
|
16
18
|
const { CallContext, PropagationEvent, Signature } = require('../../models');
|
|
17
19
|
|
|
@@ -40,7 +42,7 @@ const tagCustomValidatedValues = (values, data, tracker, tagRangeUtil) => {
|
|
|
40
42
|
);
|
|
41
43
|
|
|
42
44
|
props.event = new PropagationEvent({
|
|
43
|
-
context:
|
|
45
|
+
context: CallContext.create(data),
|
|
44
46
|
signature: new Signature('mongoose.mixed.doValidateSync'),
|
|
45
47
|
tagRanges: props.tagRanges,
|
|
46
48
|
source: 'P',
|
|
@@ -85,7 +85,7 @@ const doValidateSyncPatcher = (SchemaString) => {
|
|
|
85
85
|
);
|
|
86
86
|
|
|
87
87
|
props.event = new PropagationEvent({
|
|
88
|
-
context:
|
|
88
|
+
context: CallContext.create(data),
|
|
89
89
|
signature: new Signature('mongoose.string.doValidateSync'),
|
|
90
90
|
tagRanges: props.tagRanges,
|
|
91
91
|
source: 'P',
|
|
@@ -73,14 +73,14 @@ module.exports.handle = function handle() {
|
|
|
73
73
|
if (tracked) {
|
|
74
74
|
tracked.props.tagRanges = tagRanges;
|
|
75
75
|
tracked.props.event = new PropagationEvent({
|
|
76
|
-
context:
|
|
76
|
+
context: CallContext.create(data),
|
|
77
77
|
parents: [parentEvent],
|
|
78
78
|
signature,
|
|
79
79
|
source: 'P',
|
|
80
80
|
tagRanges,
|
|
81
81
|
target: 'R'
|
|
82
82
|
});
|
|
83
|
-
data.result = tracked.str;
|
|
83
|
+
data.result = tracked.str;
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
});
|
|
@@ -62,14 +62,14 @@ module.exports.handle = function handle() {
|
|
|
62
62
|
if (tracked) {
|
|
63
63
|
tracked.props.tagRanges = tagRanges;
|
|
64
64
|
tracked.props.event = new PropagationEvent({
|
|
65
|
-
context:
|
|
65
|
+
context: CallContext.create(data),
|
|
66
66
|
parents: [parentEvent],
|
|
67
67
|
signature,
|
|
68
68
|
source: 'P',
|
|
69
69
|
tagRanges,
|
|
70
70
|
target: 'R'
|
|
71
71
|
});
|
|
72
|
-
data.result = tracked.str;
|
|
72
|
+
data.result = tracked.str;
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
});
|
|
@@ -67,14 +67,14 @@ module.exports.handle = function handle() {
|
|
|
67
67
|
if (tracked) {
|
|
68
68
|
tracked.props.tagRanges = tagRanges;
|
|
69
69
|
tracked.props.event = new PropagationEvent({
|
|
70
|
-
context:
|
|
70
|
+
context: CallContext.create(data),
|
|
71
71
|
parents: [parentEvent],
|
|
72
72
|
signature,
|
|
73
73
|
source: 'P',
|
|
74
74
|
tagRanges,
|
|
75
75
|
target: 'R'
|
|
76
76
|
});
|
|
77
|
-
data.result = tracked.str;
|
|
77
|
+
data.result = tracked.str;
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
});
|
|
@@ -36,7 +36,6 @@ function getUnescapeWrapper(data, unescape) {
|
|
|
36
36
|
|
|
37
37
|
function unescapeWrapper(part) {
|
|
38
38
|
let result;
|
|
39
|
-
let resultData;
|
|
40
39
|
const start = input.indexOf(part, data.curPos);
|
|
41
40
|
// any tag ranges overlapping current part?
|
|
42
41
|
const tagRanges = tagRangeUtil.trim(
|
|
@@ -58,11 +57,11 @@ function getUnescapeWrapper(data, unescape) {
|
|
|
58
57
|
|
|
59
58
|
// allow propagation through unescape
|
|
60
59
|
result = Scopes.runInAllowAllScope(() => unescape(result));
|
|
61
|
-
resultData = tracker.getData(result);
|
|
60
|
+
const resultData = tracker.getData(result);
|
|
62
61
|
|
|
63
62
|
if (resultData) {
|
|
64
63
|
resultData.event = new PropagationEvent({
|
|
65
|
-
context:
|
|
64
|
+
context: CallContext.create({
|
|
66
65
|
...data,
|
|
67
66
|
obj: null,
|
|
68
67
|
args: data.origArgs,
|
|
@@ -289,12 +289,12 @@ function post(data) {
|
|
|
289
289
|
const sorted = _.sortBy(data.state.tagRanges, 'start');
|
|
290
290
|
tracked.props.tagRanges = [];
|
|
291
291
|
tagRangeUtil.addAllInPlace(tracked.props.tagRanges, sorted);
|
|
292
|
-
|
|
292
|
+
|
|
293
293
|
// stringify / encode
|
|
294
294
|
const method = data.funcKey.split('.')[1];
|
|
295
|
-
|
|
295
|
+
|
|
296
296
|
tracked.props.event = new PropagationEvent({
|
|
297
|
-
context:
|
|
297
|
+
context: CallContext.create({
|
|
298
298
|
...data,
|
|
299
299
|
args: data.state.origArgs,
|
|
300
300
|
obj: null
|
|
@@ -42,7 +42,7 @@ function handler(data) {
|
|
|
42
42
|
if (tracked) {
|
|
43
43
|
tracked.props.tagRanges = tagRanges;
|
|
44
44
|
tracked.props.event = new PropagationEvent({
|
|
45
|
-
context:
|
|
45
|
+
context: CallContext.create({
|
|
46
46
|
...data,
|
|
47
47
|
obj: null
|
|
48
48
|
}),
|
|
@@ -53,7 +53,7 @@ function handler(data) {
|
|
|
53
53
|
target: 'R',
|
|
54
54
|
untags: ['url-encoded']
|
|
55
55
|
});
|
|
56
|
-
data.result = tracked.str;
|
|
56
|
+
data.result = tracked.str;
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
|
@@ -45,7 +45,7 @@ module.exports.handle = function() {
|
|
|
45
45
|
);
|
|
46
46
|
|
|
47
47
|
const event = new PropagationEvent({
|
|
48
|
-
context:
|
|
48
|
+
context: CallContext.create(data),
|
|
49
49
|
parents: [trackingData.event],
|
|
50
50
|
signature: new Signature('sequelize/lib/sql-string.escape'),
|
|
51
51
|
source: 'P',
|
|
@@ -127,7 +127,7 @@ module.exports.handle = function() {
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
const event = new PropagationEvent({
|
|
130
|
-
context:
|
|
130
|
+
context: CallContext.create(data),
|
|
131
131
|
parents: [trackingData.event],
|
|
132
132
|
signature: new Signature(
|
|
133
133
|
'sequelize/lib/sql-string.formatNamedParameters'
|
|
@@ -88,7 +88,7 @@ module.exports.handle = function() {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
const event = new PropagationEvent({
|
|
91
|
-
context:
|
|
91
|
+
context: CallContext.create(data),
|
|
92
92
|
parents: [trackingData.event],
|
|
93
93
|
signature: new Signature('sequelize/lib/sql-string.format'),
|
|
94
94
|
source: 'P',
|
|
@@ -16,7 +16,6 @@ Copyright: 2022 Contrast Security, Inc
|
|
|
16
16
|
* String.prototype.replace Propagation Provider module.
|
|
17
17
|
* @module lib/assess/propagators/String.prototype.replace
|
|
18
18
|
*/
|
|
19
|
-
|
|
20
19
|
'use strict';
|
|
21
20
|
|
|
22
21
|
const _ = require('lodash');
|
|
@@ -183,10 +182,10 @@ function findOffset(args) {
|
|
|
183
182
|
return _.isNumber(args[1])
|
|
184
183
|
? args[1] // no general capture groups
|
|
185
184
|
: _.isNumber(args[args.length - 2])
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
185
|
+
? args[args.length - 2] // no named-capture groups
|
|
186
|
+
: _.isNumber(args[args.length - 3])
|
|
187
|
+
? args[args.length - 3] // w/ named-capture groups
|
|
188
|
+
: (() => {
|
|
190
189
|
// Invalid call at this point though
|
|
191
190
|
for (const arg of args) {
|
|
192
191
|
if (_.isNumber(arg)) return arg;
|
|
@@ -595,7 +594,7 @@ function trackFinalResult(callContext) {
|
|
|
595
594
|
tagRanges: trackData.resultTagRanges,
|
|
596
595
|
result: tracked.str
|
|
597
596
|
});
|
|
598
|
-
tracked.props.tagRanges = trackData.resultTagRanges;
|
|
597
|
+
tracked.props.tagRanges = trackData.resultTagRanges;
|
|
599
598
|
callContext.result = tracked.str;
|
|
600
599
|
}
|
|
601
600
|
}
|
|
@@ -614,7 +613,7 @@ function createPropagationEvent({ callContext, tagRanges, result }) {
|
|
|
614
613
|
}
|
|
615
614
|
} = callContext;
|
|
616
615
|
const signature = new Signature(PROPAGATOR_METHOD);
|
|
617
|
-
const context =
|
|
616
|
+
const context = CallContext.create({
|
|
618
617
|
obj,
|
|
619
618
|
args,
|
|
620
619
|
result,
|
|
@@ -646,8 +645,8 @@ function getParentEvents(source, trackData) {
|
|
|
646
645
|
...(source === 'P'
|
|
647
646
|
? [trackData.replacerData.event]
|
|
648
647
|
: source === 'O'
|
|
649
|
-
|
|
650
|
-
|
|
648
|
+
? [trackData.objData.event]
|
|
649
|
+
: [trackData.replacerData.event, trackData.objData.event]),
|
|
651
650
|
...Array.from(trackData.dynamicEvents)
|
|
652
651
|
]);
|
|
653
652
|
}
|
|
@@ -661,8 +660,8 @@ function getSourceType({ objData, replacerData }) {
|
|
|
661
660
|
return objData.tracked && !replacerData.tracked
|
|
662
661
|
? 'O'
|
|
663
662
|
: !objData.tracked && replacerData.tracked
|
|
664
|
-
|
|
665
|
-
|
|
663
|
+
? 'P'
|
|
664
|
+
: 'A';
|
|
666
665
|
}
|
|
667
666
|
|
|
668
667
|
module.exports.coerceReplacer = coerceReplacer;
|
|
@@ -86,7 +86,7 @@ module.exports.handle = {
|
|
|
86
86
|
const oldTagRanges = getTagRanges(origString);
|
|
87
87
|
const oldEvent = getEvent(origString);
|
|
88
88
|
|
|
89
|
-
const ctxt =
|
|
89
|
+
const ctxt = CallContext.create(data);
|
|
90
90
|
|
|
91
91
|
if (args[0].length === 0) {
|
|
92
92
|
/***
|
|
@@ -166,7 +166,7 @@ module.exports.handle = {
|
|
|
166
166
|
const tracked = tracker.track(stringPart);
|
|
167
167
|
if (tracked) {
|
|
168
168
|
tracked.props.tagRanges.push(new TagRange(tagStart, tagStop, tag.tag));
|
|
169
|
-
result[i] = tracked.str;
|
|
169
|
+
result[i] = tracked.str;
|
|
170
170
|
}
|
|
171
171
|
}
|
|
172
172
|
});
|
|
@@ -206,7 +206,7 @@ function handleEmptySeperator(data, oldTagRanges, oldEvent) {
|
|
|
206
206
|
|
|
207
207
|
const { result } = data;
|
|
208
208
|
|
|
209
|
-
const ctxt =
|
|
209
|
+
const ctxt = CallContext.create(data);
|
|
210
210
|
|
|
211
211
|
// map index --> { Event, tagRanges }, so that we can update existing properties in cases where
|
|
212
212
|
// more than one tag was on the same index
|
|
@@ -233,11 +233,11 @@ function handleEmptySeperator(data, oldTagRanges, oldEvent) {
|
|
|
233
233
|
source: 'O',
|
|
234
234
|
target: 'R'
|
|
235
235
|
});
|
|
236
|
-
|
|
236
|
+
|
|
237
237
|
tracked.props.event = event;
|
|
238
238
|
info = { event, tagRanges: tracked.props.tagRanges };
|
|
239
239
|
sharedCharInfo.set(i, info);
|
|
240
|
-
result[i] = tracked.str;
|
|
240
|
+
result[i] = tracked.str;
|
|
241
241
|
}
|
|
242
242
|
}
|
|
243
243
|
|
|
@@ -259,7 +259,7 @@ function transferTracking(origString, resultArray) {
|
|
|
259
259
|
if (tracked) {
|
|
260
260
|
tracked.props.tagRanges = getTagRanges(origString);
|
|
261
261
|
tracked.props.event = getEvent(origString);
|
|
262
|
-
resultArray[i] = tracked.str;
|
|
262
|
+
resultArray[i] = tracked.str;
|
|
263
263
|
}
|
|
264
264
|
}
|
|
265
265
|
return resultArray;
|
|
@@ -45,7 +45,7 @@ function handle(data) {
|
|
|
45
45
|
const tracked = tracker.track(result);
|
|
46
46
|
if (tracked) {
|
|
47
47
|
tracked.props.tagRanges = targetRanges;
|
|
48
|
-
const context =
|
|
48
|
+
const context = CallContext.create(data);
|
|
49
49
|
const event = new PropagationEvent({
|
|
50
50
|
context,
|
|
51
51
|
signature,
|
|
@@ -55,7 +55,7 @@ function handle(data) {
|
|
|
55
55
|
});
|
|
56
56
|
event.parents.push(sourceEvent);
|
|
57
57
|
tracked.props.event = event;
|
|
58
|
-
|
|
59
|
-
data.result = tracked.str;
|
|
58
|
+
|
|
59
|
+
data.result = tracked.str;
|
|
60
60
|
}
|
|
61
61
|
}
|
|
@@ -69,7 +69,7 @@ function propagator(data, tagName, signatureName) {
|
|
|
69
69
|
if (tracked) {
|
|
70
70
|
tracked.props.tagRanges = tagRanges;
|
|
71
71
|
tracked.props.event = new PropagationEvent({
|
|
72
|
-
context:
|
|
72
|
+
context: CallContext.create({
|
|
73
73
|
...data,
|
|
74
74
|
obj: null
|
|
75
75
|
}),
|
|
@@ -80,7 +80,7 @@ function propagator(data, tagName, signatureName) {
|
|
|
80
80
|
tagRanges,
|
|
81
81
|
tags: tagName
|
|
82
82
|
});
|
|
83
|
-
data.result = tracked.str;
|
|
83
|
+
data.result = tracked.str;
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -114,7 +114,7 @@ function buildProperties(props, tagRanges, exps, result, strings, events) {
|
|
|
114
114
|
this,
|
|
115
115
|
[strings].concat(exps.map((exp, i) => `$\{exp${i}}`))
|
|
116
116
|
);
|
|
117
|
-
const ctxt =
|
|
117
|
+
const ctxt = CallContext.create({
|
|
118
118
|
obj: raw,
|
|
119
119
|
args: exps,
|
|
120
120
|
result,
|
|
@@ -39,7 +39,7 @@ module.exports.createEvent = function(
|
|
|
39
39
|
// To be 100% correct we would use result/url (should be the same)
|
|
40
40
|
// for obj/result, but it's nicer to show propagation to the specific part.
|
|
41
41
|
// Since the operation is P2O, we replace O with the url part.
|
|
42
|
-
const context =
|
|
42
|
+
const context = CallContext.create({
|
|
43
43
|
obj: part,
|
|
44
44
|
args,
|
|
45
45
|
result
|
|
@@ -99,7 +99,7 @@ module.exports.handle = function handle() {
|
|
|
99
99
|
tr.stop = data.result.length - 1;
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
|
-
const context =
|
|
102
|
+
const context = CallContext.create(data);
|
|
103
103
|
const event = new PropagationEvent({
|
|
104
104
|
context,
|
|
105
105
|
signature,
|
|
@@ -103,7 +103,7 @@ module.exports.handle = function () {
|
|
|
103
103
|
);
|
|
104
104
|
tagRangeUtil.removeInPlace(trackingData.tagRanges, ['untrusted']);
|
|
105
105
|
|
|
106
|
-
const context =
|
|
106
|
+
const context = CallContext.create(data);
|
|
107
107
|
const event = new PropagationEvent({
|
|
108
108
|
context,
|
|
109
109
|
signature,
|
|
@@ -233,7 +233,7 @@ module.exports.handle = function () {
|
|
|
233
233
|
);
|
|
234
234
|
tagRangeUtil.removeInPlace(trackingData.tagRanges, ['untrusted']);
|
|
235
235
|
|
|
236
|
-
const context =
|
|
236
|
+
const context = CallContext.create(data);
|
|
237
237
|
const event = new PropagationEvent({
|
|
238
238
|
context,
|
|
239
239
|
signature,
|
|
@@ -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 { get } = require('lodash');
|
|
16
18
|
const { CallContext, Signature } = require('../models');
|
|
17
19
|
const patcher = require('../../hooks/patcher');
|
|
@@ -30,7 +32,7 @@ module.exports = function registerSessionHandler(response) {
|
|
|
30
32
|
patchType: PATCH_TYPES.ASSESS_SINK,
|
|
31
33
|
post(data) {
|
|
32
34
|
const options = { cookie: get(data, 'args[2]', {}) };
|
|
33
|
-
const context =
|
|
35
|
+
const context = CallContext.create(data);
|
|
34
36
|
const signature = new Signature({
|
|
35
37
|
moduleName: 'restify-cookies.Response',
|
|
36
38
|
methodName: 'setCookie',
|
|
@@ -441,6 +441,7 @@ module.exports = (agent) => {
|
|
|
441
441
|
// here we will pull the method out of the fn args
|
|
442
442
|
// and replace it on the signature. the assumption
|
|
443
443
|
// is the string to replace is always the last position
|
|
444
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
444
445
|
if (signature.hasOwnProperty('userMethodPosition')) {
|
|
445
446
|
const method = args.splice(signature.userMethodPosition, 1).join();
|
|
446
447
|
const methodArray = signature.methodName.split('.');
|
|
@@ -461,7 +462,7 @@ module.exports = (agent) => {
|
|
|
461
462
|
}
|
|
462
463
|
|
|
463
464
|
if (vulnerableString) {
|
|
464
|
-
const ctxt =
|
|
465
|
+
const ctxt = CallContext.create(data);
|
|
465
466
|
// If we had to create a stacktrace already, use it rather than build
|
|
466
467
|
// another during reporting
|
|
467
468
|
if (stack) {
|
|
@@ -267,7 +267,7 @@ module.exports = ({ common }) => {
|
|
|
267
267
|
);
|
|
268
268
|
|
|
269
269
|
if (vulnerableString.length) {
|
|
270
|
-
const ctxt =
|
|
270
|
+
const ctxt = CallContext.create(data);
|
|
271
271
|
const signature = new Signature({ moduleName: 'aws-sdk', methodName });
|
|
272
272
|
report({ ruleId, signature, input: vulnerableString[0], ctxt });
|
|
273
273
|
}
|
|
@@ -132,7 +132,7 @@ module.exports = ({ common }) => {
|
|
|
132
132
|
|
|
133
133
|
if (doc && !doc.__contrastContext) {
|
|
134
134
|
try {
|
|
135
|
-
const ctxt =
|
|
135
|
+
const ctxt = CallContext.create({
|
|
136
136
|
...data,
|
|
137
137
|
result: null
|
|
138
138
|
});
|
|
@@ -358,7 +358,7 @@ module.exports = ({ common }) => {
|
|
|
358
358
|
*/
|
|
359
359
|
function getCallContext(ctxt, data) {
|
|
360
360
|
if (!ctxt) {
|
|
361
|
-
ctxt =
|
|
361
|
+
ctxt = CallContext.create(data);
|
|
362
362
|
ctxt.signature = data.name;
|
|
363
363
|
}
|
|
364
364
|
ctxt.result = data.result;
|
|
@@ -96,7 +96,7 @@ class Handler {
|
|
|
96
96
|
ruleId: NOSQL_INJECTION,
|
|
97
97
|
signature: matchSignature,
|
|
98
98
|
input: str,
|
|
99
|
-
ctxt:
|
|
99
|
+
ctxt: CallContext.create({
|
|
100
100
|
obj,
|
|
101
101
|
args: [str],
|
|
102
102
|
result: str,
|
|
@@ -118,7 +118,7 @@ class Handler {
|
|
|
118
118
|
ruleId: NOSQL_INJECTION,
|
|
119
119
|
signature: filterSignature,
|
|
120
120
|
input: str,
|
|
121
|
-
ctxt:
|
|
121
|
+
ctxt: CallContext.create({
|
|
122
122
|
obj,
|
|
123
123
|
args: [str],
|
|
124
124
|
result: str,
|
|
@@ -198,7 +198,7 @@ class SourceEventHandler {
|
|
|
198
198
|
|
|
199
199
|
props.tagRanges = this.getTagRanges({ name, result });
|
|
200
200
|
props.event = new SourceEvent({
|
|
201
|
-
context:
|
|
201
|
+
context: CallContext.create({
|
|
202
202
|
obj: 'IncomingMessage {}',
|
|
203
203
|
args: [`${this.typeKey}.${name}`],
|
|
204
204
|
result,
|
|
@@ -241,7 +241,7 @@ class SourceEventHandler {
|
|
|
241
241
|
|
|
242
242
|
const rules = new Set();
|
|
243
243
|
|
|
244
|
-
/*
|
|
244
|
+
/*
|
|
245
245
|
Maybe it's pointless because we set skipEvent to true if appliesToAllAssessRules
|
|
246
246
|
and we won't get here
|
|
247
247
|
*/
|
package/lib/core/hapi/utils.js
CHANGED
|
@@ -59,6 +59,7 @@ utils.httpOnly = function(options) {
|
|
|
59
59
|
* @return {Boolean}
|
|
60
60
|
*/
|
|
61
61
|
utils.vulnerableOption = function({ options, key }) {
|
|
62
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
62
63
|
return options.hasOwnProperty(key) && options[key] !== true;
|
|
63
64
|
};
|
|
64
65
|
|
|
@@ -81,7 +82,7 @@ utils.createSessionContext = function(obj, args, result, source, stackOpts) {
|
|
|
81
82
|
}
|
|
82
83
|
|
|
83
84
|
if (!opts) {
|
|
84
|
-
return
|
|
85
|
+
return CallContext.create({
|
|
85
86
|
obj,
|
|
86
87
|
args,
|
|
87
88
|
result,
|
|
@@ -95,7 +96,7 @@ utils.createSessionContext = function(obj, args, result, source, stackOpts) {
|
|
|
95
96
|
|
|
96
97
|
args[idx] = opts;
|
|
97
98
|
|
|
98
|
-
return
|
|
99
|
+
return CallContext.create({ obj, args, result });
|
|
99
100
|
};
|
|
100
101
|
|
|
101
102
|
/**
|
package/lib/core/stacktrace.js
CHANGED
|
@@ -146,8 +146,11 @@ class Factory {
|
|
|
146
146
|
|
|
147
147
|
if (callsite.isEval()) {
|
|
148
148
|
evalOrigin = Factory.formatFileName(callsite.getEvalOrigin());
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
|
|
150
|
+
const match = evalOrigin.match(EVAL_ORIGIN_REGEX);
|
|
151
|
+
if (match) {
|
|
152
|
+
[, file, lineNumber, columnNumber] = match;
|
|
153
|
+
}
|
|
151
154
|
}
|
|
152
155
|
|
|
153
156
|
file = file || callsite.getFileName();
|
|
@@ -48,7 +48,7 @@ function hook() {
|
|
|
48
48
|
_.set(data.args, '[0].secret', '[HIDDEN]');
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
const ctxt =
|
|
51
|
+
const ctxt = CallContext.create(data);
|
|
52
52
|
// event of when the session was initialized that will be reused for all
|
|
53
53
|
// session findings
|
|
54
54
|
const sessionEvent = new SessionEvent({
|
package/lib/list-installed.js
CHANGED
|
@@ -21,7 +21,7 @@ const {
|
|
|
21
21
|
AGENT_INFO: { SUPPORTED_NPM_VERSIONS },
|
|
22
22
|
} = require('./constants');
|
|
23
23
|
|
|
24
|
-
const VERSION_REGEX = /^npm@(\S+)\s+(\S+)$/m;
|
|
24
|
+
const VERSION_REGEX = /^npm@(\S+)\s+(\S+[\s\S]*)$/m;
|
|
25
25
|
const isWin32 = process.platform === 'win32';
|
|
26
26
|
|
|
27
27
|
const execFile = util.promisify(require('child_process').execFile);
|