@contrast/agent 4.22.0 → 4.22.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.
|
@@ -103,18 +103,25 @@ module.exports = class CallContext {
|
|
|
103
103
|
return !!(str && typeof str === 'object' && str[PROXY_TARGET]);
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
static getDisplayRange(arg) {
|
|
106
|
+
static getDisplayRange(arg, orgArg = arg, iteration = 0) {
|
|
107
107
|
if (tracker.getData(arg)) {
|
|
108
108
|
return new TagRange(0, arg.length - 1, 'untrusted');
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
if (arg && typeof arg === 'object') {
|
|
112
112
|
for (const key in arg) {
|
|
113
|
+
if (arg[key] && typeof arg[key] === 'object' && iteration < 5) {
|
|
114
|
+
const nestedDisplayRange = CallContext.getDisplayRange(arg[key], orgArg, iteration += 1);
|
|
115
|
+
if (!_.isEmpty(nestedDisplayRange)) {
|
|
116
|
+
return nestedDisplayRange;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
113
119
|
const trackedData = tracker.getData(arg[key]);
|
|
114
|
-
if (trackedData) {
|
|
120
|
+
if (trackedData && trackedData.tagRanges.length > 0) {
|
|
115
121
|
const { start, stop } = trackedData.tagRanges[0];
|
|
122
|
+
const offset = Array.isArray(orgArg) ? 2 : 0;
|
|
116
123
|
const taintedString = arg[key].substring(start, stop + 1);
|
|
117
|
-
const taintRangeStart = CallContext.valueString(
|
|
124
|
+
const taintRangeStart = CallContext.valueString(orgArg).indexOf(taintedString) + offset;
|
|
118
125
|
if (taintRangeStart === -1) {
|
|
119
126
|
// If tracked string is not in the abbreviated stringified obj, disable highlighting
|
|
120
127
|
return new TagRange(0, 0, 'disable-highlighting');
|
|
@@ -178,9 +185,9 @@ module.exports = class CallContext {
|
|
|
178
185
|
return value.toString();
|
|
179
186
|
}
|
|
180
187
|
|
|
181
|
-
const
|
|
188
|
+
const type = _.get(value, 'constructor.name', 'null');
|
|
182
189
|
|
|
183
|
-
if (
|
|
190
|
+
if ((type === 'Object' || type === 'Array') && value) {
|
|
184
191
|
// make string representation uniform with no new lines and consistent spaces
|
|
185
192
|
let str = util
|
|
186
193
|
.inspect(value)
|
|
@@ -192,7 +199,7 @@ module.exports = class CallContext {
|
|
|
192
199
|
|
|
193
200
|
return str;
|
|
194
201
|
}
|
|
195
|
-
return
|
|
202
|
+
return type;
|
|
196
203
|
}
|
|
197
204
|
};
|
|
198
205
|
|
|
@@ -19,36 +19,74 @@ const { PATCH_TYPES } = require('../../constants');
|
|
|
19
19
|
const ModuleHook = require('../../hooks/require');
|
|
20
20
|
const patcher = require('../../hooks/patcher');
|
|
21
21
|
const logger = require('../logger')('contrast:arch-component');
|
|
22
|
-
const semver = require('semver');
|
|
23
22
|
|
|
23
|
+
// Architecture component for versions <3.0.0
|
|
24
24
|
ModuleHook.resolve(
|
|
25
25
|
{
|
|
26
26
|
name: 'mongodb',
|
|
27
27
|
file: 'lib/mongo_client.js',
|
|
28
|
-
version: '
|
|
28
|
+
version: '<3.0.0'
|
|
29
29
|
},
|
|
30
|
-
(MongoClient
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
30
|
+
(MongoClient) => {
|
|
31
|
+
patcher.patch(MongoClient, 'connect', {
|
|
32
|
+
name: 'MongoClient.connect.arch_component',
|
|
33
|
+
patchType: PATCH_TYPES.ARCH_COMPONENT,
|
|
34
|
+
alwaysRun: true,
|
|
35
|
+
pre(ctx) {
|
|
36
|
+
// check if typeof callback == 'function'
|
|
37
|
+
// if yes:
|
|
38
|
+
// - MongoClient.connect executes a cb function, which has access to the connection status
|
|
39
|
+
// if not:
|
|
40
|
+
// - MongoClient.connect should return a promise and we can check it's result in another hook, just as before
|
|
41
|
+
const callbackIndex = ctx.args[2] ? 2 : 1;
|
|
42
|
+
if (ctx.args[callbackIndex] instanceof Function || typeof ctx.args[callbackIndex] === 'function') {
|
|
43
|
+
ctx.args[callbackIndex] = patcher.patch(ctx.args[callbackIndex], {
|
|
44
|
+
name: 'MongoClient.connect.callback.arch_component',
|
|
45
|
+
patchType: PATCH_TYPES.ARCH_COMPONENT,
|
|
46
|
+
alwaysRun: true,
|
|
47
|
+
pre(ctx) {
|
|
48
|
+
const [, db] = ctx.args;
|
|
49
|
+
if (db && db.s.topology && db.s.topology.s) {
|
|
50
|
+
try {
|
|
51
|
+
const server = db.s.topology.s.server.s;
|
|
52
|
+
if (server.pool && server.pool.state == 'connected') {
|
|
53
|
+
const connections = server.pool.availableConnections;
|
|
54
|
+
for (const c of connections) {
|
|
55
|
+
agentEmitter.emit('architectureComponent', {
|
|
56
|
+
vendor: 'MongoDB',
|
|
57
|
+
url: `mongodb://${c.host}:${c.port}`,
|
|
58
|
+
remoteHost: '',
|
|
59
|
+
remotePort: c.port
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
} catch (err) {
|
|
64
|
+
logger.warn('unable to report MongoDB architecture component, err: %o', err);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
post(ctx) {
|
|
72
|
+
if (!ctx.result || !ctx.result.then) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// it never gets here if callbacks are used, because the result won't be then-able
|
|
76
|
+
ctx.result.then(db => {
|
|
77
|
+
if (db && db.s && db.s.topology && db.s.topology.s) {
|
|
43
78
|
try {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
79
|
+
const server = db.s.topology.s.server.s;
|
|
80
|
+
if (server.pool && server.pool.state == 'connected') {
|
|
81
|
+
const connections = server.pool.availableConnections;
|
|
82
|
+
for (const c of connections) {
|
|
83
|
+
agentEmitter.emit('architectureComponent', {
|
|
84
|
+
vendor: 'MongoDB',
|
|
85
|
+
url: `mongodb://${c.host}:${c.port}`,
|
|
86
|
+
remoteHost: '',
|
|
87
|
+
remotePort: c.port
|
|
88
|
+
});
|
|
89
|
+
}
|
|
52
90
|
}
|
|
53
91
|
} catch (err) {
|
|
54
92
|
logger.warn(
|
|
@@ -56,60 +94,96 @@ ModuleHook.resolve(
|
|
|
56
94
|
err,
|
|
57
95
|
);
|
|
58
96
|
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
// Architecture component for versions >=3.3.0 <4.0.0
|
|
105
|
+
ModuleHook.resolve(
|
|
106
|
+
{
|
|
107
|
+
name: 'mongodb',
|
|
108
|
+
file: 'lib/mongo_client.js',
|
|
109
|
+
version: '>=3.0.0 <4.0.0'
|
|
110
|
+
},
|
|
111
|
+
(MongoClient, { version }) => {
|
|
112
|
+
patcher.patch(MongoClient.prototype, 'connect', {
|
|
113
|
+
name: 'MongoClient.connect.arch_component',
|
|
114
|
+
patchType: PATCH_TYPES.ARCH_COMPONENT,
|
|
115
|
+
alwaysRun: true,
|
|
116
|
+
post(ctx) {
|
|
117
|
+
if (!ctx.result || !ctx.result.then) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// We should report only when connection is successful
|
|
122
|
+
ctx.result.then(function(client) {
|
|
123
|
+
try {
|
|
124
|
+
const { servers = [] } = ctx.obj.s && ctx.obj.s.options;
|
|
125
|
+
for (const server of servers) {
|
|
126
|
+
agentEmitter.emit('architectureComponent', {
|
|
127
|
+
vendor: 'MongoDB',
|
|
128
|
+
url: `mongodb://${server.host}:${server.port}`,
|
|
129
|
+
remoteHost: '',
|
|
130
|
+
remotePort: server.port,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
} catch (err) {
|
|
134
|
+
logger.warn(
|
|
135
|
+
'unable to report MongoDB architecture component, err: %o',
|
|
136
|
+
err,
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
},
|
|
141
|
+
});
|
|
63
142
|
},
|
|
64
143
|
);
|
|
65
144
|
|
|
66
|
-
|
|
67
|
-
* It's not limited in the require hook to >=4.0.0 because
|
|
68
|
-
* that would result in confusing logs for the customer that
|
|
69
|
-
* we don't support older versions (which is not true) */
|
|
145
|
+
// Architecture component for versions >=4.0.0
|
|
70
146
|
ModuleHook.resolve(
|
|
71
147
|
{
|
|
72
148
|
name: 'mongodb',
|
|
73
|
-
version: '>=
|
|
149
|
+
version: '>=4.0.0'
|
|
74
150
|
},
|
|
75
151
|
(MongoDB, { version }) => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
152
|
+
patcher.patch(MongoDB.MongoClient.prototype, 'connect', {
|
|
153
|
+
name: 'MongoClient.connect.arch_component',
|
|
154
|
+
patchType: PATCH_TYPES.ARCH_COMPONENT,
|
|
155
|
+
alwaysRun: true,
|
|
156
|
+
post(ctx) {
|
|
157
|
+
if (!ctx.result || !ctx.result.then) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
85
160
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
161
|
+
// We should report only when connection is successful
|
|
162
|
+
ctx.result.then(function(client) {
|
|
163
|
+
if (client && client.topology && client.topology.s) {
|
|
164
|
+
try {
|
|
165
|
+
const { servers } = client.topology.s;
|
|
166
|
+
for (const [, server] of servers) {
|
|
167
|
+
if (server.s && server.s.state === 'connected') {
|
|
168
|
+
const { srvServiceName } = server.s.options;
|
|
169
|
+
const { address } = server.s.description;
|
|
170
|
+
agentEmitter.emit('architectureComponent', {
|
|
171
|
+
vendor: 'MongoDB',
|
|
172
|
+
url: `${srvServiceName}://${address}`,
|
|
173
|
+
remoteHost: '',
|
|
174
|
+
remotePort: address.split(':').pop()
|
|
175
|
+
});
|
|
102
176
|
}
|
|
103
|
-
} catch (err) {
|
|
104
|
-
logger.warn(
|
|
105
|
-
'unable to report MongoDB architecture component, err: %o',
|
|
106
|
-
err,
|
|
107
|
-
);
|
|
108
177
|
}
|
|
178
|
+
} catch (err) {
|
|
179
|
+
logger.warn(
|
|
180
|
+
'unable to report MongoDB architecture component, err: %o',
|
|
181
|
+
err,
|
|
182
|
+
);
|
|
109
183
|
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
},
|
|
187
|
+
});
|
|
114
188
|
},
|
|
115
189
|
);
|