@newrelic/security-agent 1.0.1 → 1.1.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,21 @@
1
+ ### v1.1.1 (2024-03-21)
2
+ #### Bug fixes
3
+ * Reverted IAST support for gRPC.
4
+
5
+ ### v1.1.0 (2024-03-19)
6
+ #### Features
7
+ * IAST support for grpc
8
+ * Functionality to report API endpoints of the application
9
+ * IAST support for undici
10
+ #### Bug fixes
11
+ * Updated permissions for file/directory created by security agent
12
+ #### Miscellaneous chores
13
+ * Bumped follow-redirects from v1.15.2 to v1.15.4
14
+ * Updated axios to v1.6.8
15
+ * Bumped ip from v2.0.0 to v2.0.1
16
+ * Bumped undici from 5.28.2 to v5.28.3
17
+ * Readme update
18
+
1
19
  ### v1.0.1 (2024-02-07)
2
20
  #### Bug fixes
3
21
  * Reporting of framework in security event json
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  **Note**: The IAST capability should only be used in pre-production environments as the application is tested for real exploitable vulnerabilities.
5
5
 
6
- The New Relic security agent is in preview and is not generally available. This module enables instrumentation of a Node.js application for interactive application security testing(IAST) and exposes exploitable vulnerabilities.
6
+ The New Relic security agent enables instrumentation of a Node.js application for Interactive Application Security Testing(IAST) and exposes exploitable vulnerabilities.
7
7
 
8
8
  ## Installation
9
9
 
