@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 +20 -0
- package/THIRD_PARTY_NOTICES.md +3 -21
- package/lib/instrumentation-security/hooks/crypto/nr-crypto.js +37 -16
- package/lib/instrumentation-security/hooks/graphql/nr-graphql.js +5 -5
- package/lib/instrumentation-security/hooks/http/nr-http.js +7 -4
- package/lib/instrumentation-security/hooks/native/nr-vm.js +46 -0
- package/lib/instrumentation-security/hooks/nextjs/nr-next.js +93 -0
- package/lib/instrumentation-security/index.js +24 -0
- package/lib/nr-security-agent/lib/core/Auth-headers.js +2 -1
- package/lib/nr-security-agent/lib/core/event.js +2 -1
- package/lib/nr-security-agent/lib/core/sec-util.js +1 -1
- package/package.json +2 -3
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
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
-
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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 &&
|
|
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
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
|
30
|
+
const transaction = shim.tracer.getTransaction();
|
|
31
31
|
try {
|
|
32
|
-
if (
|
|
33
|
-
let request = requestManager.getRequestFromId(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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.
|
|
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.
|
|
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",
|