@newrelic/security-agent 3.0.3 → 3.0.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/CHANGELOG.md +17 -0
- package/THIRD_PARTY_NOTICES.md +0 -18
- package/lib/instrumentation-security/hooks/hapi/nr-hapi.js +1 -2
- package/lib/instrumentation-security/hooks/mongodb/common.js +207 -34
- package/lib/instrumentation-security/hooks/mongodb/v4-mongo.js +15 -5
- package/lib/nr-security-agent/lib/core/commonUtils.js +2 -2
- package/lib/nr-security-agent/resources/config.js +2 -2
- package/package.json +3 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
### v3.0.5 (2026-10-29)
|
|
2
|
+
#### Bug fixes
|
|
3
|
+
* Subscribe to agent mongodb channels instead of wrapping prototypes (#375)
|
|
4
|
+
* Delegate wrapped mongodb methods to the prototype at call time (#376)
|
|
5
|
+
|
|
6
|
+
#### Miscellaneous chores
|
|
7
|
+
* bump undici to 7.30.1 and ws to 8.22.0 (#377)
|
|
8
|
+
|
|
9
|
+
### v3.0.4 (2026-05-14)
|
|
10
|
+
#### Bug fixes
|
|
11
|
+
* remove dependency on uuid module (#357)
|
|
12
|
+
* update hapi instrumentation, remove shim.argsToArray method (#360)
|
|
13
|
+
|
|
14
|
+
#### Miscellaneous chores
|
|
15
|
+
* (deps-dev): bump protobufjs from 7.2.5 to 7.5.8 (#358)
|
|
16
|
+
* (deps-dev): bump fast-xml-parser and @aws-sdk/xml-builder (#356)
|
|
17
|
+
|
|
1
18
|
### v3.0.3 (2026-04-08)
|
|
2
19
|
#### Miscellaneous chores
|
|
3
20
|
* (deps-dev): bump koa from 3.0.3 to 3.1.2 (#330)
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -30,7 +30,6 @@ code, the source code can be found at [https://github.com/newrelic/csec-node-age
|
|
|
30
30
|
* [undici](#undici)
|
|
31
31
|
* [unescape-js](#unescape-js)
|
|
32
32
|
* [unescape](#unescape)
|
|
33
|
-
* [uuid](#uuid)
|
|
34
33
|
* [ws](#ws)
|
|
35
34
|
|
|
36
35
|
**[devDependencies](#devDependencies)**
|
|
@@ -465,23 +464,6 @@ THE SOFTWARE.
|
|
|
465
464
|
|
|
466
465
|
```
|
|
467
466
|
|
|
468
|
-
### uuid
|
|
469
|
-
|
|
470
|
-
This product includes source derived from [uuid](https://github.com/uuidjs/uuid) ([v9.0.1](https://github.com/uuidjs/uuid/tree/v9.0.1)), distributed under the [MIT License](https://github.com/uuidjs/uuid/blob/v9.0.1/LICENSE.md):
|
|
471
|
-
|
|
472
|
-
```
|
|
473
|
-
The MIT License (MIT)
|
|
474
|
-
|
|
475
|
-
Copyright (c) 2010-2020 Robert Kieffer and other contributors
|
|
476
|
-
|
|
477
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
478
|
-
|
|
479
|
-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
480
|
-
|
|
481
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
482
|
-
|
|
483
|
-
```
|
|
484
|
-
|
|
485
467
|
### ws
|
|
486
468
|
|
|
487
469
|
This product includes source derived from [ws](https://github.com/websockets/ws) ([v8.18.0](https://github.com/websockets/ws/tree/v8.18.0)), distributed under the [MIT License](https://github.com/websockets/ws/blob/v8.18.0/LICENSE):
|
|
@@ -49,8 +49,7 @@ function serverPostConstructor(shim) {
|
|
|
49
49
|
function wrapProtoRoute(shim, proto) {
|
|
50
50
|
shim.wrap(proto, 'route', function wrapRoute(shim, original) {
|
|
51
51
|
logger.debug(`Instrumenting ${proto}.route`);
|
|
52
|
-
return function wrappedRoute() {
|
|
53
|
-
const args = shim.argsToArray.apply(shim, arguments)
|
|
52
|
+
return function wrappedRoute(...args) {
|
|
54
53
|
if (!shim.isObject(args[0])) {
|
|
55
54
|
return original.apply(this, args)
|
|
56
55
|
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
/* eslint sonarjs/cognitive-complexity: ["error", 18] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
|
|
9
9
|
|
|
10
|
+
const diagnosticsChannel = require("diagnostics_channel");
|
|
10
11
|
const { CURSOR_OPS, COLLECTION_OPS, DB_OPS } = require("./constants");
|
|
11
12
|
const common = module.exports;
|
|
12
13
|
const requestManager = require("../../core/request-manager");
|
|
@@ -18,6 +19,30 @@ const { EVENT_TYPE, EVENT_CATEGORY } = require('../../core/event-constants');
|
|
|
18
19
|
const { NR_CSEC_FUZZ_REQUEST_ID } = require('../../core/constants');
|
|
19
20
|
const logger = API.getLogger();
|
|
20
21
|
|
|
22
|
+
// Prefix for the newrelic agent's mongodb tracing channels. The agent publishes
|
|
23
|
+
// one tracing channel per instrumented mongodb class; subscribing to these lets
|
|
24
|
+
// us attach to constructed instances without reassigning prototype methods.
|
|
25
|
+
const AGENT_MONGODB_CHANNEL_PREFIX = "orchestrion:mongodb:";
|
|
26
|
+
// Marks an instance whose methods we have already wrapped, so repeated channel
|
|
27
|
+
// events for the same object do not double-wrap.
|
|
28
|
+
const CSEC_MONGO_INSTANCE_HOOKED = Symbol("csecMongoInstanceHooked");
|
|
29
|
+
// Tracks the active subscription handlers per agent channel. The mongodb hook
|
|
30
|
+
// can run more than once in a process (e.g. the newrelic agent being unloaded
|
|
31
|
+
// and re-instrumented), each time with a fresh `shim`. The tracing channel is
|
|
32
|
+
// process-global, so on each run we must remove the previous subscription
|
|
33
|
+
// (bound to the old `shim`) before adding a new one, otherwise we stack
|
|
34
|
+
// duplicate subscribers that serve a stale `shim`.
|
|
35
|
+
//
|
|
36
|
+
// This registry must live on `globalThis`, not in a module-scoped variable:
|
|
37
|
+
// this file's path contains "mongodb", so test/require-cache busters that evict
|
|
38
|
+
// modules matching "mongodb" would reload this module and reset a module-scoped
|
|
39
|
+
// Map — losing the handle needed to unsubscribe the still-live prior
|
|
40
|
+
// subscription. Keyed by full channel name -> handlers object.
|
|
41
|
+
const CHANNEL_SUBSCRIPTIONS_KEY = Symbol.for("newrelic.csec.mongodb.channelSubscriptions");
|
|
42
|
+
const channelSubscriptions =
|
|
43
|
+
globalThis[CHANNEL_SUBSCRIPTIONS_KEY] ||
|
|
44
|
+
(globalThis[CHANNEL_SUBSCRIPTIONS_KEY] = new Map());
|
|
45
|
+
|
|
21
46
|
function methodChecker(data) {
|
|
22
47
|
data = data.toLowerCase();
|
|
23
48
|
if (data.includes("delete")) {
|
|
@@ -53,52 +78,200 @@ function payloadType(obj) {
|
|
|
53
78
|
|
|
54
79
|
}
|
|
55
80
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
81
|
+
/**
|
|
82
|
+
* Builds the security wrapper for a mongodb operation. The returned function
|
|
83
|
+
* reads the operation payload, generates the NoSQL security event, and (for
|
|
84
|
+
* fuzz requests) hooks the callback, then delegates to the original method.
|
|
85
|
+
*
|
|
86
|
+
* This is shared by both attachment strategies: the legacy prototype wrap
|
|
87
|
+
* (`queryHook`, used for mongodb < 4 where the newrelic agent does not provide
|
|
88
|
+
* subscriber based instrumentation) and the per-instance attachment
|
|
89
|
+
* (`instrumentInstance`, used for mongodb >= 4 so we do not reassign a
|
|
90
|
+
* prototype method already instrumented by the newrelic agent).
|
|
91
|
+
*
|
|
92
|
+
* @param {Shim} shim
|
|
93
|
+
* @param {string} method name of the operation being wrapped
|
|
94
|
+
* @param {Function} fn the original method
|
|
95
|
+
* @returns {Function} the wrapped method
|
|
96
|
+
*/
|
|
97
|
+
function makeQueryWrapper(shim, method, fn) {
|
|
98
|
+
return function queryWrapper() {
|
|
99
|
+
const request = requestManager.getRequest(shim);
|
|
100
|
+
if (CURSOR_OPS.includes(method)) {
|
|
101
|
+
if (!this.mongo_sec_hooked && this.operation && this.operation.cmd) {
|
|
102
|
+
const pType = payloadType(this.operation.cmd);
|
|
74
103
|
const payloadData = {
|
|
75
104
|
payloadType: pType,
|
|
76
|
-
payload:
|
|
105
|
+
payload: this.operation.cmd,
|
|
77
106
|
};
|
|
78
107
|
shim.interceptedArgs = payloadData;
|
|
79
|
-
|
|
80
108
|
}
|
|
109
|
+
} else {
|
|
110
|
+
this.mongo_sec_hooked = true;
|
|
81
111
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
112
|
+
const pType = methodChecker(method);
|
|
113
|
+
const payloadData = {
|
|
114
|
+
payloadType: pType,
|
|
115
|
+
payload: arguments,
|
|
116
|
+
};
|
|
117
|
+
shim.interceptedArgs = payloadData;
|
|
118
|
+
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
if (request) {
|
|
123
|
+
//generate event here
|
|
124
|
+
const traceObject = secUtils.getTraceObject(shim);
|
|
125
|
+
const secMetadata = securityMetaData.getSecurityMetaData(request, JSON.parse(JSON.stringify(shim.interceptedArgs)), traceObject, secUtils.getExecutionId(), EVENT_TYPE.NOSQL_DB_COMMAND, EVENT_CATEGORY.MONGO)
|
|
126
|
+
const secEvent = API.generateSecEvent(secMetadata);
|
|
127
|
+
API.sendEvent(secEvent);
|
|
128
|
+
if (request.headers[NR_CSEC_FUZZ_REQUEST_ID]) {
|
|
129
|
+
callbackHook(shim, arguments, arguments.length - 1, secEvent);
|
|
92
130
|
}
|
|
93
|
-
} catch (error) {
|
|
94
131
|
}
|
|
95
|
-
|
|
132
|
+
} catch (error) {
|
|
133
|
+
}
|
|
96
134
|
|
|
97
|
-
|
|
98
|
-
|
|
135
|
+
|
|
136
|
+
return fn.apply(this, arguments);
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function queryHook(shim, mod, method) {
|
|
141
|
+
shim.wrap(mod, method, function wrapQuery(shim, fn) {
|
|
142
|
+
logger.debug(`Instrumenting mongodb.${method}`);
|
|
143
|
+
return makeQueryWrapper(shim, method, fn);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Attaches the security wrapper to a single mongodb instance (a `Collection`,
|
|
149
|
+
* cursor, etc.) as an own property, leaving the class prototype untouched.
|
|
150
|
+
*
|
|
151
|
+
* The newrelic agent (>= the release that instruments mongodb via
|
|
152
|
+
* `diagnostics_channel`) reassigns the driver prototype methods. If we also
|
|
153
|
+
* wrapped the prototype, the two reassignments would clobber one another and
|
|
154
|
+
* the agent's datastore instrumentation would be lost. Wrapping the instance
|
|
155
|
+
* sits below the prototype, so both coexist. See
|
|
156
|
+
* https://github.com/newrelic/csec-node-agent/issues/374.
|
|
157
|
+
*
|
|
158
|
+
* @param {Shim} shim
|
|
159
|
+
* @param {object} instance a constructed mongodb object (e.g. a `Collection`)
|
|
160
|
+
* @param {string[]} methods operation names to wrap when present on `instance`
|
|
161
|
+
*/
|
|
162
|
+
function instrumentInstance(shim, instance, methods) {
|
|
163
|
+
if (!instance || instance[CSEC_MONGO_INSTANCE_HOOKED]) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
// Guard so repeated channel events for the same instance do not re-wrap.
|
|
167
|
+
Object.defineProperty(instance, CSEC_MONGO_INSTANCE_HOOKED, {
|
|
168
|
+
value: true,
|
|
169
|
+
enumerable: false,
|
|
170
|
+
writable: true,
|
|
171
|
+
configurable: true
|
|
99
172
|
});
|
|
173
|
+
|
|
174
|
+
const proto = Object.getPrototypeOf(instance);
|
|
175
|
+
for (let i = 0; i < methods.length; i++) {
|
|
176
|
+
const method = methods[i];
|
|
177
|
+
if (typeof instance[method] !== "function") {
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
logger.debug(`Instrumenting mongodb instance method ${method}`);
|
|
181
|
+
// Own property on the instance; does not touch the prototype. Delegate to
|
|
182
|
+
// the prototype method *lazily* (resolved at call time) rather than
|
|
183
|
+
// capturing it now: the newrelic agent wraps the prototype method on each
|
|
184
|
+
// (re-)instrumentation, so a value captured at construction time can go
|
|
185
|
+
// stale and bypass the agent's current wrapper. Reading it from the
|
|
186
|
+
// prototype at call time always runs whatever the agent currently has.
|
|
187
|
+
instance[method] = makeQueryWrapper(shim, method, function callProto() {
|
|
188
|
+
return proto[method].apply(this, arguments);
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Subscribes to a newrelic agent mongodb construction tracing channel and
|
|
195
|
+
* attaches the security wrapper to each constructed instance. Returns false if
|
|
196
|
+
* the agent does not expose the channel (e.g. an older agent without
|
|
197
|
+
* subscriber based mongodb instrumentation), so callers can fall back to the
|
|
198
|
+
* legacy prototype wrapping.
|
|
199
|
+
*
|
|
200
|
+
* @param {Shim} shim
|
|
201
|
+
* @param {string} channelName the agent channel, e.g. `nr_collection`
|
|
202
|
+
* @param {string[]} methods operation names to wrap on each instance
|
|
203
|
+
* @returns {boolean} whether the channel subscription was established
|
|
204
|
+
*/
|
|
205
|
+
function subscribeToAgentChannel(shim, channelName, methods) {
|
|
206
|
+
const fullName = `${AGENT_MONGODB_CHANNEL_PREFIX}${channelName}`;
|
|
207
|
+
try {
|
|
208
|
+
const channel = diagnosticsChannel.tracingChannel(fullName);
|
|
209
|
+
// Only ride the agent's channel when the agent is actually instrumenting
|
|
210
|
+
// mongodb on it (it subscribes its own handler via `start`). If nothing is
|
|
211
|
+
// publishing here (e.g. an older newrelic agent without subscriber based
|
|
212
|
+
// mongodb instrumentation, or the agent disabled), report failure so the
|
|
213
|
+
// caller falls back to the legacy prototype wrapping. There is no colliding
|
|
214
|
+
// agent instrumentation in that case, so prototype wrapping is safe.
|
|
215
|
+
if (channel.start.hasSubscribers !== true) {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
// Remove any prior subscription for this channel. On re-instrumentation the
|
|
219
|
+
// previous handlers closed over a now-stale `shim`; replacing them keeps a
|
|
220
|
+
// single live subscription bound to the current `shim`.
|
|
221
|
+
const previous = channelSubscriptions.get(fullName);
|
|
222
|
+
if (previous) {
|
|
223
|
+
channel.unsubscribe(previous);
|
|
224
|
+
}
|
|
225
|
+
const handlers = {
|
|
226
|
+
end(event) {
|
|
227
|
+
try {
|
|
228
|
+
instrumentInstance(shim, event && event.self, methods);
|
|
229
|
+
} catch (error) {
|
|
230
|
+
logger.debug(`Error instrumenting mongodb instance via ${channelName}`, error);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
channel.subscribe(handlers);
|
|
235
|
+
channelSubscriptions.set(fullName, handlers);
|
|
236
|
+
return true;
|
|
237
|
+
} catch (error) {
|
|
238
|
+
logger.debug(`Could not subscribe to agent channel ${channelName}`, error);
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
100
241
|
}
|
|
101
242
|
|
|
243
|
+
/**
|
|
244
|
+
* Instruments cursor operations for mongodb >= 4 by subscribing to the newrelic
|
|
245
|
+
* agent's cursor construction channel and attaching to each instance. Falls
|
|
246
|
+
* back to the legacy prototype wrapping when the agent channel is unavailable.
|
|
247
|
+
*
|
|
248
|
+
* @param {Shim} shim
|
|
249
|
+
* @param {Cursor} [Cursor] cursor class, used only for the fallback path
|
|
250
|
+
*/
|
|
251
|
+
common.instrumentCursorViaChannel = function instrumentCursorViaChannel(shim, Cursor) {
|
|
252
|
+
const methods = CURSOR_OPS.concat(["each"]);
|
|
253
|
+
const subscribed = subscribeToAgentChannel(shim, "nr_cursor", methods);
|
|
254
|
+
if (!subscribed) {
|
|
255
|
+
common.instrumentCursor(shim, Cursor);
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Instruments collection operations for mongodb >= 4 by subscribing to the
|
|
261
|
+
* newrelic agent's collection construction channel and attaching to each
|
|
262
|
+
* instance. Falls back to the legacy prototype wrapping when the agent channel
|
|
263
|
+
* is unavailable.
|
|
264
|
+
*
|
|
265
|
+
* @param {Shim} shim
|
|
266
|
+
* @param {Collection} [Collection] collection class, used only for the fallback path
|
|
267
|
+
*/
|
|
268
|
+
common.instrumentCollectionViaChannel = function instrumentCollectionViaChannel(shim, Collection) {
|
|
269
|
+
const subscribed = subscribeToAgentChannel(shim, "nr_collection", COLLECTION_OPS);
|
|
270
|
+
if (!subscribed) {
|
|
271
|
+
common.instrumentCollection(shim, Collection);
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
|
|
102
275
|
/**
|
|
103
276
|
* Instruments all methods from constants.CURSOR_OPS on a given
|
|
104
277
|
* cursor class
|
|
@@ -6,12 +6,22 @@
|
|
|
6
6
|
|
|
7
7
|
'use strict'
|
|
8
8
|
|
|
9
|
-
const {
|
|
9
|
+
const { instrumentCollectionViaChannel, instrumentCursorViaChannel, instrumentDb } = require('./common')
|
|
10
10
|
|
|
11
11
|
module.exports = function instrument(shim, mongodb) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
// The newrelic agent instruments mongodb (>= 4) via diagnostics_channel and
|
|
13
|
+
// reassigns the driver prototype methods. Reassigning those same prototype
|
|
14
|
+
// methods here would clobber the agent's instrumentation (and vice versa), so
|
|
15
|
+
// we subscribe to the agent's construction channels and attach our security
|
|
16
|
+
// wrapper to each constructed instance instead. A single `nr_cursor`
|
|
17
|
+
// subscription covers AbstractCursor and its subclasses (FindCursor,
|
|
18
|
+
// AggregationCursor). See https://github.com/newrelic/csec-node-agent/issues/374.
|
|
19
|
+
//
|
|
20
|
+
// If the agent does not expose those channels (older agent without
|
|
21
|
+
// subscriber based mongodb instrumentation), these fall back to the legacy
|
|
22
|
+
// prototype wrapping, which is safe because there is no colliding agent
|
|
23
|
+
// instrumentation in that case.
|
|
24
|
+
instrumentCursorViaChannel(shim, mongodb.AbstractCursor)
|
|
25
|
+
instrumentCollectionViaChannel(shim, mongodb.Collection)
|
|
16
26
|
instrumentDb(shim, mongodb.Db)
|
|
17
27
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
/* eslint-disable prefer-promise-reject-errors */
|
|
7
7
|
const fs = require('fs');
|
|
8
|
-
const
|
|
8
|
+
const { randomUUID } = require('node:crypto');
|
|
9
9
|
const logs = require('./logging');
|
|
10
10
|
const logger = logs.getLogger();
|
|
11
11
|
const OS = require('os');
|
|
@@ -45,7 +45,7 @@ const skip_detection_category_map = {
|
|
|
45
45
|
* @returns UUID
|
|
46
46
|
*/
|
|
47
47
|
function getUUID() {
|
|
48
|
-
let uuid = process.env.applicationUUID ||
|
|
48
|
+
let uuid = process.env.applicationUUID || randomUUID();
|
|
49
49
|
process.env.applicationUUID = uuid;
|
|
50
50
|
return uuid;
|
|
51
51
|
}
|
|
@@ -11,8 +11,8 @@ if(process.platform == 'win32'){
|
|
|
11
11
|
AGENT_DIR = path.join(__dirname, "..\\..\\..\\");
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
const
|
|
15
|
-
process.env.applicationUUID = process.env.applicationUUID ||
|
|
14
|
+
const { randomUUID } = require('node:crypto');
|
|
15
|
+
process.env.applicationUUID = process.env.applicationUUID || randomUUID();
|
|
16
16
|
|
|
17
17
|
module.exports = {
|
|
18
18
|
AGENT_DIR,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@newrelic/security-agent",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.5",
|
|
4
4
|
"description": "New Relic Security Agent for Node.js",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"jsonVersion": "1.2.9",
|
|
@@ -52,11 +52,10 @@
|
|
|
52
52
|
"request-ip": "^3.3.0",
|
|
53
53
|
"ringbufferjs": "^2.0.0",
|
|
54
54
|
"semver": "^7.5.4",
|
|
55
|
-
"undici": "^7.
|
|
55
|
+
"undici": "^7.30.1",
|
|
56
56
|
"unescape": "^1.0.1",
|
|
57
57
|
"unescape-js": "^1.1.4",
|
|
58
|
-
"
|
|
59
|
-
"ws": "^8.17.1"
|
|
58
|
+
"ws": "^8.22.0"
|
|
60
59
|
},
|
|
61
60
|
"devDependencies": {
|
|
62
61
|
"@grpc/proto-loader": "^0.7.10",
|