@newrelic/security-agent 3.0.0 → 3.0.2
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 +10 -1
- package/THIRD_PARTY_NOTICES.md +8 -143
- package/lib/instrumentation-security/hooks/director/nr-director.js +2 -3
- package/lib/instrumentation-security/hooks/express/nr-express.js +3 -4
- package/lib/instrumentation-security/hooks/fastify/nr-fastify.js +3 -3
- package/lib/instrumentation-security/hooks/fs/nr-fs.js +5 -6
- package/lib/instrumentation-security/hooks/hapi/nr-hapi.js +1 -2
- package/lib/instrumentation-security/hooks/http/nr-http.js +6 -6
- package/lib/instrumentation-security/hooks/koa/@koa/nr-@koa-router.js +2 -3
- package/lib/instrumentation-security/hooks/nextjs/nr-next.js +0 -1
- package/lib/instrumentation-security/hooks/restify/nr-restify.js +1 -2
- package/lib/instrumentation-security/hooks/undici/nr-undici.js +1 -2
- package/lib/nr-security-agent/lib/core/Auth-headers.js +1 -2
- package/lib/nr-security-agent/lib/core/Policy.js +3 -20
- package/lib/nr-security-agent/lib/core/applicationinfo.js +4 -5
- package/lib/nr-security-agent/lib/core/commonUtils.js +34 -24
- package/lib/nr-security-agent/lib/core/connections/aws-lambda-client.js +1 -3
- package/lib/nr-security-agent/lib/core/connections/websocket/response/index.js +1 -3
- package/lib/nr-security-agent/lib/core/event.js +2 -2
- package/lib/nr-security-agent/lib/core/xss-utils.js +5 -6
- package/package.json +3 -7
- package/lib/nr-security-agent/lib/core/jsonValidator.js +0 -149
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
|
+
### v3.0.2 (2026-02-17)
|
|
2
|
+
#### Miscellaneous chores
|
|
3
|
+
* refactor: Removed dependence on lodash in lieu of using native javascript
|
|
4
|
+
* refactor: Replace cron module with node-cron. Removed pretty-bytes, js-yaml and jsonschema modules
|
|
5
|
+
|
|
6
|
+
### v3.0.1 (2026-01-29)
|
|
7
|
+
#### Miscellaneous chores
|
|
8
|
+
* (deps): Updated lodash to v4.17.23 and undici to v7.19.0
|
|
9
|
+
|
|
1
10
|
### v3.0.0 (2026-01-06)
|
|
2
11
|
### ⚠ BREAKING CHANGES
|
|
3
|
-
* Dropped support for Node.js
|
|
12
|
+
* Dropped support for Node.js v18
|
|
4
13
|
|
|
5
14
|
#### Features
|
|
6
15
|
* Dropped support of Node 18.x and added Node 24.x
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -16,18 +16,14 @@ code, the source code can be found at [https://github.com/newrelic/csec-node-age
|
|
|
16
16
|
|
|
17
17
|
* [check-disk-space](#check-disk-space)
|
|
18
18
|
* [content-type](#content-type)
|
|
19
|
-
* [cron](#cron)
|
|
20
19
|
* [fast-safe-stringify](#fast-safe-stringify)
|
|
21
20
|
* [find-package-json](#find-package-json)
|
|
22
21
|
* [hash.js](#hashjs)
|
|
23
22
|
* [html-entities](#html-entities)
|
|
24
23
|
* [https-proxy-agent](#https-proxy-agent)
|
|
25
24
|
* [is-invalid-path](#is-invalid-path)
|
|
26
|
-
* [js-yaml](#js-yaml)
|
|
27
|
-
* [jsonschema](#jsonschema)
|
|
28
|
-
* [lodash](#lodash)
|
|
29
25
|
* [log4js](#log4js)
|
|
30
|
-
* [
|
|
26
|
+
* [node-cron](#node-cron)
|
|
31
27
|
* [request-ip](#request-ip)
|
|
32
28
|
* [ringbufferjs](#ringbufferjs)
|
|
33
29
|
* [semver](#semver)
|
|
@@ -132,22 +128,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
132
128
|
|
|
133
129
|
```
|
|
134
130
|
|
|
135
|
-
### cron
|
|
136
|
-
|
|
137
|
-
This product includes source derived from [cron](https://github.com/kelektiv/node-cron) ([v3.1.7](https://github.com/kelektiv/node-cron/tree/v3.1.7)), distributed under the [MIT License](https://github.com/kelektiv/node-cron/blob/v3.1.7/LICENSE):
|
|
138
|
-
|
|
139
|
-
```
|
|
140
|
-
The MIT License (MIT)
|
|
141
|
-
Copyright © 2017 Nicholas Campbell <nicholas.j.campbell@gmail.com>
|
|
142
|
-
|
|
143
|
-
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:
|
|
144
|
-
|
|
145
|
-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
146
|
-
|
|
147
|
-
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.
|
|
148
|
-
|
|
149
|
-
```
|
|
150
|
-
|
|
151
131
|
### fast-safe-stringify
|
|
152
132
|
|
|
153
133
|
This product includes source derived from [fast-safe-stringify](https://github.com/davidmarkclements/fast-safe-stringify) ([v2.1.1](https://github.com/davidmarkclements/fast-safe-stringify/tree/v2.1.1)), distributed under the [MIT License](https://github.com/davidmarkclements/fast-safe-stringify/blob/v2.1.1/LICENSE):
|
|
@@ -296,119 +276,6 @@ THE SOFTWARE.
|
|
|
296
276
|
|
|
297
277
|
```
|
|
298
278
|
|
|
299
|
-
### js-yaml
|
|
300
|
-
|
|
301
|
-
This product includes source derived from [js-yaml](https://github.com/nodeca/js-yaml) ([v4.1.1](https://github.com/nodeca/js-yaml/tree/v4.1.1)), distributed under the [MIT License](https://github.com/nodeca/js-yaml/blob/v4.1.1/LICENSE):
|
|
302
|
-
|
|
303
|
-
```
|
|
304
|
-
(The MIT License)
|
|
305
|
-
|
|
306
|
-
Copyright (C) 2011-2015 by Vitaly Puzrin
|
|
307
|
-
|
|
308
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
309
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
310
|
-
in the Software without restriction, including without limitation the rights
|
|
311
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
312
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
313
|
-
furnished to do so, subject to the following conditions:
|
|
314
|
-
|
|
315
|
-
The above copyright notice and this permission notice shall be included in
|
|
316
|
-
all copies or substantial portions of the Software.
|
|
317
|
-
|
|
318
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
319
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
320
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
321
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
322
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
323
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
324
|
-
THE SOFTWARE.
|
|
325
|
-
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
### jsonschema
|
|
329
|
-
|
|
330
|
-
This product includes source derived from [jsonschema](https://github.com/tdegrunt/jsonschema) ([v1.4.1](https://github.com/tdegrunt/jsonschema/tree/v1.4.1)), distributed under the [MIT License](https://github.com/tdegrunt/jsonschema/blob/v1.4.1/LICENSE):
|
|
331
|
-
|
|
332
|
-
```
|
|
333
|
-
jsonschema is licensed under MIT license.
|
|
334
|
-
|
|
335
|
-
Copyright (C) 2012-2015 Tom de Grunt <tom@degrunt.nl>
|
|
336
|
-
|
|
337
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
338
|
-
this software and associated documentation files (the "Software"), to deal in
|
|
339
|
-
the Software without restriction, including without limitation the rights to
|
|
340
|
-
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
341
|
-
of the Software, and to permit persons to whom the Software is furnished to do
|
|
342
|
-
so, subject to the following conditions:
|
|
343
|
-
|
|
344
|
-
The above copyright notice and this permission notice shall be included in all
|
|
345
|
-
copies or substantial portions of the Software.
|
|
346
|
-
|
|
347
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
348
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
349
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
350
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
351
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
352
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
353
|
-
SOFTWARE.
|
|
354
|
-
|
|
355
|
-
```
|
|
356
|
-
|
|
357
|
-
### lodash
|
|
358
|
-
|
|
359
|
-
This product includes source derived from [lodash](https://github.com/lodash/lodash) ([v4.17.21](https://github.com/lodash/lodash/tree/v4.17.21)), distributed under the [MIT License](https://github.com/lodash/lodash/blob/v4.17.21/LICENSE):
|
|
360
|
-
|
|
361
|
-
```
|
|
362
|
-
Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
|
|
363
|
-
|
|
364
|
-
Based on Underscore.js, copyright Jeremy Ashkenas,
|
|
365
|
-
DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
|
|
366
|
-
|
|
367
|
-
This software consists of voluntary contributions made by many
|
|
368
|
-
individuals. For exact contribution history, see the revision history
|
|
369
|
-
available at https://github.com/lodash/lodash
|
|
370
|
-
|
|
371
|
-
The following license applies to all parts of this software except as
|
|
372
|
-
documented below:
|
|
373
|
-
|
|
374
|
-
====
|
|
375
|
-
|
|
376
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
|
377
|
-
a copy of this software and associated documentation files (the
|
|
378
|
-
"Software"), to deal in the Software without restriction, including
|
|
379
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
|
380
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
|
381
|
-
permit persons to whom the Software is furnished to do so, subject to
|
|
382
|
-
the following conditions:
|
|
383
|
-
|
|
384
|
-
The above copyright notice and this permission notice shall be
|
|
385
|
-
included in all copies or substantial portions of the Software.
|
|
386
|
-
|
|
387
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
388
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
389
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
390
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
391
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
392
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
393
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
394
|
-
|
|
395
|
-
====
|
|
396
|
-
|
|
397
|
-
Copyright and related rights for sample code are waived via CC0. Sample
|
|
398
|
-
code is defined as all source code displayed within the prose of the
|
|
399
|
-
documentation.
|
|
400
|
-
|
|
401
|
-
CC0: http://creativecommons.org/publicdomain/zero/1.0/
|
|
402
|
-
|
|
403
|
-
====
|
|
404
|
-
|
|
405
|
-
Files located in the node_modules and vendor directories are externally
|
|
406
|
-
maintained libraries used by this software which have their own
|
|
407
|
-
licenses; we recommend you read them, as their terms may differ from the
|
|
408
|
-
terms above.
|
|
409
|
-
|
|
410
|
-
```
|
|
411
|
-
|
|
412
279
|
### log4js
|
|
413
280
|
|
|
414
281
|
This product includes source derived from [log4js](https://github.com/log4js-node/log4js-node) ([v6.9.1](https://github.com/log4js-node/log4js-node/tree/v6.9.1)), distributed under the [Apache-2.0 License](https://github.com/log4js-node/log4js-node/blob/v6.9.1/LICENSE):
|
|
@@ -430,20 +297,18 @@ Copyright 2015 Gareth Jones (with contributions from many other people)
|
|
|
430
297
|
|
|
431
298
|
```
|
|
432
299
|
|
|
433
|
-
###
|
|
300
|
+
### node-cron
|
|
434
301
|
|
|
435
|
-
This product includes source derived from [
|
|
302
|
+
This product includes source derived from [node-cron](https://github.com/merencia/node-cron) ([v4.2.1](https://github.com/merencia/node-cron/tree/v4.2.1)), distributed under the [ISC License](https://github.com/merencia/node-cron/blob/v4.2.1/LICENSE.md):
|
|
436
303
|
|
|
437
304
|
```
|
|
438
|
-
|
|
305
|
+
## ISC License
|
|
439
306
|
|
|
440
|
-
Copyright (c)
|
|
307
|
+
Copyright (c) 2016, Lucas Merencia \<lucas.merencia@gmail.com\>
|
|
441
308
|
|
|
442
|
-
Permission
|
|
309
|
+
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
|
443
310
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
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.
|
|
311
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
447
312
|
|
|
448
313
|
```
|
|
449
314
|
|
|
@@ -516,7 +381,7 @@ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
516
381
|
|
|
517
382
|
### undici
|
|
518
383
|
|
|
519
|
-
This product includes source derived from [undici](https://github.com/nodejs/undici) ([v7.
|
|
384
|
+
This product includes source derived from [undici](https://github.com/nodejs/undici) ([v7.19.0](https://github.com/nodejs/undici/tree/v7.19.0)), distributed under the [MIT License](https://github.com/nodejs/undici/blob/v7.19.0/LICENSE):
|
|
520
385
|
|
|
521
386
|
```
|
|
522
387
|
MIT License
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
const requestManager = require("../../core/request-manager");
|
|
10
10
|
const secUtils = require('../../core/sec-utils');
|
|
11
11
|
const { ATTHERATE, DOUBLE_DOLLAR, COLON } = require('../../core/constants');
|
|
12
|
-
const lodash = require('lodash');
|
|
13
12
|
const routeManager = require('../../core/route-manager');
|
|
14
13
|
const API = require("../../../nr-security-api");
|
|
15
14
|
const logger = API.getLogger();
|
|
@@ -50,7 +49,7 @@ module.exports = function initialize(shim, director) {
|
|
|
50
49
|
const path = "/" + arguments[1].join('/')
|
|
51
50
|
const stakTrace = secUtils.traceElementForRoute();
|
|
52
51
|
const splittedStack = stakTrace[0].split(DOUBLE_DOLLAR);
|
|
53
|
-
const key =
|
|
52
|
+
const key = method.toUpperCase() + ATTHERATE + path;
|
|
54
53
|
routeManager.setRoute(key, splittedStack[0]);
|
|
55
54
|
if (path.includes(COLON)) {
|
|
56
55
|
const dummyKey = key.split(COLON)[0] + ":param_input";
|
|
@@ -89,7 +88,7 @@ function extractParams(shim, params) {
|
|
|
89
88
|
let uri = request.url.split("?")[0];
|
|
90
89
|
const param = Object.values(params)[0];
|
|
91
90
|
if (uri.includes(param)) {
|
|
92
|
-
uri =
|
|
91
|
+
uri = uri.replace(param, ':param_input');
|
|
93
92
|
request.uri = uri;
|
|
94
93
|
requestManager.setRequest(transaction.id, request);
|
|
95
94
|
}
|
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
const requestManager = require("../../core/request-manager");
|
|
15
15
|
const secUtils = require('../../core/sec-utils');
|
|
16
16
|
const { ATTHERATE, DOUBLE_DOLLAR } = require('../../core/constants');
|
|
17
|
-
const lodash = require('lodash');
|
|
18
17
|
const routeManager = require('../../core/route-manager');
|
|
19
18
|
const API = require("../../../nr-security-api");
|
|
20
19
|
const logger = API.getLogger();
|
|
@@ -55,7 +54,7 @@ function wrapExpress4(shim, express) {
|
|
|
55
54
|
try {
|
|
56
55
|
const stakTrace = secUtils.traceElementForRoute();
|
|
57
56
|
const splittedStack = stakTrace[0].split(DOUBLE_DOLLAR);
|
|
58
|
-
const key =
|
|
57
|
+
const key = splittedStack[1].toUpperCase() + ATTHERATE + arguments[0];
|
|
59
58
|
routeManager.setRoute(key, splittedStack[0]);
|
|
60
59
|
} catch (error) {
|
|
61
60
|
|
|
@@ -134,7 +133,7 @@ function expressFileHook(shim, mod, fun) {
|
|
|
134
133
|
const interceptedArgs = [arguments[0]];
|
|
135
134
|
shim.interceptedArgs = interceptedArgs;
|
|
136
135
|
const request = requestManager.getRequest(shim);
|
|
137
|
-
if (request && typeof arguments[0] === STRING &&
|
|
136
|
+
if (request && typeof arguments[0] === STRING && arguments[0]) {
|
|
138
137
|
const traceObject = secUtils.getTraceObject(shim);
|
|
139
138
|
try {
|
|
140
139
|
parameters[0] = path.resolve(parameters[0]);
|
|
@@ -166,7 +165,7 @@ function wrapExpress5(shim, express) {
|
|
|
166
165
|
try {
|
|
167
166
|
const stakTrace = secUtils.traceElementForRoute();
|
|
168
167
|
const splittedStack = stakTrace[0].split(DOUBLE_DOLLAR);
|
|
169
|
-
const key =
|
|
168
|
+
const key = splittedStack[1].toUpperCase() + ATTHERATE + arguments[0];
|
|
170
169
|
routeManager.setRoute(key, splittedStack[0]);
|
|
171
170
|
} catch (error) {
|
|
172
171
|
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
const requestManager = require("../../core/request-manager");
|
|
8
8
|
const secUtils = require('../../core/sec-utils');
|
|
9
9
|
const { ATTHERATE, DOUBLE_DOLLAR } = require('../../core/constants');
|
|
10
|
-
const lodash = require('lodash');
|
|
11
10
|
const routeManager = require('../../core/route-manager');
|
|
12
11
|
const semver = require('semver')
|
|
13
12
|
const API = require("../../../nr-security-api");
|
|
@@ -44,7 +43,7 @@ const setupRouteHandler = (shim, fastify, moduleName) => {
|
|
|
44
43
|
try {
|
|
45
44
|
const stakTrace = secUtils.traceElementForRoute();
|
|
46
45
|
const splittedStack = stakTrace[0].split(DOUBLE_DOLLAR);
|
|
47
|
-
const key =
|
|
46
|
+
const key = splittedStack[1].toUpperCase() + ATTHERATE + arguments[0];
|
|
48
47
|
routeManager.setRoute(key, splittedStack[0]);
|
|
49
48
|
} catch (error) {
|
|
50
49
|
}
|
|
@@ -141,7 +140,8 @@ function extractParams(shim, req) {
|
|
|
141
140
|
}
|
|
142
141
|
});
|
|
143
142
|
}
|
|
144
|
-
const
|
|
143
|
+
const symbolKey = Object.getOwnPropertySymbols(req).find(symbol => symbol.toString() === 'Symbol(fastify.context)');
|
|
144
|
+
const txInfo = symbolKey ? req[symbolKey] : undefined;
|
|
145
145
|
if (request && txInfo && txInfo.config && txInfo.config.url) {
|
|
146
146
|
request.uri = txInfo.config.url;
|
|
147
147
|
requestManager.setRequest(transaction.id, request);
|
|
@@ -16,7 +16,6 @@ const logger = API.getLogger();
|
|
|
16
16
|
const { STRING, QUESTIONMARK, DOTDOTSLASH, UNDEFINED, SELF_FD_PATH, SLASH, SLASHDOTDOT, NR_CSEC_FUZZ_REQUEST_ID } = require('../../core/constants');
|
|
17
17
|
const fsConsts = process.binding('constants').fs;
|
|
18
18
|
const agentModule = API.getSecAgent();
|
|
19
|
-
const lodash = require('lodash');
|
|
20
19
|
|
|
21
20
|
const requireHook = require('../require/nr-require');
|
|
22
21
|
|
|
@@ -132,7 +131,7 @@ function openHook(shim, mod, moduleName) {
|
|
|
132
131
|
parameters[0] = arguments[0];
|
|
133
132
|
}
|
|
134
133
|
}
|
|
135
|
-
if (request && typeof parameters[0] === STRING &&
|
|
134
|
+
if (request && typeof parameters[0] === STRING && parameters[0]) {
|
|
136
135
|
const policy = API.getPolicy();
|
|
137
136
|
const dynamicScanningFlag = policy.data ? policy.data.vulnerabilityScan.iastScan.enabled : false;
|
|
138
137
|
const url = request.url;
|
|
@@ -187,7 +186,7 @@ function probableToFAHooks(shim, mod, moduleName) {
|
|
|
187
186
|
const interceptedArgs = [arguments[0]];
|
|
188
187
|
shim.interceptedArgs = interceptedArgs;
|
|
189
188
|
const request = requestManager.getRequest(shim);
|
|
190
|
-
if (request && typeof arguments[0] === STRING &&
|
|
189
|
+
if (request && typeof arguments[0] === STRING && arguments[0]) {
|
|
191
190
|
const traceObject = secUtils.getTraceObject(shim);
|
|
192
191
|
let absoluteParameters = [parameters[0]];
|
|
193
192
|
const secMetadata = securityMetaData.getSecurityMetaData(request, absoluteParameters, traceObject, secUtils.getExecutionId(), EVENT_TYPE.FILE_OPERATION, EVENT_CATEGORY.FILE)
|
|
@@ -222,7 +221,7 @@ function probableToFIHooks(shim, mod, moduleName) {
|
|
|
222
221
|
const interceptedArgs = [arguments[0]];
|
|
223
222
|
shim.interceptedArgs = interceptedArgs;
|
|
224
223
|
const request = requestManager.getRequest(shim);
|
|
225
|
-
if (request && typeof arguments[0] === STRING &&
|
|
224
|
+
if (request && typeof arguments[0] === STRING && arguments[0]) {
|
|
226
225
|
const traceObject = secUtils.getTraceObject(shim);
|
|
227
226
|
let absoluteParameters = [parameters[0]];
|
|
228
227
|
if (fun === COPY_FILE || fun === RENAME) {
|
|
@@ -259,7 +258,7 @@ function probablePromiseToFAHooks(shim, mod, moduleName) {
|
|
|
259
258
|
const interceptedArgs = [arguments[0]];
|
|
260
259
|
shim.interceptedArgs = interceptedArgs;
|
|
261
260
|
const request = requestManager.getRequest(shim);
|
|
262
|
-
if (request && typeof arguments[0] === STRING &&
|
|
261
|
+
if (request && typeof arguments[0] === STRING && arguments[0]) {
|
|
263
262
|
const traceObject = secUtils.getTraceObject(shim);
|
|
264
263
|
let absoluteParameters = [parameters[0]];
|
|
265
264
|
const secMetadata = securityMetaData.getSecurityMetaData(request, absoluteParameters, traceObject, secUtils.getExecutionId(), EVENT_TYPE.FILE_OPERATION, EVENT_CATEGORY.FILE)
|
|
@@ -287,7 +286,7 @@ function probablePromiseToFIHooks(shim, mod, moduleName) {
|
|
|
287
286
|
const interceptedArgs = [arguments[0]];
|
|
288
287
|
shim.interceptedArgs = interceptedArgs;
|
|
289
288
|
const request = requestManager.getRequest(shim);
|
|
290
|
-
if (request && typeof arguments[0] === STRING &&
|
|
289
|
+
if (request && typeof arguments[0] === STRING && arguments[0]) {
|
|
291
290
|
const traceObject = secUtils.getTraceObject(shim);
|
|
292
291
|
let absoluteParameters = [parameters[0]];
|
|
293
292
|
if (fun === COPY_FILE || fun === RENAME) {
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
const requestManager = require("../../core/request-manager");
|
|
16
16
|
const secUtils = require('../../core/sec-utils');
|
|
17
17
|
const { ATTHERATE, DOUBLE_DOLLAR } = require('../../core/constants');
|
|
18
|
-
const lodash = require('lodash');
|
|
19
18
|
const routeManager = require('../../core/route-manager');
|
|
20
19
|
const API = require("../../../nr-security-api");
|
|
21
20
|
const logger = API.getLogger();
|
|
@@ -58,7 +57,7 @@ function wrapProtoRoute(shim, proto) {
|
|
|
58
57
|
const obj = args[0];
|
|
59
58
|
for (let i = 0; i < obj.length; i++) {
|
|
60
59
|
try {
|
|
61
|
-
const method =
|
|
60
|
+
const method = obj[i].method.toUpperCase();
|
|
62
61
|
const path = obj[i].path;
|
|
63
62
|
const stakTrace = secUtils.traceElementForRoute();
|
|
64
63
|
const splittedStack = stakTrace[0].split(DOUBLE_DOLLAR);
|
|
@@ -13,7 +13,6 @@ const UINT8ARRAY_TYPE = 'Uint8Array';
|
|
|
13
13
|
const OBJECT_TYPE = 'object'
|
|
14
14
|
const unescapeJs = require('unescape-js');
|
|
15
15
|
const ConType = require('content-type');
|
|
16
|
-
const lodash = require('lodash');
|
|
17
16
|
const URL = require('url')
|
|
18
17
|
const secUtils = require('../../core/sec-utils');
|
|
19
18
|
const API = require("../../../nr-security-api");
|
|
@@ -69,7 +68,7 @@ function setupRequestMapCleanup() {
|
|
|
69
68
|
if (NRAgent) {
|
|
70
69
|
NRAgent.on('transactionFinished', function onTransactionFinished(transaction) {
|
|
71
70
|
const requestData = requestManager.getRequestFromId(transaction.id);
|
|
72
|
-
if (requestData && requestData.tempFiles &&
|
|
71
|
+
if (requestData && requestData.tempFiles && requestData.tempFiles.length > 0) {
|
|
73
72
|
const tempFiles = requestData.tempFiles;
|
|
74
73
|
for (let i = 0; i < tempFiles.length; i++) {
|
|
75
74
|
const file = tempFiles[i];
|
|
@@ -123,7 +122,7 @@ function outboundHook(shim, mod, method, moduleName) {
|
|
|
123
122
|
let completeURL = data.protocol + '//' + data.headers.host + (data.port ? (':' + data.port) : '') + data.path;
|
|
124
123
|
completeURL = completeURL.split(QUESTION_MARK)[0];
|
|
125
124
|
|
|
126
|
-
if (request &&
|
|
125
|
+
if (request && data.headers.host && data.path) {
|
|
127
126
|
const appUUID = API.getSecAgent().applicationInfo.applicationUUID;
|
|
128
127
|
const id = secUtils.getExecutionId().toString();
|
|
129
128
|
let generateFlag = false;
|
|
@@ -181,7 +180,7 @@ function parseFuzzheaders(requestData, transactionId) {
|
|
|
181
180
|
let encryptedData = additionalData[6].trim();
|
|
182
181
|
let hashVerifier = additionalData[7].trim();
|
|
183
182
|
|
|
184
|
-
if (
|
|
183
|
+
if (!encryptedData || !hashVerifier) {
|
|
185
184
|
return;
|
|
186
185
|
}
|
|
187
186
|
let decryptedData = secUtils.decryptData(encryptedData);
|
|
@@ -427,7 +426,8 @@ function responseHook(resp, req, shim) {
|
|
|
427
426
|
return function wrappedEnd() {
|
|
428
427
|
const response = this;
|
|
429
428
|
const request = requestManager.getRequest(shim);
|
|
430
|
-
const
|
|
429
|
+
const symbolKey = Object.getOwnPropertySymbols(response).find(symbol => symbol.toString() === 'Symbol(transactionInfo)');
|
|
430
|
+
const txInfo = symbolKey ? response[symbolKey] : undefined;
|
|
431
431
|
try {
|
|
432
432
|
if (txInfo && txInfo.error && request) {
|
|
433
433
|
ExceptionReporting.generateExceptionReportingEvent(txInfo.error, request);
|
|
@@ -756,7 +756,7 @@ function trustBoundaryCheck(sessionObject, shim) {
|
|
|
756
756
|
params.push(String(sessionObject[key]));
|
|
757
757
|
}
|
|
758
758
|
});
|
|
759
|
-
if (
|
|
759
|
+
if (params.length > 0) {
|
|
760
760
|
const traceObject = secUtils.getTraceObject(shim);
|
|
761
761
|
const secMetadata = securityMetaData.getSecurityMetaData(request, params, traceObject, secUtils.getExecutionId(), EVENT_TYPE.TRUSTBOUNDARY, EVENT_CATEGORY.TRUSTBOUNDARY)
|
|
762
762
|
const secEvent = API.generateSecEvent(secMetadata);
|
|
@@ -7,7 +7,6 @@ module.exports = initialize
|
|
|
7
7
|
const requestManager = require('../../../core/request-manager');
|
|
8
8
|
const secUtils = require('../../../core/sec-utils');
|
|
9
9
|
const { ATTHERATE, DOUBLE_DOLLAR } = require('../../../core/constants');
|
|
10
|
-
const lodash = require('lodash');
|
|
11
10
|
const routeManager = require('../../../core/route-manager');
|
|
12
11
|
const url = require('url');
|
|
13
12
|
const API = require("../../../../nr-security-api");
|
|
@@ -34,7 +33,7 @@ function initialize(shim, mod, moduleName) {
|
|
|
34
33
|
try {
|
|
35
34
|
const stakTrace = secUtils.traceElementForRoute();
|
|
36
35
|
const splittedStack = stakTrace[0].split(DOUBLE_DOLLAR);
|
|
37
|
-
const key =
|
|
36
|
+
const key = splittedStack[1].toUpperCase() + ATTHERATE + arguments[0];
|
|
38
37
|
routeManager.setRoute(key, splittedStack[0]);
|
|
39
38
|
} catch (error) {
|
|
40
39
|
}
|
|
@@ -88,7 +87,7 @@ function paramHook(shim, mod, moduleName) {
|
|
|
88
87
|
});
|
|
89
88
|
}
|
|
90
89
|
// logic to get path param
|
|
91
|
-
if (
|
|
90
|
+
if (!!result) {
|
|
92
91
|
Object.keys(result).forEach(function (key) {
|
|
93
92
|
if (result[key]) {
|
|
94
93
|
if (!request.parameterMap[key]) {
|
|
@@ -8,7 +8,6 @@ const requestManager = require("../../core/request-manager");
|
|
|
8
8
|
const API = require("../../../nr-security-api");
|
|
9
9
|
const routeManager = require('../../core/route-manager');
|
|
10
10
|
const logger = API.getLogger();
|
|
11
|
-
const lodash = require('lodash');
|
|
12
11
|
const { ATTHERATE, DOUBLE_DOLLAR, EMPTY_STR } = require('../../core/constants');
|
|
13
12
|
|
|
14
13
|
const semver = require('semver')
|
|
@@ -7,7 +7,6 @@ module.exports = initialize
|
|
|
7
7
|
const requestManager = require('../../core/request-manager');
|
|
8
8
|
const secUtils = require('../../core/sec-utils');
|
|
9
9
|
const { ATTHERATE, DOUBLE_DOLLAR } = require('../../core/constants');
|
|
10
|
-
const lodash = require('lodash');
|
|
11
10
|
const routeManager = require('../../core/route-manager');
|
|
12
11
|
const url = require('url');
|
|
13
12
|
const API = require("../../../nr-security-api");
|
|
@@ -31,7 +30,7 @@ function initialize(shim, mod, moduleName) {
|
|
|
31
30
|
return function wrapper() {
|
|
32
31
|
if (arguments[0]) {
|
|
33
32
|
try {
|
|
34
|
-
const method =
|
|
33
|
+
const method = arguments[0].method.toUpperCase();
|
|
35
34
|
const path = arguments[0].path;
|
|
36
35
|
const key = method + ATTHERATE + path;
|
|
37
36
|
const stakTrace = secUtils.traceElementForRoute();
|
|
@@ -7,7 +7,6 @@ module.exports = initialize
|
|
|
7
7
|
const requestManager = require('../../core/request-manager');
|
|
8
8
|
const secUtils = require("../../core/sec-utils");
|
|
9
9
|
const API = require("../../../nr-security-api");
|
|
10
|
-
const lodash = require('lodash');
|
|
11
10
|
const securityMetaData = require('../../core/security-metadata');
|
|
12
11
|
const { EVENT_TYPE, EVENT_CATEGORY } = require('../../core/event-constants');
|
|
13
12
|
const { NR_CSEC_FUZZ_REQUEST_ID, QUESTION_MARK, EMPTY_STRING, COLON, SLASH } = require('../../core/constants');
|
|
@@ -103,7 +102,7 @@ function fetchHook(shim, mod, methodName) {
|
|
|
103
102
|
data.port = parsedUrl.port ? parsedUrl.port : parsedUrl.port;
|
|
104
103
|
|
|
105
104
|
shim.interceptedArgs = data;
|
|
106
|
-
if (request &&
|
|
105
|
+
if (request && data.headers.host && data.path) {
|
|
107
106
|
const appUUID = API.getSecAgent().applicationInfo.applicationUUID;
|
|
108
107
|
const traceObject = secUtils.getTraceObject(shim);
|
|
109
108
|
const secMetadata = securityMetaData.getSecurityMetaData(request, data, traceObject, secUtils.getExecutionId(), EVENT_TYPE.HTTP_REQUEST, EVENT_CATEGORY.HTTP)
|
|
@@ -11,7 +11,6 @@ const logger = logs.getLogger();
|
|
|
11
11
|
const initLogger = logs.getInitLogger();
|
|
12
12
|
const LinkingMetaData = require('./LinkingMetadata');
|
|
13
13
|
const LogMessage = require('./LogMessage');
|
|
14
|
-
const lodash = require('lodash');
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
/* eslint-disable camelcase */
|
|
@@ -47,7 +46,7 @@ function AuthHeaders() {
|
|
|
47
46
|
instanceCount = 0;
|
|
48
47
|
}
|
|
49
48
|
authHeaders['NR-CSEC-IAST-SCAN-INSTANCE-COUNT'] = instanceCount ? instanceCount : 0
|
|
50
|
-
if ((NRAgent.config.security.iast_test_identifier &&
|
|
49
|
+
if ((NRAgent.config.security.iast_test_identifier && NRAgent.config.security.iast_test_identifier) || process.env.NEW_RELIC_SECURITY_IAST_TEST_IDENTIFIER) {
|
|
51
50
|
let iast_test_identifier = NRAgent.config.security.iast_test_identifier || process.env.NEW_RELIC_SECURITY_IAST_TEST_IDENTIFIER
|
|
52
51
|
authHeaders['NR-CSEC-IAST-TEST-IDENTIFIER'] = iast_test_identifier;
|
|
53
52
|
logger.debug("iast_test_identifier is:", iast_test_identifier);
|
|
@@ -6,17 +6,12 @@
|
|
|
6
6
|
|
|
7
7
|
const API = require('../../../nr-security-api');
|
|
8
8
|
const NRAgent = API.getNRAgent();
|
|
9
|
-
const { Agent } = require('./agent');
|
|
10
|
-
|
|
11
9
|
let policy;
|
|
12
|
-
const path = require('path');
|
|
13
|
-
const fs = require('fs');
|
|
14
|
-
const yaml = require('js-yaml');
|
|
15
10
|
const logs = require('./logging');
|
|
16
11
|
const logger = logs.getLogger();
|
|
17
12
|
const initLogger = logs.getInitLogger();
|
|
18
|
-
const jsonValidator = require('./jsonValidator');
|
|
19
13
|
const LOG_MESSAGES = require('./sec-agent-constants').LOG_MESSAGES;
|
|
14
|
+
const default_policy = {"version":"DEFAULT","logLevel":"INFO","policyPull":true,"policyPullInterval":60,"vulnerabilityScan":{"enabled":false,"cveScan":{"enabled":false,"enableEnvScan":false,"cveDefinitionUpdateInterval":360},"iastScan":{"enabled":false,"probing":{"interval":1,"batchSize":17}}},"protectionMode":{"enabled":false,"ipBlocking":{"enabled":false,"attackerIpBlocking":false,"ipDetectViaXFF":false,"timeout":2},"apiBlocking":{"enabled":false,"protectAllApis":false,"protectKnownVulnerableApis":false,"protectAttackedApis":false}},"sendCompleteStackTrace":false,"enableHTTPRequestPrinting":false,"policyParameters":{"allowedIps":[],"blockedIps":[],"allowedApis":[],"blockedApis":[],"allowedRequests":[]}}
|
|
20
15
|
|
|
21
16
|
function Policy() {
|
|
22
17
|
this.data = {};
|
|
@@ -40,12 +35,6 @@ function getInstance() {
|
|
|
40
35
|
// sets up policy data to use globally.
|
|
41
36
|
function setPolicyData(data) {
|
|
42
37
|
policy = getInstance();
|
|
43
|
-
const jsonValidationResult = jsonValidator.validate(data);
|
|
44
|
-
if (jsonValidationResult && jsonValidationResult.errors && jsonValidationResult.errors.length > 0) {
|
|
45
|
-
logger.error(LOG_MESSAGES.EXP_RAISE_POL, JSON.stringify(jsonValidationResult.errors));
|
|
46
|
-
logger.info(LOG_MESSAGES.FALLBACK_TO_CURR_POLICY, JSON.stringify(policy.data));
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
38
|
if (policy.data.version !== data.version) {
|
|
50
39
|
policy.data = data;
|
|
51
40
|
appInfoVersionUpdate(policy, data);
|
|
@@ -59,13 +48,7 @@ function setPolicyData(data) {
|
|
|
59
48
|
|
|
60
49
|
// function to setup default policy provided in resources directory
|
|
61
50
|
function setDefaultPolicy() {
|
|
62
|
-
let default_policy_file = path.resolve(__dirname, '../../resources/default-policy.yaml');
|
|
63
|
-
if(process.platform == 'win32'){
|
|
64
|
-
default_policy_file = path.resolve(__dirname, '..\\..\\resources\\default-policy.yaml');
|
|
65
|
-
}
|
|
66
|
-
// Get document, or throw exception on error
|
|
67
51
|
try {
|
|
68
|
-
const default_policy = yaml.load(fs.readFileSync(default_policy_file, 'utf8'));
|
|
69
52
|
policy = getInstance();
|
|
70
53
|
policy.data = default_policy;
|
|
71
54
|
logger.info(LOG_MESSAGES.DEFAULT_POL_SET, JSON.stringify(policy.data));
|
|
@@ -76,8 +59,8 @@ function setDefaultPolicy() {
|
|
|
76
59
|
|
|
77
60
|
/**
|
|
78
61
|
* Function to set applicationInfo with updated policy version
|
|
79
|
-
* @param {*} policy
|
|
80
|
-
* @param {*} data
|
|
62
|
+
* @param {*} policy
|
|
63
|
+
* @param {*} data
|
|
81
64
|
*/
|
|
82
65
|
function appInfoVersionUpdate(policy, data) {
|
|
83
66
|
const appInfo = require('./applicationinfo').getInstance();
|
|
@@ -9,7 +9,6 @@ const { BasicInfo } = require('./event');
|
|
|
9
9
|
const { JsonHandler } = require('./json-file-handler');
|
|
10
10
|
const fs = require('fs');
|
|
11
11
|
const shaSizeUtil = require('./sha-size-util');
|
|
12
|
-
const _ = require('lodash');
|
|
13
12
|
const OS = require('os');
|
|
14
13
|
const { Agent } = require('./agent');
|
|
15
14
|
const commonUtils = require('./commonUtils');
|
|
@@ -115,7 +114,7 @@ function ApplicationInfo () {
|
|
|
115
114
|
this.identifier.envInfo.name = getHostName();
|
|
116
115
|
this.identifier.envInfo.ipaddress = localIpAddress();
|
|
117
116
|
|
|
118
|
-
if (
|
|
117
|
+
if (containerId) {
|
|
119
118
|
this.identifier.id = containerId;
|
|
120
119
|
this.identifier.kind = "CONTAINER";
|
|
121
120
|
const containerProps = setContainerProperties(this.identifier);
|
|
@@ -131,10 +130,10 @@ function ApplicationInfo () {
|
|
|
131
130
|
} else if (isLambda) {
|
|
132
131
|
const lambdaARN = process.env[AWS_LAMBDA_QUALIFIED_ARN_ENV_IDENTIFIER];
|
|
133
132
|
const lambdaVersion = process.env[AWS_LAMBDA_FUNCTION_VERSION_ENV_IDENTIFIER];
|
|
134
|
-
this.applicationUUID =
|
|
133
|
+
this.applicationUUID = !lambdaARN ? ApplicationInfo.Constants.EMPTY_UUID : `${lambdaARN}:${lambdaVersion}`;
|
|
135
134
|
this.identifier.isHost = true;
|
|
136
135
|
this.identifier.isLambda = isLambda;
|
|
137
|
-
this.identifier.lambdaFunctionARN =
|
|
136
|
+
this.identifier.lambdaFunctionARN = !lambdaARN
|
|
138
137
|
? `${process.env[AWS_LAMBDA_FUNCTION_NAME_ENV_IDENTIFIER]}:${lambdaVersion}`
|
|
139
138
|
: `${lambdaARN}:${lambdaVersion}`;
|
|
140
139
|
this.identifier.lambdaAWSSessionToken = process.env[AWS_SESSION_TOKEN_ENV_IDENTIFIER];
|
|
@@ -347,7 +346,7 @@ function getContainerID () {
|
|
|
347
346
|
// podman
|
|
348
347
|
if (st.indexOf(LIBPOD) > -1 && st.indexOf(SCOPE_IDENTIFIER) > -1) {
|
|
349
348
|
const containerId = st.split(LIBPOD).pop().split(SCOPE_IDENTIFIER)[0];
|
|
350
|
-
if (
|
|
349
|
+
if (containerId) {
|
|
351
350
|
return containerId;
|
|
352
351
|
}
|
|
353
352
|
}
|
|
@@ -17,16 +17,14 @@ const { CSEC_HOME, SLASH, EMPTY_STR } = require('./sec-agent-constants');
|
|
|
17
17
|
const njsAgentConstants = require('./sec-agent-constants');
|
|
18
18
|
const API = require('../../../nr-security-api');
|
|
19
19
|
const NRAgent = API.getNRAgent();
|
|
20
|
-
const lodash = require('lodash')
|
|
21
20
|
const backupLogFileRegex = /.log.\d/gm;
|
|
22
21
|
let websocketHealth;
|
|
23
22
|
|
|
24
23
|
const ringBuffer = require('ringbufferjs');
|
|
25
24
|
const bufferedLogEvents = new ringBuffer(10);
|
|
26
|
-
const
|
|
25
|
+
const nodeCron = require('node-cron');
|
|
27
26
|
let scanStartTime = 0;
|
|
28
27
|
let trafficStartedTime = 0;
|
|
29
|
-
const cron = require('cron');
|
|
30
28
|
|
|
31
29
|
const skip_detection_category_map = {
|
|
32
30
|
insecure_settings: ['CRYPTO', 'HASH', 'RANDOM', 'SECURE_COOKIE', 'TRUSTBOUNDARY'],
|
|
@@ -72,7 +70,7 @@ function getKindIdPair(identifier, hostId) {
|
|
|
72
70
|
|
|
73
71
|
/**
|
|
74
72
|
* Utility to check worker thread support
|
|
75
|
-
* @returns
|
|
73
|
+
* @returns
|
|
76
74
|
*/
|
|
77
75
|
function hasWorker() {
|
|
78
76
|
let workerFlag = false;
|
|
@@ -109,7 +107,7 @@ function runtimeSupportsAsyncFunctionGenerators() {
|
|
|
109
107
|
|
|
110
108
|
/**
|
|
111
109
|
* Utility to create directory and set permissions
|
|
112
|
-
* @param {*} dir
|
|
110
|
+
* @param {*} dir
|
|
113
111
|
*/
|
|
114
112
|
function createPathIfNotExist(dir) {
|
|
115
113
|
try {
|
|
@@ -131,7 +129,7 @@ function createPathIfNotExist(dir) {
|
|
|
131
129
|
|
|
132
130
|
/**
|
|
133
131
|
* Utility to get OS
|
|
134
|
-
* @returns
|
|
132
|
+
* @returns
|
|
135
133
|
*/
|
|
136
134
|
function getOS() {
|
|
137
135
|
if (process.platform === 'darwin') {
|
|
@@ -351,11 +349,11 @@ function logRollOver() {
|
|
|
351
349
|
|
|
352
350
|
/**
|
|
353
351
|
* Utility to get validator service endpoint
|
|
354
|
-
* @returns
|
|
352
|
+
* @returns
|
|
355
353
|
*/
|
|
356
354
|
function getValidatorServiceEndpointURL() {
|
|
357
355
|
let validatorServiceEndpointURL = NRAgent ? NRAgent.config.security.validator_service_url : "wss://csec.nr-data.net";
|
|
358
|
-
if (
|
|
356
|
+
if (!validatorServiceEndpointURL) {
|
|
359
357
|
validatorServiceEndpointURL = "wss://csec.nr-data.net";
|
|
360
358
|
}
|
|
361
359
|
return validatorServiceEndpointURL
|
|
@@ -363,7 +361,7 @@ function getValidatorServiceEndpointURL() {
|
|
|
363
361
|
|
|
364
362
|
/**
|
|
365
363
|
* Utility to get security mode
|
|
366
|
-
* @returns
|
|
364
|
+
* @returns
|
|
367
365
|
*/
|
|
368
366
|
function getCSECmode() {
|
|
369
367
|
const mode = NRAgent ? NRAgent.config.security.mode : 'IAST';
|
|
@@ -372,7 +370,7 @@ function getCSECmode() {
|
|
|
372
370
|
|
|
373
371
|
/**
|
|
374
372
|
* Utility to get path of CA Cert
|
|
375
|
-
* @returns
|
|
373
|
+
* @returns
|
|
376
374
|
*/
|
|
377
375
|
function getPathOfCACert() {
|
|
378
376
|
let relativePath = path.resolve(__dirname, '../../resources/cert.pem');
|
|
@@ -384,7 +382,7 @@ function getPathOfCACert() {
|
|
|
384
382
|
}
|
|
385
383
|
/**
|
|
386
384
|
* Setting ws health status
|
|
387
|
-
* @param {*} status
|
|
385
|
+
* @param {*} status
|
|
388
386
|
*/
|
|
389
387
|
function setWSHealthStatus(status) {
|
|
390
388
|
websocketHealth = status;
|
|
@@ -424,7 +422,7 @@ function addLogEventtoBuffer(logMessage) {
|
|
|
424
422
|
}
|
|
425
423
|
/**
|
|
426
424
|
* Utility to get framework from APM
|
|
427
|
-
* @returns
|
|
425
|
+
* @returns
|
|
428
426
|
*/
|
|
429
427
|
function getFramework() {
|
|
430
428
|
let framework = EMPTY_STR;
|
|
@@ -451,6 +449,8 @@ function listSkipDetectionCategory() {
|
|
|
451
449
|
return skipList;
|
|
452
450
|
}
|
|
453
451
|
|
|
452
|
+
let cronJobInstance = null;
|
|
453
|
+
|
|
454
454
|
function refreshAgent() {
|
|
455
455
|
const { Agent } = require('./agent');
|
|
456
456
|
if (Agent.getAgent().status.getStatus() == 'disabled' || Agent.getAgent().delayed) {
|
|
@@ -465,22 +465,32 @@ function refreshAgent() {
|
|
|
465
465
|
function executeCronSchedule() {
|
|
466
466
|
try {
|
|
467
467
|
let schedule = NRAgent.config.security.scan_schedule.schedule;
|
|
468
|
-
if (
|
|
468
|
+
if (!schedule) {
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Prevent creating multiple cron jobs
|
|
473
|
+
if (cronJobInstance) {
|
|
469
474
|
return;
|
|
470
475
|
}
|
|
476
|
+
|
|
471
477
|
logger.debug("Schedule config is set to:", schedule);
|
|
472
478
|
schedule = schedule.replace(/\?/g, '*');
|
|
473
|
-
logger.info("Security Agent scheduled time is set to:",
|
|
474
|
-
const
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
479
|
+
logger.info("Security Agent scheduled time is set to:", schedule);
|
|
480
|
+
const { Agent } = require('./agent');
|
|
481
|
+
Agent.getAgent().delayed = true
|
|
482
|
+
cronJobInstance = nodeCron.schedule(
|
|
483
|
+
schedule,
|
|
484
|
+
() => {
|
|
485
|
+
logger.info('Cron schedule invoked at the schedule:',schedule);
|
|
486
|
+
refreshAgent();
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
scheduled: true,
|
|
490
|
+
runOnInit: false,
|
|
491
|
+
}
|
|
483
492
|
);
|
|
493
|
+
logger.debug("Cron job instance created successfully");
|
|
484
494
|
} catch (error) {
|
|
485
495
|
logger.error("Error while processing schedule. Please check schedule cron expression", error);
|
|
486
496
|
shutDownAgent();
|
|
@@ -506,7 +516,7 @@ function honourDurationConfiguration() {
|
|
|
506
516
|
}
|
|
507
517
|
/**
|
|
508
518
|
* Utility to send error to error inbox of APM
|
|
509
|
-
* @param {*} error
|
|
519
|
+
* @param {*} error
|
|
510
520
|
*/
|
|
511
521
|
function sendErrorToErrorInbox(error) {
|
|
512
522
|
API.newrelic.noticeError(error);
|
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
* SPDX-License-Identifier: New Relic Software License v1.0
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const _ = require('lodash');
|
|
7
|
-
|
|
8
6
|
const logger = require('../logging').getLogger();
|
|
9
7
|
|
|
10
8
|
let lambdaClient;
|
|
@@ -21,7 +19,7 @@ function invokeLambda (arn, version, data) {
|
|
|
21
19
|
if (!lambdaClient) {
|
|
22
20
|
throw new Error('Cannot invoke lambda, client not initialized');
|
|
23
21
|
}
|
|
24
|
-
if (
|
|
22
|
+
if (!arn || !version) {
|
|
25
23
|
throw new Error('Cannot invoke lambda, invalid ARN specified');
|
|
26
24
|
}
|
|
27
25
|
const dataString = JSON.stringify(data);
|
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
* SPDX-License-Identifier: New Relic Software License v1.0
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const _ = require('lodash');
|
|
7
|
-
|
|
8
6
|
const { SERVER_COMMAND, SEVERE } = require('../../../sec-agent-constants');
|
|
9
7
|
const UnsupportedAgentHandler = require('./unsupported-agent-handler');
|
|
10
8
|
const StartupHandshakeHandler = require('./startup-handshake-handler');
|
|
@@ -47,7 +45,7 @@ const handle = function handle (json) {
|
|
|
47
45
|
};
|
|
48
46
|
|
|
49
47
|
const setLogger = function setLogger (logger) {
|
|
50
|
-
|
|
48
|
+
Object.values(commandHandlerMap).forEach((handler) => {
|
|
51
49
|
handler.setLogger(logger);
|
|
52
50
|
});
|
|
53
51
|
NoOpHandler.setLogger(logger);
|
|
@@ -10,7 +10,6 @@ const policyManager = require('./Policy');
|
|
|
10
10
|
const LinkingMetaData = require('./LinkingMetadata');
|
|
11
11
|
const API = require('../../../nr-security-api');
|
|
12
12
|
const NRAgent = API.getNRAgent();
|
|
13
|
-
const lodash = require('lodash');
|
|
14
13
|
const commonUtils = require('./commonUtils');
|
|
15
14
|
const crypto = require('crypto');
|
|
16
15
|
/**
|
|
@@ -32,7 +31,8 @@ function BasicInfo() {
|
|
|
32
31
|
this.framework = EMPTY_STR;
|
|
33
32
|
}
|
|
34
33
|
this.groupName = commonUtils.getCSECmode();
|
|
35
|
-
|
|
34
|
+
const policyData = policyManager.getInstance().data;
|
|
35
|
+
this.policyVersion = (policyData && Object.keys(policyData).length > 0) ? policyData.version : 'DEFAULT';
|
|
36
36
|
|
|
37
37
|
if (NRAgent && NRAgent.config) {
|
|
38
38
|
this.appAccountId = NRAgent.config.account_id;
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* SPDX-License-Identifier: New Relic Software License v1.0
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const _ = require('lodash');
|
|
7
6
|
const decode = require('unescape');
|
|
8
7
|
const querystring = require('querystring');
|
|
9
8
|
|
|
@@ -178,7 +177,7 @@ function getXSSConstructs (data) {
|
|
|
178
177
|
return constructs;
|
|
179
178
|
}
|
|
180
179
|
|
|
181
|
-
if (
|
|
180
|
+
if (!tagName) {
|
|
182
181
|
return constructs;
|
|
183
182
|
}
|
|
184
183
|
|
|
@@ -206,7 +205,7 @@ function getXSSConstructs (data) {
|
|
|
206
205
|
attribRegex.lastIndex++;
|
|
207
206
|
}
|
|
208
207
|
|
|
209
|
-
let attribData =
|
|
208
|
+
let attribData = attribMatcher[0].trim();
|
|
210
209
|
|
|
211
210
|
currPos = attribRegex.lastIndex - 1;
|
|
212
211
|
tmpCurrPos = data.indexOf(ANGLE_END, tmpStartPos);
|
|
@@ -214,7 +213,7 @@ function getXSSConstructs (data) {
|
|
|
214
213
|
if ((tmpCurrPos === -1 || attribMatcher.index < tmpCurrPos)) {
|
|
215
214
|
tmpStartPos = tmpCurrPos = attribRegex.lastIndex - 1;
|
|
216
215
|
tmpStartPos++;
|
|
217
|
-
if (
|
|
216
|
+
if (!attribMatcher[3] && attribRegex.lastIndex >= tmpCurrPos) {
|
|
218
217
|
tmpStartPos = tmpCurrPos = data.indexOf(ANGLE_END, attribMatcher.index);
|
|
219
218
|
if (tmpStartPos > -1) {
|
|
220
219
|
attribData = attribData.substring(0, tmpStartPos);
|
|
@@ -224,7 +223,7 @@ function getXSSConstructs (data) {
|
|
|
224
223
|
const val = attribData.split(EQUALS)[1];
|
|
225
224
|
const upperCaseAttribKey = key.toUpperCase();
|
|
226
225
|
|
|
227
|
-
if (
|
|
226
|
+
if (key && (upperCaseAttribKey.startsWith('ON') || upperCaseAttribKey === 'SRC' || upperCaseAttribKey === 'HREF' ||
|
|
228
227
|
upperCaseAttribKey === 'ACTION' || upperCaseAttribKey === 'FORMACTION' || upperCaseAttribKey === 'SRCDOC' ||
|
|
229
228
|
upperCaseAttribKey === 'DATA' || decode(val).toUpperCase().replace(/\s/g, '').includes('JAVASCRIPT:') ||
|
|
230
229
|
htmlEntities.decode(val).toUpperCase().replace(/\s/g, '').includes('JAVASCRIPT:'))) {
|
|
@@ -259,7 +258,7 @@ function getXSSConstructs (data) {
|
|
|
259
258
|
let body = data.substring(currPos + 1);
|
|
260
259
|
const tagEnd = body.indexOf(ANGLE_END);
|
|
261
260
|
|
|
262
|
-
if (
|
|
261
|
+
if (body && tagEnd !== -1) {
|
|
263
262
|
body = data.substring(tagEnd);
|
|
264
263
|
constructs.add(data.substring(startPos, currPos + 1) + body);
|
|
265
264
|
break;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@newrelic/security-agent",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"description": "New Relic Security Agent for Node.js",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"jsonVersion": "1.2.9",
|
|
@@ -41,22 +41,18 @@
|
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"check-disk-space": "^3.4.0",
|
|
43
43
|
"content-type": "^1.0.5",
|
|
44
|
-
"cron": "^3.1.7",
|
|
45
44
|
"fast-safe-stringify": "^2.1.1",
|
|
46
45
|
"find-package-json": "^1.2.0",
|
|
47
46
|
"hash.js": "^1.1.7",
|
|
48
47
|
"html-entities": "^2.3.6",
|
|
49
48
|
"https-proxy-agent": "^7.0.4",
|
|
50
49
|
"is-invalid-path": "^1.0.2",
|
|
51
|
-
"js-yaml": "^4.1.1",
|
|
52
|
-
"jsonschema": "^1.4.1",
|
|
53
|
-
"lodash": "^4.17.21",
|
|
54
50
|
"log4js": "^6.9.1",
|
|
55
|
-
"
|
|
51
|
+
"node-cron": "^4.2.1",
|
|
56
52
|
"request-ip": "^3.3.0",
|
|
57
53
|
"ringbufferjs": "^2.0.0",
|
|
58
54
|
"semver": "^7.5.4",
|
|
59
|
-
"undici": "^7.
|
|
55
|
+
"undici": "^7.19.0",
|
|
60
56
|
"unescape": "^1.0.1",
|
|
61
57
|
"unescape-js": "^1.1.4",
|
|
62
58
|
"uuid": "^9.0.1",
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2023 New Relic Corporation. All rights reserved.
|
|
3
|
-
* SPDX-License-Identifier: New Relic Software License v1.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const Validator = require('jsonschema').Validator;
|
|
7
|
-
const v = new Validator();
|
|
8
|
-
const schema = {
|
|
9
|
-
title: 'LCPolicy',
|
|
10
|
-
description: 'A policy for language collectors',
|
|
11
|
-
type: 'object',
|
|
12
|
-
properties: {
|
|
13
|
-
version: {
|
|
14
|
-
type: 'string',
|
|
15
|
-
minLength: 1
|
|
16
|
-
},
|
|
17
|
-
policyPull: {
|
|
18
|
-
type: 'boolean'
|
|
19
|
-
},
|
|
20
|
-
policyPullInterval: {
|
|
21
|
-
type: 'integer',
|
|
22
|
-
minimum: 0,
|
|
23
|
-
maximum: 2678400
|
|
24
|
-
},
|
|
25
|
-
vulnerabilityScan: {
|
|
26
|
-
type: 'object',
|
|
27
|
-
properties: {
|
|
28
|
-
enabled: {
|
|
29
|
-
type: 'boolean'
|
|
30
|
-
},
|
|
31
|
-
iastScan: {
|
|
32
|
-
type: 'object',
|
|
33
|
-
properties: {
|
|
34
|
-
enabled: {
|
|
35
|
-
type: 'boolean'
|
|
36
|
-
},
|
|
37
|
-
probing: {
|
|
38
|
-
type: 'object',
|
|
39
|
-
properties: {
|
|
40
|
-
interval: {
|
|
41
|
-
type: 'integer',
|
|
42
|
-
minimum: 1,
|
|
43
|
-
maximum: 60
|
|
44
|
-
},
|
|
45
|
-
batchSize: {
|
|
46
|
-
type: 'integer',
|
|
47
|
-
minimum: 1,
|
|
48
|
-
maximum: 300
|
|
49
|
-
}
|
|
50
|
-
},
|
|
51
|
-
required: [
|
|
52
|
-
'interval',
|
|
53
|
-
'batchSize'
|
|
54
|
-
]
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
required: [
|
|
58
|
-
'enabled',
|
|
59
|
-
'probing'
|
|
60
|
-
]
|
|
61
|
-
}
|
|
62
|
-
},
|
|
63
|
-
required: [
|
|
64
|
-
'enabled',
|
|
65
|
-
'iastScan'
|
|
66
|
-
]
|
|
67
|
-
},
|
|
68
|
-
protectionMode: {
|
|
69
|
-
type: 'object',
|
|
70
|
-
properties: {
|
|
71
|
-
enabled: {
|
|
72
|
-
type: 'boolean'
|
|
73
|
-
},
|
|
74
|
-
ipBlocking: {
|
|
75
|
-
type: 'object',
|
|
76
|
-
properties: {
|
|
77
|
-
enabled: {
|
|
78
|
-
type: 'boolean'
|
|
79
|
-
},
|
|
80
|
-
attackerIpBlocking: {
|
|
81
|
-
type: 'boolean'
|
|
82
|
-
},
|
|
83
|
-
ipDetectViaXFF: {
|
|
84
|
-
type: 'boolean'
|
|
85
|
-
}
|
|
86
|
-
},
|
|
87
|
-
required: [
|
|
88
|
-
'enabled',
|
|
89
|
-
'attackerIpBlocking',
|
|
90
|
-
'ipDetectViaXFF'
|
|
91
|
-
]
|
|
92
|
-
},
|
|
93
|
-
apiBlocking: {
|
|
94
|
-
type: 'object',
|
|
95
|
-
properties: {
|
|
96
|
-
enabled: {
|
|
97
|
-
type: 'boolean'
|
|
98
|
-
},
|
|
99
|
-
protectAllApis: {
|
|
100
|
-
type: 'boolean'
|
|
101
|
-
},
|
|
102
|
-
protectKnownVulnerableApis: {
|
|
103
|
-
type: 'boolean'
|
|
104
|
-
},
|
|
105
|
-
protectAttackedApis: {
|
|
106
|
-
type: 'boolean'
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
required: [
|
|
110
|
-
'enabled',
|
|
111
|
-
'protectAllApis',
|
|
112
|
-
'protectKnownVulnerableApis',
|
|
113
|
-
'protectAttackedApis'
|
|
114
|
-
]
|
|
115
|
-
}
|
|
116
|
-
},
|
|
117
|
-
required: [
|
|
118
|
-
'enabled',
|
|
119
|
-
'ipBlocking',
|
|
120
|
-
'apiBlocking'
|
|
121
|
-
]
|
|
122
|
-
},
|
|
123
|
-
sendCompleteStackTrace: {
|
|
124
|
-
type: 'boolean'
|
|
125
|
-
},
|
|
126
|
-
enableHTTPRequestPrinting: {
|
|
127
|
-
type: 'boolean'
|
|
128
|
-
}
|
|
129
|
-
},
|
|
130
|
-
required: [
|
|
131
|
-
'version',
|
|
132
|
-
'policyPull',
|
|
133
|
-
'policyPullInterval',
|
|
134
|
-
'vulnerabilityScan',
|
|
135
|
-
'protectionMode',
|
|
136
|
-
'sendCompleteStackTrace',
|
|
137
|
-
'enableHTTPRequestPrinting'
|
|
138
|
-
]
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
function validate (data) {
|
|
142
|
-
const result = v.validate(data, schema);
|
|
143
|
-
return result;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
module.exports = {
|
|
148
|
-
validate
|
|
149
|
-
};
|