@newrelic/security-agent 2.2.0 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ ### v2.3.1 (2025-02-04)
2
+ #### Bug fixes
3
+ * Removed docker-cli-js dependency and updated mongodb unit test case (#283)
4
+ * Added safety check for agentModule before accessing its properties (#284)
5
+
6
+ ### v2.3.0 (2025-02-03)
7
+ #### Features
8
+ * Added Support for VM module
9
+ * IAST support for Next.js
10
+ * Support for Insecure settings i.e crypto, hash and random modules
11
+
12
+ #### Bug fixes
13
+ * Fix for special characters in ws header
14
+ * Fix for getting transaction in graphql instrumentation
15
+ * Fix for mongodb unit tests
16
+
17
+ #### Miscellaneous chores
18
+ * deps-dev: bump undici from v5.28.4 to v5.28.5
19
+ * Updated axios to v1.7.9
20
+
1
21
  ### v2.2.0 (2024-12-18)
2
22
  #### Features
3
23
  * Support for express 5.x
@@ -59,7 +59,6 @@ code, the source code can be found at [https://github.com/newrelic/csec-node-age
59
59
  * [eslint-plugin-promise](#eslint-plugin-promise)
60
60
  * [eslint-plugin-sonarjs](#eslint-plugin-sonarjs)
61
61
  * [koa](#koa)
62
- * [mongodb-memory-server](#mongodb-memory-server)
63
62
  * [mongodb](#mongodb)
64
63
  * [mongodb](#mongodb)
65
64
  * [mongodb](#mongodb)
@@ -79,7 +78,7 @@ code, the source code can be found at [https://github.com/newrelic/csec-node-age
79
78
 
80
79
  ### axios
81
80
 
82
- This product includes source derived from [axios](https://github.com/axios/axios) ([v1.7.4](https://github.com/axios/axios/tree/v1.7.4)), distributed under the [MIT License](https://github.com/axios/axios/blob/v1.7.4/LICENSE):
81
+ This product includes source derived from [axios](https://github.com/axios/axios) ([v1.7.9](https://github.com/axios/axios/tree/v1.7.9)), distributed under the [MIT License](https://github.com/axios/axios/blob/v1.7.9/LICENSE):
83
82
 
84
83
  ```
85
84
  # Copyright (c) 2014-present Matt Zabriskie & Collaborators
@@ -259,7 +258,7 @@ THE SOFTWARE.
259
258
 
260
259
  ### https-proxy-agent
261
260
 
262
- This product includes source derived from [https-proxy-agent](https://github.com/TooTallNate/proxy-agents) ([v7.0.4](https://github.com/TooTallNate/proxy-agents/tree/v7.0.4)), distributed under the [MIT License](https://github.com/TooTallNate/proxy-agents/blob/v7.0.4/LICENSE):
261
+ This product includes source derived from [https-proxy-agent](https://github.com/TooTallNate/proxy-agents) ([v7.0.6](https://github.com/TooTallNate/proxy-agents/tree/v7.0.6)), distributed under the [MIT License](https://github.com/TooTallNate/proxy-agents/blob/v7.0.6/LICENSE):
263
262
 
264
263
  ```
265
264
  (The MIT License)
@@ -512,7 +511,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
512
511
 
513
512
  ### semver
514
513
 
515
- This product includes source derived from [semver](https://github.com/npm/node-semver) ([v7.5.4](https://github.com/npm/node-semver/tree/v7.5.4)), distributed under the [ISC License](https://github.com/npm/node-semver/blob/v7.5.4/LICENSE):
514
+ This product includes source derived from [semver](https://github.com/npm/node-semver) ([v7.6.3](https://github.com/npm/node-semver/tree/v7.6.3)), distributed under the [ISC License](https://github.com/npm/node-semver/blob/v7.6.3/LICENSE):
516
515
 
517
516
  ```
518
517
  The ISC License
@@ -1874,23 +1873,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1874
1873
 
1875
1874
  ```
1876
1875
 
1877
- ### mongodb-memory-server
1878
-
1879
- This product includes source derived from [mongodb-memory-server](https://github.com/nodkz/mongodb-memory-server) ([v8.13.0](https://github.com/nodkz/mongodb-memory-server/tree/v8.13.0)), distributed under the [MIT License](https://github.com/nodkz/mongodb-memory-server/blob/v8.13.0/LICENSE.md):
1880
-
1881
- ```
1882
- The MIT License (MIT)
1883
-
1884
- Copyright (c) 2017-present Pavel Chertorogov
1885
-
1886
- 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:
1887
-
1888
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
1889
-
1890
- 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.
1891
-
1892
- ```
1893
-
1894
1876
  ### mongodb
1895
1877
 
1896
1878
  This product includes source derived from [mongodb](https://github.com/mongodb/node-mongodb-native) ([v2.2.36](https://github.com/mongodb/node-mongodb-native/tree/v2.2.36)), distributed under the [Apache-2.0 License](undefined):
@@ -11,20 +11,24 @@ const securityMetaData = require('../../core/security-metadata');
11
11
  const { EVENT_TYPE, EVENT_CATEGORY } = require('../../core/event-constants');
12
12
  const { NR_CSEC_FUZZ_REQUEST_ID } = require('../../core/constants');
13
13
  const logger = API.getLogger();
14
+ const NRLIB = 'newrelic/lib';
15
+ const SALIB = 'security-agent/lib'
14
16
 
15
17
  /**
16
- * Entry point of ldapjs and ldapts module hook
18
+ * Entry point of crypto module hook
17
19
  * @param {*} shim
18
20
  * @param {*} mod
19
21
  * @param {*} moduleName
20
22
  */
21
23
  function initialize(shim, mod, moduleName) {
24
+ if (API && API.getNRAgent() && API.getNRAgent().config.security.exclude_from_iast_scan.iast_detection_category.insecure_settings) {
25
+ logger.warn('insecure_settings detection is disabled');
26
+ return;
27
+ }
22
28
  logger.info('Instrumenting ' + moduleName)
23
29
  cryptoCipherHooks(shim, mod, 'createCipheriv', moduleName);
24
30
  cryptoHashHmacHooks(shim, mod, 'createHash', moduleName);
25
31
  cryptoHashHmacHooks(shim, mod, 'createHmac', moduleName);
26
- // cryptoRandomHooks(shim, mod, 'randomInt', moduleName);
27
- // cryptoRandomHooks(shim, mod, 'randomBytes', moduleName);
28
32
  cryptoRandomHooks(shim, Math, 'random', "Math");
29
33
  }
30
34
  /**
@@ -41,12 +45,17 @@ function cryptoCipherHooks(shim, mod, methodName, moduleName) {
41
45
  const interceptedArgs = [arguments[0]];
42
46
  shim.interceptedArgs = interceptedArgs;
43
47
  const request = requestManager.getRequest(shim);
44
- if (request) {
48
+ if (request && API.getSecAgent() && API.getSecAgent().status && API.getSecAgent().status.getStatus() === 'active') {
45
49
  const traceObject = secUtils.getTraceObject(shim);
46
50
  const secMetadata = securityMetaData.getSecurityMetaData(request, interceptedArgs, traceObject, secUtils.getExecutionId(), EVENT_TYPE.CRYPTO, EVENT_CATEGORY.CIPHER)
47
- const secEvent = API.generateSecEvent(secMetadata);
48
- this.secEvent = secEvent;
49
- API.sendEvent(secEvent);
51
+ if (secMetadata.traceObject && secMetadata.traceObject.stacktrace && (secMetadata.traceObject.stacktrace[0].includes(NRLIB) || secMetadata.traceObject.stacktrace[0].includes(SALIB))) {
52
+ //do nothing
53
+ }
54
+ else {
55
+ const secEvent = API.generateSecEvent(secMetadata);
56
+ this.secEvent = secEvent;
57
+ API.sendEvent(secEvent);
58
+ }
50
59
  }
51
60
  const result = fn.apply(this, arguments);
52
61
 
@@ -74,15 +83,21 @@ function cryptoHashHmacHooks(shim, mod, methodName, moduleName) {
74
83
  const interceptedArgs = [arguments[0]];
75
84
  shim.interceptedArgs = interceptedArgs;
76
85
  const request = requestManager.getRequest(shim);
77
- if (request) {
86
+
87
+ if (request && arguments[0] !== 'sha256' && API.getSecAgent() && API.getSecAgent().status && API.getSecAgent().status.getStatus() === 'active') {
78
88
  const traceObject = secUtils.getTraceObject(shim);
79
89
  const secMetadata = securityMetaData.getSecurityMetaData(request, interceptedArgs, traceObject, secUtils.getExecutionId(), EVENT_TYPE.HASH, EVENT_CATEGORY.HASH)
80
- const secEvent = API.generateSecEvent(secMetadata);
81
- this.secEvent = secEvent;
82
- API.sendEvent(secEvent);
90
+ if (secMetadata.traceObject && secMetadata.traceObject.stacktrace && (secMetadata.traceObject.stacktrace[0].includes(NRLIB) || secMetadata.traceObject.stacktrace[0].includes(SALIB))) {
91
+ //do nothing
92
+ }
93
+ else {
94
+ const secEvent = API.generateSecEvent(secMetadata);
95
+ this.secEvent = secEvent;
96
+ API.sendEvent(secEvent);
97
+ }
83
98
  }
84
99
  const result = fn.apply(this, arguments);
85
- if (result && request && request.headers[NR_CSEC_FUZZ_REQUEST_ID]) {
100
+ if (result && request && request.headers[NR_CSEC_FUZZ_REQUEST_ID] && arguments[0] !== 'sha256') {
86
101
  API.generateExitEvent(this.secEvent);
87
102
  delete this.secEvent
88
103
  }
@@ -104,12 +119,18 @@ function cryptoRandomHooks(shim, mod, methodName, moduleName) {
104
119
  const interceptedArgs = ["Math.random"];
105
120
  shim.interceptedArgs = interceptedArgs;
106
121
  const request = requestManager.getRequest(shim);
107
- if (request && arguments[0]) {
122
+ if (request && API.getSecAgent() && API.getSecAgent().status && API.getSecAgent().status.getStatus() === 'active') {
108
123
  const traceObject = secUtils.getTraceObject(shim);
109
124
  const secMetadata = securityMetaData.getSecurityMetaData(request, interceptedArgs, traceObject, secUtils.getExecutionId(), EVENT_TYPE.RANDOM, EVENT_CATEGORY.WEAKRANDOM)
110
- const secEvent = API.generateSecEvent(secMetadata);
111
- this.secEvent = secEvent;
112
- API.sendEvent(secEvent);
125
+ if (secMetadata.traceObject && secMetadata.traceObject.stacktrace && secMetadata.traceObject.stacktrace[0] && (secMetadata.traceObject.stacktrace[0].includes(NRLIB) || secMetadata.traceObject.stacktrace[0].includes(SALIB))) {
126
+ //do nothing
127
+ }
128
+ else {
129
+ const secEvent = API.generateSecEvent(secMetadata);
130
+ this.secEvent = secEvent;
131
+ API.sendEvent(secEvent);
132
+ }
133
+
113
134
  }
114
135
  const result = fn.apply(this, arguments);
115
136
  if (result && request && request.headers[NR_CSEC_FUZZ_REQUEST_ID]) {
@@ -27,10 +27,10 @@ module.exports = function initialize(shim, mod) {
27
27
  return fn;
28
28
  }
29
29
  return function wrappedExecute() {
30
- const segment = shim.getActiveSegment();
30
+ const transaction = shim.tracer.getTransaction();
31
31
  try {
32
- if (segment && segment.transaction) {
33
- let request = requestManager.getRequestFromId(segment.transaction.id);
32
+ if (transaction) {
33
+ let request = requestManager.getRequestFromId(transaction.id);
34
34
  let customDataType = {};
35
35
  //check for query parms
36
36
  if (request.headers['x-apollo-operation-name']) {
@@ -47,7 +47,7 @@ module.exports = function initialize(shim, mod) {
47
47
  }
48
48
  }
49
49
  request.customDataType = customDataType;
50
- requestManager.setRequest(segment.transaction.id, request);
50
+ requestManager.setRequest(transaction.id, request);
51
51
  }
52
52
 
53
53
  //check for body
@@ -60,7 +60,7 @@ module.exports = function initialize(shim, mod) {
60
60
  customDataType['*.variables'] = 'GRAPHQL_VARIABLE';
61
61
  }
62
62
  request.customDataType = customDataType;
63
- requestManager.setRequest(segment.transaction.id, request);
63
+ requestManager.setRequest(transaction.id, request);
64
64
  }
65
65
  }
66
66
 
@@ -459,8 +459,8 @@ function responseHook(resp, req, shim) {
459
459
  const policy = API.getPolicy();
460
460
  const dynamicScanningFlag = policy.data ? (policy.data.vulnerabilityScan?.enabled && policy.data.vulnerabilityScan.iastScan.enabled) : false;
461
461
  const type = response.getHeader(CONTENT_TYPE);
462
- let isUnsupportedType = isUnsupportedContentType(type);
463
-
462
+ let isUnsupportedType = isUnsupportedContentType(type, response);
463
+
464
464
  if (request && (construct || dynamicScanningFlag) && !isUnsupportedType) {
465
465
  const args = [];
466
466
  args.push(construct);
@@ -481,8 +481,11 @@ function responseHook(resp, req, shim) {
481
481
  * @param {*} conType
482
482
  * @returns
483
483
  */
484
- function isUnsupportedContentType(conType) {
484
+ function isUnsupportedContentType(conType, response) {
485
485
  try {
486
+ if(response.getHeaders()['etag']){
487
+ return false;
488
+ }
486
489
  if (!conType) {
487
490
  return true;
488
491
  }
@@ -534,7 +537,7 @@ function isUnsupportedContentType(conType) {
534
537
  function responseBodyCompute(response, args) {
535
538
  let encoding = UTF8;
536
539
  const type = response.getHeader(CONTENT_TYPE);
537
- let isUnsupportedType = isUnsupportedContentType(type);
540
+ let isUnsupportedType = isUnsupportedContentType(type, response);
538
541
  if (isUnsupportedType) {
539
542
  return;
540
543
  }
@@ -0,0 +1,46 @@
1
+ module.exports = initialize;
2
+ const requestManager = require("../../core/request-manager");
3
+ const secUtils = require("../../core/sec-utils");
4
+ const API = require("../../../nr-security-api");
5
+ const securityMetaData = require('../../core/security-metadata');
6
+ const { NR_CSEC_FUZZ_REQUEST_ID } = require('../../core/constants');
7
+ const logger = API.getLogger();
8
+
9
+ function initialize(shim, vm, moduleName) {
10
+ logger.info('Instrumenting', moduleName);
11
+ vmHooks(shim, vm, 'runInNewContext', moduleName);
12
+ vmHooks(shim, vm, 'runInThisContext', moduleName);
13
+ vmHooks(shim, vm, 'runInContext', moduleName);
14
+ }
15
+
16
+ /**
17
+ * Wrapper to hook vm methods
18
+ * @param {*} shim
19
+ * @param {*} vm
20
+ * @param {*} method
21
+ * @param {*} moduleName
22
+ */
23
+ function vmHooks(shim, vm, method, moduleName) {
24
+ shim.wrap(vm, method, function makeWrapper(shim, fn) {
25
+ logger.debug(`Instrumenting ${moduleName}.${method}`);
26
+ return function wrapper() {
27
+ const interceptedArgs = [arguments[0]];
28
+ shim.interceptedArgs = interceptedArgs;
29
+ const request = requestManager.getRequest(shim);
30
+ if (request) {
31
+ const traceObject = secUtils.getTraceObject(shim);
32
+ const secMetadata = securityMetaData.getSecurityMetaData(request, interceptedArgs, traceObject, secUtils.getExecutionId(), "JAVASCRIPT_INJECTION", "JAVASCRIPT_INJECTION")
33
+ const secEvent = API.generateSecEvent(secMetadata);
34
+ this.secEvent = secEvent;
35
+ API.sendEvent(secEvent);
36
+ }
37
+
38
+ const result = fn.apply(this, arguments);
39
+ if (result && request && request.headers[NR_CSEC_FUZZ_REQUEST_ID]) {
40
+ API.generateExitEvent(this.secEvent);
41
+ delete this.secEvent
42
+ }
43
+ return result;
44
+ };
45
+ });
46
+ }
@@ -0,0 +1,93 @@
1
+ /*
2
+ * Copyright 2023 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: New Relic Pre-Release
4
+ */
5
+
6
+ 'use strict'
7
+ const requestManager = require("../../core/request-manager");
8
+ const API = require("../../../nr-security-api");
9
+ const logger = API.getLogger();
10
+
11
+ const semver = require('semver')
12
+
13
+ module.exports = function initialize(shim, nextjs) {
14
+ const nextVersion = shim.require('./package.json').version
15
+ logger.info("Instrumenting nextjs", nextVersion);
16
+
17
+ const nextServer = nextjs.default;
18
+ hookRunAPI(shim, nextServer.prototype, nextVersion);
19
+ }
20
+
21
+ /**
22
+ * Wrapper for Server.prototype.runApi
23
+ * @param {*} shim
24
+ * @param {*} mod
25
+ * @param {*} nextVersion
26
+ */
27
+ function hookRunAPI(shim, mod, nextVersion) {
28
+ shim.wrap(mod, 'runApi', function wrapRunApi(shim, originalFn) {
29
+ if (!shim.isFunction(originalFn)) {
30
+ return originalFn
31
+ }
32
+ logger.debug("Instrumenting Server.prototype.runApi");
33
+ return function wrappedRunApi() {
34
+ try {
35
+ const { page, params } = extractAttrs(arguments, nextVersion)
36
+ extractParams(shim, page, params);
37
+ } catch (error) {
38
+ logger.debug("Error while processing path paramters");
39
+ }
40
+
41
+ return originalFn.apply(this, arguments)
42
+ }
43
+ })
44
+ }
45
+
46
+ /**
47
+ * Extracts the page and params from an API request
48
+ *
49
+ * @param {object} args arguments to runApi
50
+ * @param {string} version next.js version
51
+ * @returns {object} { page, params }
52
+ */
53
+ function extractAttrs(args, version) {
54
+ let params
55
+ let page
56
+ if (semver.gte(version, '13.4.13')) {
57
+ const [, , , match] = args
58
+ page = match?.definition?.pathname
59
+ params = { ...match?.params }
60
+ } else {
61
+ ;[, , , params, page] = args
62
+ }
63
+
64
+ return { params, page }
65
+ }
66
+
67
+ /**
68
+ * Utility to extract path params
69
+ * @param {*} page
70
+ * @param {*} params
71
+ */
72
+ function extractParams(shim, page, params) {
73
+ try {
74
+ const transaction = shim.tracer.getTransaction();
75
+ if (transaction) {
76
+ let request = requestManager.getRequestFromId(transaction.id);
77
+ Object.keys(params).forEach(function (key) {
78
+ if (params[key]) {
79
+ if (!request.parameterMap[key]) {
80
+ request.parameterMap[key] = new Array(params[key].toString());
81
+ requestManager.setRequest(transaction.id, request);
82
+ }
83
+ }
84
+ });
85
+ if (request && page) {
86
+ request.uri = page;
87
+ requestManager.setRequest(transaction.id, request);
88
+ }
89
+ }
90
+ } catch (error) {
91
+ }
92
+ }
93
+
@@ -253,4 +253,28 @@ newrelic.instrument({
253
253
  }
254
254
  })
255
255
 
256
+ newrelic.instrument({
257
+ moduleName: 'crypto',
258
+ onRequire: require('./hooks/crypto/nr-crypto'),
259
+ onError: function intrumentErrorHandler(err) {
260
+ logger.error(err.message, err.stack)
261
+ }
262
+ })
256
263
 
264
+ newrelic.instrumentWebframework({
265
+ moduleName: 'next/dist/server/next-server',
266
+ isEsm: true,
267
+ onRequire: require('./hooks/nextjs/nr-next'),
268
+ onError: function intrumentErrorHandler(err) {
269
+ logger.error(err.message, err.stack)
270
+ }
271
+ })
272
+
273
+ newrelic.instrument({
274
+ moduleName: 'vm',
275
+ isEsm: true,
276
+ onRequire: require('./hooks/native/nr-vm'),
277
+ onError: function intrumentErrorHandler(err) {
278
+ logger.error(err.message, err.stack)
279
+ }
280
+ })
@@ -36,7 +36,8 @@ function AuthHeaders() {
36
36
  authHeaders['NR-ACCOUNT-ID'] = NRAgent.config.account_id;
37
37
  authHeaders['NR-LICENSE-KEY'] = NRAgent ? NRAgent.config.license_key : '';
38
38
  authHeaders["NR-CSEC-IAST-DATA-TRANSFER-MODE"] = "PULL";
39
- authHeaders['NR-CSEC-ENTITY-NAME'] = metadata['entity.name'] ? metadata['entity.name'] : '';
39
+ const entityName = metadata['entity.name'] ? metadata['entity.name'] : '';
40
+ authHeaders['NR-CSEC-ENTITY-NAME'] = encodeURIComponent(entityName);
40
41
  authHeaders['NR-CSEC-ENTITY-GUID'] = metadata['entity.guid'] ? metadata['entity.guid'] : '';
41
42
  let instanceCount = parseInt(NRAgent.config.security.scan_controllers.scan_instance_count);
42
43
  if (isNaN(instanceCount)) {
@@ -12,6 +12,7 @@ const API = require('../../../nr-security-api');
12
12
  const NRAgent = API.getNRAgent();
13
13
  const lodash = require('lodash');
14
14
  const commonUtils = require('./commonUtils');
15
+ const crypto = require('crypto');
15
16
  /**
16
17
  * BasicInfo Structure, which is applicatble to each
17
18
  * Event generated from agent.
@@ -99,7 +100,7 @@ function SecEvent(fileName, funcName, lineNumber, argument, eid, applicationInfo
99
100
  const dynamicScanning = vulnerabilityScan.enabled && vulnerabilityScan.iastScan.enabled;
100
101
  this.isIASTEnable = dynamicScanning;
101
102
  if (this.isIASTEnable) {
102
- this.id = eid + Math.floor(Math.random() * (100000 - 1) + 1);
103
+ this.id = eid + Math.floor(crypto.randomInt(100) * (100000 - 1) + 1);
103
104
  } else {
104
105
  this.id = eid;
105
106
  }
@@ -196,7 +196,7 @@ function generateExitEvent(secEvent) {
196
196
 
197
197
  function sendEvent(secEvent) {
198
198
  const agentModule = Agent.getAgent();
199
- if (agentModule.status.getStatus() != 'connecting' && NRAgent.config.security.enabled && agentModule.status.getStatus() == 'active') {
199
+ if (agentModule && agentModule.status.getStatus() != 'connecting' && NRAgent.config.security.enabled && agentModule.status.getStatus() == 'active') {
200
200
  agentModule.client.dispatcher(secEvent);
201
201
  if (!firstEventSent && agentModule.status.getStatus() === 'active') {
202
202
  if(commonUtils.trafficStartedTime == 0){
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newrelic/security-agent",
3
- "version": "2.2.0",
3
+ "version": "2.3.1",
4
4
  "description": "New Relic Security Agent for Node.js",
5
5
  "main": "index.js",
6
6
  "jsonVersion": "1.2.9",
@@ -39,7 +39,7 @@
39
39
  "url": "https://github.com/newrelic/csec-node-agent.git"
40
40
  },
41
41
  "dependencies": {
42
- "axios": "^1.7.4",
42
+ "axios": "^1.7.9",
43
43
  "check-disk-space": "^3.4.0",
44
44
  "content-type": "^1.0.5",
45
45
  "cron": "^3.1.7",
@@ -84,7 +84,6 @@
84
84
  "eslint-plugin-sonarjs": "^0.15.0",
85
85
  "koa": "^2.14.1",
86
86
  "mongodb": "^4.13.0",
87
- "mongodb-memory-server": "^8.11.2",
88
87
  "mongodb2": "npm:mongodb@^2.2.36",
89
88
  "mongodb3": "npm:mongodb@^3.7.3",
90
89
  "newrelic": "^10.3.1",