@@ -67,6 +67,7 @@ The [Developer docs](http://newrelic.github.io/node-newrelic/) for writing instr
67
67
  - [ldapts](https://www.npmjs.com/package/ldapts)(2.x and above)
68
68
  - [xpath](https://www.npmjs.com/package/xpath)(0.0.20 and above)
69
69
  - [xpath.js](https://www.npmjs.com/package/xpath.js)(0.0.1 and above)
70
+ - [undici](https://www.npmjs.com/package/undici)(4.7.0 and above)
70
71
 
71
72
  For more information, please see New Relic Node.js agent [compatibility and requirements](https://docs.newrelic.com/docs/apm/agents/nodejs-agent/getting-started/compatibility-requirements-nodejs-agent/).
72
73
 
@@ -64,7 +64,9 @@ code, the source code can be found at [https://github.com/newrelic/csec-node-age
64
64
  * [request](#request)
65
65
  * [restify](#restify)
66
66
  * [sinon](#sinon)
67
+ * [stream](#stream)
67
68
  * [tap](#tap)
69
+ * [undici](#undici)
68
70
  * [xmldom](#xmldom)
69
71
  * [xpath.js](#xpathjs)
70
72
  * [xpath](#xpath)
@@ -74,7 +76,7 @@ code, the source code can be found at [https://github.com/newrelic/csec-node-age
74
76
 
75
77
  ### axios
76
78
 
77
- This product includes source derived from [axios](https://github.com/axios/axios) ([v1.6.5](https://github.com/axios/axios/tree/v1.6.5)), distributed under the [MIT License](https://github.com/axios/axios/blob/v1.6.5/LICENSE):
79
+ This product includes source derived from [axios](https://github.com/axios/axios) ([v1.6.8](https://github.com/axios/axios/tree/v1.6.8)), distributed under the [MIT License](https://github.com/axios/axios/blob/v1.6.8/LICENSE):
78
80
 
79
81
  ```
80
82
  # Copyright (c) 2014-present Matt Zabriskie & Collaborators
@@ -2588,6 +2590,22 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2588
2590
 
2589
2591
  ```
2590
2592
 
2593
+ ### stream
2594
+
2595
+ This product includes source derived from [stream](https://github.com/juliangruber/stream) ([v0.0.2](https://github.com/juliangruber/stream/tree/v0.0.2)), distributed under the [MIT License](https://github.com/juliangruber/stream/blob/v0.0.2/README.md):
2596
+
2597
+ ```
2598
+ MIT License
2599
+
2600
+ Copyright (c) <year> <copyright holders>
2601
+
2602
+ 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:
2603
+
2604
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
2605
+
2606
+ 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.
2607
+ ```
2608
+
2591
2609
  ### tap
2592
2610
 
2593
2611
  This product includes source derived from [tap](https://github.com/tapjs/node-tap) ([v16.3.7](https://github.com/tapjs/node-tap/tree/v16.3.7)), distributed under the [ISC License](https://github.com/tapjs/node-tap/blob/v16.3.7/LICENSE):
@@ -2611,6 +2629,35 @@ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2611
2629
 
2612
2630
  ```
2613
2631
 
2632
+ ### undici
2633
+
2634
+ This product includes source derived from [undici](https://github.com/nodejs/undici) ([v5.28.3](https://github.com/nodejs/undici/tree/v5.28.3)), distributed under the [MIT License](https://github.com/nodejs/undici/blob/v5.28.3/LICENSE):
2635
+
2636
+ ```
2637
+ MIT License
2638
+
2639
+ Copyright (c) Matteo Collina and Undici contributors
2640
+
2641
+ Permission is hereby granted, free of charge, to any person obtaining a copy
2642
+ of this software and associated documentation files (the "Software"), to deal
2643
+ in the Software without restriction, including without limitation the rights
2644
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2645
+ copies of the Software, and to permit persons to whom the Software is
2646
+ furnished to do so, subject to the following conditions:
2647
+
2648
+ The above copyright notice and this permission notice shall be included in all
2649
+ copies or substantial portions of the Software.
2650
+
2651
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2652
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2653
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2654
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2655
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2656
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2657
+ SOFTWARE.
2658
+
2659
+ ```
2660
+
2614
2661
  ### xmldom
2615
2662
 
2616
2663
  This product includes source derived from [xmldom](https://github.com/xmldom/xmldom) ([v0.6.0](https://github.com/xmldom/xmldom/tree/v0.6.0)), distributed under the [MIT License](https://github.com/xmldom/xmldom/blob/v0.6.0/LICENSE):
@@ -10,8 +10,8 @@ const routeMap = new Map();
10
10
  * @param {*} key
11
11
  * @param {*} value
12
12
  */
13
- function setRoute(key, value){
14
- routeMap.set(key,value);
13
+ function setRoute(key, value) {
14
+ routeMap.set(key, value);
15
15
  }
16
16
 
17
17
  /**
@@ -19,12 +19,35 @@ function setRoute(key, value){
19
19
  * @param {*} key
20
20
  * @returns
21
21
  */
22
- function getRoute(key){
22
+ function getRoute(key) {
23
23
  return routeMap.get(key);
24
24
  }
25
25
 
26
- module.exports={
26
+ /**
27
+ * Utility to get all api end points
28
+ * @returns all keys from routeMap
29
+ */
30
+ function getAllAPIEndPoints() {
31
+ let apiEndpoints = [];
32
+ try {
33
+ routeMap.forEach((value, key) => {
34
+ let obj = {};
35
+ let splitted = key.split('@');
36
+ obj.method = splitted[0];
37
+ obj.path = splitted[1];
38
+ obj.handler = routeMap.get(key);
39
+ apiEndpoints.push(obj);
40
+ })
41
+ } catch (error) {
42
+
43
+ }
44
+
45
+ return apiEndpoints;
46
+ }
47
+
48
+ module.exports = {
27
49
  getRoute,
28
50
  setRoute,
29
- routeMap
51
+ routeMap,
52
+ getAllAPIEndPoints
30
53
  }
@@ -150,11 +150,11 @@ function getExecutionId(){
150
150
  function createPathIfNotExist (dir) {
151
151
  try {
152
152
  if (!fs.existsSync(dir)) {
153
- fs.mkdirSync(dir, 777, { recursive: true });
153
+ fs.mkdirSync(dir, 770, { recursive: true });
154
154
  logger.info(dir + ' Created');
155
- fs.chmodSync(dir, 0o777);
155
+ fs.chmodSync(dir, 0o770);
156
156
  } else {
157
- fs.chmodSync(dir, 0o777);
157
+ fs.chmodSync(dir, 0o770);
158
158
  logger.debug(dir + ' Already Exists');
159
159
  }
160
160
  } catch (error) {
@@ -27,9 +27,8 @@ module.exports = function initialize(shim, express, moduleName) {
27
27
 
28
28
  if (express.Router.use) {
29
29
  wrapExpress4(shim, express)
30
- } else {
31
- // wrapExpress3(shim, express)
32
- }
30
+ }
31
+
33
32
  }
34
33
 
35
34
  /**
@@ -57,7 +56,6 @@ function wrapExpress4(shim, express) {
57
56
  }
58
57
  })
59
58
 
60
-
61
59
  //Wrapper to hook process_params method to extract out path param and query params.
62
60
  shim.wrap(express.Router, 'process_params', function wrapParam(shim, fn) {
63
61
  if (!shim.isFunction(fn)) {
@@ -0,0 +1,139 @@
1
+ /*
2
+ * Copyright 2023 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: New Relic Pre-Release
4
+ */
5
+
6
+ module.exports = initialize
7
+ const requestManager = require('../../core/request-manager');
8
+ const secUtils = require("../../core/sec-utils");
9
+ const API = require("../../../nr-security-api");
10
+ const lodash = require('lodash');
11
+ const securityMetaData = require('../../core/security-metadata');
12
+ const { EVENT_TYPE, EVENT_CATEGORY } = require('../../core/event-constants');
13
+ const { NR_CSEC_FUZZ_REQUEST_ID, QUESTION_MARK, EMPTY_STRING, COLON, SLASH } = require('../../core/constants');
14
+ const NRCSECTRACINGDATA = 'NR-CSEC-TRACING-DATA';
15
+ const DOUBLE_SLASH = '//';
16
+ const logger = API.getLogger();
17
+ const url = require('url');
18
+
19
+
20
+ /**
21
+ * Entry point undici module instrumentation.
22
+ * @param {*} shim
23
+ * @param {*} mod
24
+ * @param {*} moduleName
25
+ */
26
+ function initialize(shim, mod, moduleName) {
27
+ logger.info('Instrumenting ' + moduleName);
28
+ fetchHook(shim, mod, "fetch");
29
+ let util = shim.require('./lib/core/util');
30
+ parseOriginHook(shim, util, "parseOrigin")
31
+
32
+ }
33
+ /**
34
+ * Wrapper for util.parseOrigin
35
+ * @param {*} shim
36
+ * @param {*} mod
37
+ * @param {*} methodName
38
+ */
39
+ function parseOriginHook(shim, mod, methodName) {
40
+ shim.wrap(mod, methodName, function ClientWrapper(shim, fn) {
41
+ logger.debug(`Instrumenting ${methodName}`);
42
+ if (!shim.isFunction(fn)) {
43
+ return fn
44
+ }
45
+ return function wrapper() {
46
+ const request = requestManager.getRequest(shim);
47
+ try {
48
+ if (typeof arguments[0] === 'string') {
49
+ let URLObject = new URL(arguments[0]);
50
+ const data = {};
51
+ data.headers = {};
52
+ data.path = URLObject.pathname ? URLObject.pathname : EMPTY_STRING;
53
+ data.protocol = URLObject.protocol ? URLObject.protocol : 'http:';
54
+ data.headers.host = URLObject.host ? URLObject.host : URLObject.hostname;
55
+ shim.interceptedArgs = data;
56
+ if (request) {
57
+ const traceObject = secUtils.getTraceObject(shim);
58
+ const secMetadata = securityMetaData.getSecurityMetaData(request, data, traceObject, secUtils.getExecutionId(), EVENT_TYPE.HTTP_REQUEST, EVENT_CATEGORY.HTTP)
59
+ this.secEvent = API.generateSecEvent(secMetadata);
60
+ API.sendEvent(this.secEvent);
61
+ }
62
+ }
63
+ } catch (error) {
64
+
65
+ }
66
+ const result = fn.apply(this, arguments);
67
+ if (result && request && request.headers[NR_CSEC_FUZZ_REQUEST_ID]) {
68
+ API.generateExitEvent(this.secEvent);
69
+ delete this.secEvent
70
+ }
71
+ return result;
72
+ }
73
+ })
74
+ }
75
+
76
+ /**
77
+ * Wrapper to hook undici.fetch()
78
+ * @param {*} shim
79
+ * @param {*} mod
80
+ * @param {*} methodName
81
+ */
82
+ function fetchHook(shim, mod, methodName) {
83
+ shim.wrap(mod, methodName, function makeWrapper(shim, fn) {
84
+ logger.debug(`Instrumenting ${methodName}`);
85
+ if (!shim.isFunction(fn)) {
86
+ return fn
87
+ }
88
+ return function wrapper() {
89
+ const request = requestManager.getRequest(shim);
90
+ try {
91
+ const completeURL = arguments[0];
92
+ const parsedUrl = url.parse(completeURL);
93
+ const data = {};
94
+ data.headers = {};
95
+ data.method = arguments[0].method ? arguments[0].method : EMPTY_STRING;
96
+ data.path = parsedUrl.pathname ? parsedUrl.pathname : parsedUrl.path;
97
+ data.protocol = parsedUrl.protocol;
98
+ data.headers.host = parsedUrl.host ? parsedUrl.host : parsedUrl.hostname;
99
+ data.port = parsedUrl.port ? parsedUrl.port : parsedUrl.port;
100
+
101
+ shim.interceptedArgs = data;
102
+ if (request && !lodash.isEmpty(data.headers.host) && !lodash.isEmpty(data.path)) {
103
+ const appUUID = API.getSecAgent().applicationInfo.applicationUUID;
104
+ const traceObject = secUtils.getTraceObject(shim);
105
+ const secMetadata = securityMetaData.getSecurityMetaData(request, data, traceObject, secUtils.getExecutionId(), EVENT_TYPE.HTTP_REQUEST, EVENT_CATEGORY.HTTP)
106
+ this.secEvent = API.generateSecEvent(secMetadata);
107
+ API.sendEvent(this.secEvent);
108
+
109
+ let traceHeader = EMPTY_STRING;
110
+ if (request.headers['nr-csec-tracing-data']) {
111
+ traceHeader = request.headers['nr-csec-tracing-data'];
112
+ }
113
+
114
+ if (arguments[1] instanceof Object) {
115
+ if (arguments[1] && arguments[1].headers && request.headers) {
116
+ arguments[1].headers[NRCSECTRACINGDATA] = traceHeader + appUUID + '/' + this.secEvent.apiId + '/' + this.secEvent.id + ';';
117
+ } else {
118
+ arguments[1].headers = {};
119
+ arguments[1].headers[NRCSECTRACINGDATA] = traceHeader + appUUID + '/' + this.secEvent.apiId + '/' + this.secEvent.id + ';';
120
+ }
121
+ if (request && request.headers[NR_CSEC_FUZZ_REQUEST_ID] && arguments[1].headers) {
122
+ arguments[1].headers[NR_CSEC_FUZZ_REQUEST_ID] = request.headers[NR_CSEC_FUZZ_REQUEST_ID];
123
+ }
124
+ }
125
+ }
126
+ } catch (error) {
127
+ logger.debug("Error while extracting undici fetch args:", error);
128
+ }
129
+ const result = fn.apply(this, arguments);
130
+
131
+ if (result && request && request.headers[NR_CSEC_FUZZ_REQUEST_ID]) {
132
+ API.generateExitEvent(this.secEvent);
133
+ delete this.secEvent
134
+ }
135
+ return result;
136
+ }
137
+ })
138
+ }
139
+
@@ -190,6 +190,15 @@ newrelic.instrumentWebframework({
190
190
  }
191
191
  })
192
192
 
193
+ newrelic.instrumentWebframework({
194
+ moduleName: 'undici',
195
+ isEsm: true,
196
+ onRequire: require('./hooks/undici/nr-undici'),
197
+ onError: function intrumentErrorHandler(err) {
198
+ logger.error(err.message, err.stack)
199
+ }
200
+ })
201
+
193
202
 
194
203
 
195
204
 
@@ -0,0 +1,29 @@
1
+
2
+ /*
3
+ * Copyright 2023 New Relic Corporation. All rights reserved.
4
+ * SPDX-License-Identifier: New Relic Software License v1.0
5
+ */
6
+
7
+ const { BasicInfo } = require('./event');
8
+ const applicationInfo = require('./applicationinfo').getInstance();
9
+ /**
10
+ * Function Constructor to create object of FuzzFail event
11
+ * @param {*} fuzzHeader
12
+ */
13
+ function APIEndPoint (apiEndpoints) {
14
+ BasicInfo.call(this);
15
+ this.jsonVersion = applicationInfo.jsonVersion;
16
+ this.jsonName = 'sec-application-url-mapping';
17
+ this.eventType = "sec-application-url-mapping"
18
+ this.applicationUUID = applicationInfo.applicationUUID;
19
+ this.groupName = applicationInfo.groupName;
20
+ this.mappings = apiEndpoints;
21
+
22
+ return this;
23
+ }
24
+
25
+ APIEndPoint.prototype.constructor = APIEndPoint;
26
+
27
+ module.exports = {
28
+ APIEndPoint
29
+ };
@@ -97,11 +97,11 @@ function runtimeSupportsAsyncFunctionGenerators() {
97
97
  function createPathIfNotExist(dir) {
98
98
  try {
99
99
  if (!fs.existsSync(dir)) {
100
- fs.mkdirSync(dir, 777, { recursive: true });
100
+ fs.mkdirSync(dir, 770, { recursive: true });
101
101
  logger.info(dir + ' Created');
102
- fs.chmodSync(dir, 0o777);
102
+ fs.chmodSync(dir, 0o770);
103
103
  } else {
104
- fs.chmodSync(dir, 0o777);
104
+ fs.chmodSync(dir, 0o770);
105
105
  logger.debug(dir + ' Already Exists');
106
106
  }
107
107
  } catch (error) {
@@ -139,7 +139,7 @@ function createDirectories() {
139
139
  createPathIfNotExist(`${CSEC_HOME}${SLASH}nr-security-home${SLASH}tmp${SLASH}language-agent${SLASH}${getUUID()}`);
140
140
  createPathIfNotExist(`${CSEC_HOME}${SLASH}nr-security-home${SLASH}tmp${SLASH}language-agent${SLASH}${getUUID()}${SLASH}ds-tmp`);
141
141
  try {
142
- fs.chmodSync(`${CSEC_HOME}${SLASH}nr-security-home`, 0o777);
142
+ fs.chmodSync(`${CSEC_HOME}${SLASH}nr-security-home`, 0o770);
143
143
  } catch (error) {
144
144
  }
145
145
  }
@@ -31,11 +31,11 @@ const CSEC_ROOT = `${CSEC_HOME}${sep}nr-security-home${sep}`;
31
31
  function createLogPathIfNotExist(dir) {
32
32
  try {
33
33
  if (!fs.existsSync(dir)) {
34
- fs.mkdirSync(dir, 777, { recursive: true });
35
- fs.chmodSync(dir, 0o777);
34
+ fs.mkdirSync(dir, 770, { recursive: true });
35
+ fs.chmodSync(dir, 0o770);
36
36
  }
37
37
  else {
38
- fs.chmodSync(dir, 0o777);
38
+ fs.chmodSync(dir, 0o770);
39
39
  }
40
40
  } catch (error) {
41
41
  }
@@ -168,8 +168,8 @@ function getLogger(applicationUUID = process.env.applicationUUID) {
168
168
  logger = log4js.getLogger('NR_CSEC');
169
169
  const initLogger = getInitLogger();
170
170
  try {
171
- fs.chmodSync(`${logFileName}`, 0o777);
172
- fs.chmodSync(`${initLogFileName}`, 0o777);
171
+ fs.chmodSync(`${logFileName}`, 0o660);
172
+ fs.chmodSync(`${initLogFileName}`, 0o660);
173
173
  } catch (error) {
174
174
  }
175
175
  initLogger.info("[STEP-2] => Generating unique identifier:", applicationUUID)
@@ -93,7 +93,7 @@ function getFormattedData() {
93
93
  function writeSnapshot() {
94
94
  const snapshot = getFormattedData();
95
95
  commonUtils.removeOlderSnapshots();
96
- fs.writeFile(statusFile, snapshot, { mode: 0o777 }, function (err) {
96
+ fs.writeFile(statusFile, snapshot, { mode: 0o660 }, function (err) {
97
97
  if (err) {
98
98
  logger.debug(err.message);
99
99
  const LogMessage = require('./LogMessage');
@@ -101,7 +101,7 @@ function writeSnapshot() {
101
101
  commonUtils.addLogEventtoBuffer(logMessage);
102
102
  } else {
103
103
  logger.info('Snapshot updated to file: %s', statusFile);
104
- fs.chmod(statusFile, 0o777, (err) => {
104
+ fs.chmod(statusFile, 0o660, (err) => {
105
105
  if (err) {
106
106
  addErrortoBuffer(err);
107
107
  }
@@ -70,6 +70,15 @@ const initialize = function () {
70
70
  setTimeout(() => {
71
71
  setInterval(sendHC, HC_INTERVAL_MS);
72
72
  sendHC();
73
+ try {
74
+ let apiEndpoints = require('../../../instrumentation-security/core/route-manager').getAllAPIEndPoints();
75
+ let data = require('./apiEndpoints').APIEndPoint(apiEndpoints);
76
+ logger.debug("All API end points of the application is:",JSON.stringify(data));
77
+ getDispatcherAndSendEvent(data);
78
+ } catch (error) {
79
+ logger.debug("Error while processing API endpoints",error);
80
+ }
81
+
73
82
  try {
74
83
  const framework = NRAgent.environment.get('Framework')[0];
75
84
  const dispatcher = NRAgent.environment.get('Dispatcher')[0];
@@ -78,8 +87,8 @@ const initialize = function () {
78
87
  } catch (error) {
79
88
  logger.debug("Error while extracting data from APM environment",error);
80
89
  }
90
+ }, 20000);
81
91
 
82
- }, 30000);
83
92
 
84
93
  setInterval(commonUtils.logRollOver, 30000);
85
94
  initLogger.info("[STEP-5] => Security Agent components started");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newrelic/security-agent",
3
- "version": "1.0.1",
3
+ "version": "1.1.1",
4
4
  "description": "New Relic Security Agent for Node.js",
5
5
  "main": "index.js",
6
6
  "jsonVersion": "1.1.1",
@@ -35,7 +35,7 @@
35
35
  "url": "https://github.com/newrelic/csec-node-agent.git"
36
36
  },
37
37
  "dependencies": {
38
- "axios": "^1.6.5",
38
+ "axios": "^1.6.8",
39
39
  "check-disk-space": "^3.4.0",
40
40
  "content-type": "^1.0.5",
41
41
  "fast-safe-stringify": "^2.1.1",
@@ -84,7 +84,9 @@
84
84
  "request": "^2.88.2",
85
85
  "restify": "^11.1.0",
86
86
  "sinon": "^15.0.0",
87
+ "stream": "^0.0.2",
87
88
  "tap": "^16.3.2",
89
+ "undici": "^5.28.0",
88
90
  "xmldom": "^0.6.0",
89
91
  "xpath": "^0.0.32",
90
92
  "xpath.js": "^1.1.0"