From 092fbc44d65a2c977bbcf7ed9dc8ca919f815299 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Wed, 4 Sep 2024 21:27:34 +0530 Subject: [PATCH 01/50] feat: Support to honour proxy settings via config (#236) --- .../core/connections/websocket/proxy-util.js | 61 ++++++ .../core/connections/websocket/websocket.js | 13 +- package-lock.json | 179 +++++++++++++++--- package.json | 1 + 4 files changed, 229 insertions(+), 25 deletions(-) create mode 100644 lib/nr-security-agent/lib/core/connections/websocket/proxy-util.js diff --git a/lib/nr-security-agent/lib/core/connections/websocket/proxy-util.js b/lib/nr-security-agent/lib/core/connections/websocket/proxy-util.js new file mode 100644 index 00000000..c5ebd915 --- /dev/null +++ b/lib/nr-security-agent/lib/core/connections/websocket/proxy-util.js @@ -0,0 +1,61 @@ +/* + * Copyright 2024 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: New Relic Software License v1.0 + */ + +'use strict' + +const { HttpsProxyAgent } = require('https-proxy-agent') +const logs = require('../../logging'); +let logger = logs.getLogger(); +const commonUtils = require('../../commonUtils'); +const fs = require('fs'); + +let agentProxyWithKeepAlive = null + +exports.proxyAgent = function proxyAgent(config) { + if (null !== agentProxyWithKeepAlive) { + return agentProxyWithKeepAlive + } + const proxyUrl = proxyOptions(config) + let proxyOpts = { + secureEndpoint: config.ssl, + auth: proxyUrl.auth, + ca: config?.certificates?.length ? config.certificates : [], + keepAlive: true + } + let cert = ''; + try { + const certPath = commonUtils.getPathOfCACert(); + cert = fs.readFileSync(certPath, 'utf8'); + } catch (error) { + logger.error("Error in reading certificate:", error); + + } + proxyOpts.ca.push(cert); + logger.info(`Using proxy: ${proxyUrl}`) + agentProxyWithKeepAlive = new HttpsProxyAgent(proxyUrl, proxyOpts) + return agentProxyWithKeepAlive +} + +/** + * Utility to create proxy URL + * @param config + * @returns + */ +function proxyOptions(config) { + let proxyUrl + if (config.proxy) { + proxyUrl = config.proxy + } else { + proxyUrl = 'https://' + let proxyAuth = config.proxy_user + if (config.proxy_pass !== '') { + proxyAuth += ':' + config.proxy_pass + proxyUrl += `${proxyAuth}@` + } + + proxyUrl += `${config.proxy_host || 'localhost'}:${config.proxy_port || 80}` + } + return proxyUrl +} diff --git a/lib/nr-security-agent/lib/core/connections/websocket/websocket.js b/lib/nr-security-agent/lib/core/connections/websocket/websocket.js index 2fcab579..15ffb2dd 100644 --- a/lib/nr-security-agent/lib/core/connections/websocket/websocket.js +++ b/lib/nr-security-agent/lib/core/connections/websocket/websocket.js @@ -22,6 +22,7 @@ const statusUtils = require('../../statusUtils'); const commonUtils = require('../../commonUtils'); const IASTUtil = require('../websocket/response/IASTUtils'); const LogMessage = require('../../LogMessage'); +const proxyUtil = require('./proxy-util'); const BUSY = 'busy'; const IDLE = 'idle'; @@ -105,7 +106,7 @@ SecWebSocket.prototype.init = function init() { const authHeaders = require('../../Auth-headers').getInstance(); initLogger.info(`Connecting to Validator at ${validatorService}`); IASTUtil.IASTCleanup(); - let cert = '' + let cert = ''; try { const certPath = commonUtils.getPathOfCACert(); cert = fs.readFileSync(certPath, 'utf8'); @@ -115,8 +116,14 @@ SecWebSocket.prototype.init = function init() { commonUtils.addLogEventtoBuffer(logMessage); } - - webSocket = new WebSocket(validatorService, { headers: authHeaders, cert: cert, handshakeTimeout: 10000 }); + const isProxy = !!(NRAgent.config.proxy || NRAgent.config.proxy_port || NRAgent.config.proxy_host) + if(isProxy){ + const agentWithProxy = proxyUtil.proxyAgent(NRAgent.config); + webSocket = new WebSocket(validatorService, { headers: authHeaders, cert: cert, handshakeTimeout: 10000, agent:agentWithProxy }); + } + else{ + webSocket = new WebSocket(validatorService, { headers: authHeaders, cert: cert, handshakeTimeout: 10000 }); + } webSocket.on(WS_ON_OPEN, this.openCB); webSocket.on(WS_ON_MSG, this.msgCB); diff --git a/package-lock.json b/package-lock.json index 22da26e6..7621f345 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "find-package-json": "^1.2.0", "hash.js": "^1.1.7", "html-entities": "^2.3.6", + "https-proxy-agent": "^7.0.4", "is-invalid-path": "^1.0.2", "js-yaml": "^4.1.0", "jsonschema": "^1.4.1", @@ -2441,6 +2442,33 @@ "npm": ">=6" } }, + "node_modules/@newrelic/native-metrics/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/@newrelic/native-metrics/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@newrelic/newrelic-oss-cli": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/@newrelic/newrelic-oss-cli/-/newrelic-oss-cli-0.1.2.tgz", @@ -5728,15 +5756,14 @@ } }, "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dependencies": { - "debug": "4" + "debug": "^4.3.4" }, "engines": { - "node": ">= 6.0.0" + "node": ">= 14" } }, "node_modules/aggregate-error": { @@ -8918,16 +8945,15 @@ } }, "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", "dependencies": { - "agent-base": "6", + "agent-base": "^7.0.2", "debug": "4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/hyperlinker": { @@ -10362,6 +10388,31 @@ "node": ">=12.22.0" } }, + "node_modules/mongodb-memory-server-core/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/mongodb-memory-server-core/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/mongodb-memory-server-core/node_modules/tslib": { "version": "2.5.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", @@ -10531,6 +10582,18 @@ "@newrelic/native-metrics": "^9.0.1" } }, + "node_modules/newrelic/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/newrelic/node_modules/concat-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", @@ -10546,6 +10609,19 @@ "typedarray": "^0.0.6" } }, + "node_modules/newrelic/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/newrelic/node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -17925,6 +18001,29 @@ "https-proxy-agent": "^5.0.1", "nan": "^2.17.0", "semver": "^7.5.2" + }, + "dependencies": { + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "optional": true, + "requires": { + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "optional": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + } } }, "@newrelic/newrelic-oss-cli": { @@ -20495,12 +20594,11 @@ "requires": {} }, "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "requires": { - "debug": "4" + "debug": "^4.3.4" } }, "aggregate-error": { @@ -22863,12 +22961,11 @@ } }, "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", "requires": { - "agent-base": "6", + "agent-base": "^7.0.2", "debug": "4" } }, @@ -23990,6 +24087,25 @@ "yauzl": "^2.10.0" }, "dependencies": { + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "tslib": { "version": "2.5.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", @@ -24134,6 +24250,15 @@ "winston-transport": "^4.5.0" }, "dependencies": { + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, "concat-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", @@ -24146,6 +24271,16 @@ "typedarray": "^0.0.6" } }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", diff --git a/package.json b/package.json index 20bb7d94..c4eae34e 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "find-package-json": "^1.2.0", "hash.js": "^1.1.7", "html-entities": "^2.3.6", + "https-proxy-agent": "^7.0.4", "is-invalid-path": "^1.0.2", "js-yaml": "^4.1.0", "jsonschema": "^1.4.1", From 86d4f504af4e2fd1118cebc0ce513df2a3be52bf Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 5 Sep 2024 11:53:25 +0530 Subject: [PATCH 02/50] fix: Fix for file integrity security event generation (#249) --- lib/instrumentation-security/hooks/fs/nr-fs.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/instrumentation-security/hooks/fs/nr-fs.js b/lib/instrumentation-security/hooks/fs/nr-fs.js index 0ae06066..76882aae 100644 --- a/lib/instrumentation-security/hooks/fs/nr-fs.js +++ b/lib/instrumentation-security/hooks/fs/nr-fs.js @@ -25,6 +25,7 @@ const RENAME = 'rename'; const FSReqCallback = 'FSReqCallback'; const FSReqWrap = 'FSReqWrap'; const OBJECT = 'object'; +const semver = require('semver'); const functionsProbableToFA = [ "fstat", @@ -37,7 +38,7 @@ const functionsProbableToFA = [ "realpath", ]; -const functionProbableToFI = [ +let functionProbableToFI = [ "rename", "ftruncate", "rmdir", @@ -214,6 +215,9 @@ function probableToFAHooks(shim, mod, moduleName) { * @param {*} moduleName */ function probableToFIHooks(shim, mod, moduleName) { + if (semver.satisfies(process.version, '>19.0.0')) { + functionProbableToFI.push('writeFileSync'); + } functionProbableToFI.forEach(function (fun) { shim.wrap(mod, fun, function makeFIWrapper(shim, fn) { logger.debug(`Instrumenting ${moduleName}.${fun}`); @@ -228,7 +232,7 @@ function probableToFIHooks(shim, mod, moduleName) { parameters[0] = path.resolve(parameters[0]); parameters[1] = path.resolve(parameters[1]); } catch (error) { - + } let absoluteParameters = [parameters[0]]; if (fun === COPY_FILE || fun === RENAME) { From 219261067d60ca5cc2763a9498b18d223d24342d Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Fri, 6 Sep 2024 17:09:44 +0530 Subject: [PATCH 03/50] update in scan rate limit flag --- .../lib/core/connections/websocket/response/IASTUtils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/nr-security-agent/lib/core/connections/websocket/response/IASTUtils.js b/lib/nr-security-agent/lib/core/connections/websocket/response/IASTUtils.js index 9c171ce4..139621bf 100644 --- a/lib/nr-security-agent/lib/core/connections/websocket/response/IASTUtils.js +++ b/lib/nr-security-agent/lib/core/connections/websocket/response/IASTUtils.js @@ -73,8 +73,8 @@ function generateIASTDataRequest() { const NRAgent = API.getNRAgent(); - if (NRAgent.config.security.scan_controllers.scan_request_rate_limit) { - let scanRateLimit = NRAgent.config.security.scan_controllers.scan_request_rate_limit; + if (NRAgent.config.security.scan_controllers.iast_scan_request_rate_limit) { + let scanRateLimit = NRAgent.config.security.scan_controllers.iast_scan_request_rate_limit; batchSize = parseInt(scanRateLimit/12); if (scanRateLimit < 12){ batchSize = 1; From df4f2830c770a7e80235a6420c0bb36e8818db58 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 12 Sep 2024 16:10:24 +0530 Subject: [PATCH 04/50] feat: Functionality to truncate Incoming HTTP request upto default limit (#119) Co-authored-by: pratik-k2 --- .../core/request-manager.js | 4 ++- .../core/sec-utils.js | 1 + .../hooks/http/nr-http.js | 32 +++++++++++++++++-- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/lib/instrumentation-security/core/request-manager.js b/lib/instrumentation-security/core/request-manager.js index a85e8ba2..850f6864 100644 --- a/lib/instrumentation-security/core/request-manager.js +++ b/lib/instrumentation-security/core/request-manager.js @@ -48,13 +48,14 @@ function getRequest(shim) { * @param {*} shim * @param {*} data */ -function updateRequestBody(shim, data) { +function updateRequestBody(shim, data, isTruncated) { const segment = shim.getActiveSegment(); if (segment) { const transactionId = segment.transaction.id; const requestData = getRequestFromId(transactionId); if (requestData) { requestData.body = data; + requestData.dataTruncated = isTruncated; setRequest(transactionId, requestData); } } @@ -65,6 +66,7 @@ function updateRequestBody(shim, data) { const requestData = getRequestFromId(traceId); if (requestData) { requestData.body = data; + requestData.dataTruncated = isTruncated; setRequest(traceId, requestData) } } diff --git a/lib/instrumentation-security/core/sec-utils.js b/lib/instrumentation-security/core/sec-utils.js index 30b8b592..df19c506 100644 --- a/lib/instrumentation-security/core/sec-utils.js +++ b/lib/instrumentation-security/core/sec-utils.js @@ -194,6 +194,7 @@ function addRequestData(shim, request) { }); } data.clientIP = requestIp.getClientIp(request); + data.dataTruncated = false; const transactionId = segment.transaction.id; const storedRequest = requestManager.getRequestFromId(transactionId); if (storedRequest && storedRequest.uri) { diff --git a/lib/instrumentation-security/hooks/http/nr-http.js b/lib/instrumentation-security/hooks/http/nr-http.js index 0864fd83..64142fc1 100755 --- a/lib/instrumentation-security/hooks/http/nr-http.js +++ b/lib/instrumentation-security/hooks/http/nr-http.js @@ -40,6 +40,7 @@ let CSEC_HOME = NRAgent && NRAgent.config.newrelic_home ? NRAgent.config.newreli const CSEC_HOME_TMP = `${CSEC_HOME}/nr-security-home/tmp/language-agent/${process.env.applicationUUID}` let lastTransactionId = EMPTY_STRING; let uncaughtExceptionReportFlag = false; +const requestBodyLimit = 500; /** @@ -244,6 +245,7 @@ function addRequestData(shim, request) { }); } data.clientIP = requestIp.getClientIp(request); + data.dataTruncated = false; const transactionId = segment.transaction.id; const storedRequest = requestManager.getRequestFromId(transactionId); lastTransactionId = transactionId; @@ -363,7 +365,21 @@ function onDataHook(shim, mod) { const requestData = requestManager.getRequestFromId(transactionId); if (requestData) { data = requestData.body ? requestData.body.concat(chunk.toString()) : chunk.toString(); - requestManager.updateRequestBody(shim, data); + requestManager.updateRequestBody(shim, data, false); + try { + const contentLength = Buffer.byteLength(data, 'utf8'); + let bodyLimit = requestBodyLimit; + if (!isNaN(bodyLimit)) { + bodyLimit = bodyLimit * 1000; + if (contentLength && contentLength > bodyLimit) { + data = truncateStringToBytes(data, bodyLimit); + requestManager.updateRequestBody(shim, data, true); + } + } + + } catch (error) { + logger.error("Error while truncating request body", error); + } } } @@ -594,7 +610,7 @@ function deleteTempFileForIAST(file) { */ process.on('uncaughtException', (err, origin) => { console.error(err); - if(uncaughtExceptionReportFlag){ + if (uncaughtExceptionReportFlag) { process.exit(1); } const request = requestManager.getRequestFromId(lastTransactionId); @@ -606,3 +622,15 @@ process.on('uncaughtException', (err, origin) => { uncaughtExceptionReportFlag = true; }); +function truncateStringToBytes(inputString, maxBytes) { + if (!inputString || maxBytes <= 0) { + return EMPTY_STRING; // Return an empty string if input is invalid + } + const buffer = Buffer.from(inputString, UTF8); + if (buffer.length <= maxBytes) { + return inputString; + } + const truncatedBuffer = buffer.slice(0, maxBytes); + const truncatedString = truncatedBuffer.toString(UTF8); + return truncatedString; +} From 4d21108e25d0014c7bd5b0cf83e3bcfa921359f4 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 19 Sep 2024 11:23:56 +0530 Subject: [PATCH 05/50] fix: Added identifiers in events (#235) --- lib/nr-security-agent/lib/core/agent.js | 3 ++- lib/nr-security-agent/lib/core/applicationinfo.js | 4 ++-- lib/nr-security-agent/lib/core/event.js | 4 ++-- lib/nr-security-agent/lib/core/health-check.js | 3 ++- package.json | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/nr-security-agent/lib/core/agent.js b/lib/nr-security-agent/lib/core/agent.js index 9e2f7d14..f644483b 100644 --- a/lib/nr-security-agent/lib/core/agent.js +++ b/lib/nr-security-agent/lib/core/agent.js @@ -130,7 +130,8 @@ Agent.setNRAgent = function setNRAgent(agent) { } const CSECAgent = Agent.getAgent(); if (CSECAgent) { - CSECAgent.applicationInfo.entityGuid = NRAgent.config.entity_guid; + CSECAgent.applicationInfo.appEntityGuid = NRAgent.config.entity_guid; + CSECAgent.applicationInfo.appAccountId = NRAgent.config.account_id; CSECAgent.applicationInfo.linkingMetadata = LinkingMetaData.getLinkingMetadata(); CSECAgent.applicationInfo.linkingMetadata.agentRunId = NRAgent.config.run_id; CSECAgent.setApplicationInfo(CSECAgent.applicationInfo); diff --git a/lib/nr-security-agent/lib/core/applicationinfo.js b/lib/nr-security-agent/lib/core/applicationinfo.js index 8295ab0c..117abd51 100644 --- a/lib/nr-security-agent/lib/core/applicationinfo.js +++ b/lib/nr-security-agent/lib/core/applicationinfo.js @@ -90,10 +90,10 @@ function ApplicationInfo () { const k8sHost = isK8S(); const ECSEnv = isECSEnv(); const isLambda = IS_LAMBDA_ENV; - this.jsonName = APPLICATION_INFO_KEYWORD; if (NRAgent && NRAgent.config) { - this.entityGuid = NRAgent.config.entity_guid; + this.appEntityGuid = NRAgent.config.entity_guid; + this.appAccountId = NRAgent.config.account_id; } this.eventType = 'sec_appinfo'; this.startTime = Date.now(); diff --git a/lib/nr-security-agent/lib/core/event.js b/lib/nr-security-agent/lib/core/event.js index 6770b179..18f6b975 100644 --- a/lib/nr-security-agent/lib/core/event.js +++ b/lib/nr-security-agent/lib/core/event.js @@ -34,8 +34,8 @@ function BasicInfo() { this.policyVersion = (!lodash.isEmpty(policyManager.getInstance().data)) ? policyManager.getInstance().data.version : 'DEFAULT'; if (NRAgent && NRAgent.config) { - this.accountId = NRAgent.config.account_id; - this.entityGuid = NRAgent.config.entity_guid; + this.appAccountId = NRAgent.config.account_id; + this.appEntityGuid = NRAgent.config.entity_guid; this.linkingMetadata = LinkingMetaData.getLinkingMetadata(); this.linkingMetadata.agentRunId = NRAgent.config.run_id; } diff --git a/lib/nr-security-agent/lib/core/health-check.js b/lib/nr-security-agent/lib/core/health-check.js index d2f4ea57..ef9a9d8c 100644 --- a/lib/nr-security-agent/lib/core/health-check.js +++ b/lib/nr-security-agent/lib/core/health-check.js @@ -46,7 +46,8 @@ function HC(info) { this.applicationUUID = info.applicationUUID; this.eventType = 'sec_health_check_lc'; if (NRAgent && NRAgent.config) { - this.entityGuid = NRAgent.config.entity_guid; + this.appEntityGuid = NRAgent.config.entity_guid; + this.appAccountId = NRAgent.config.account_id; } this.protectedServer = NODE_SERVER; this.eventDropCount = 0; diff --git a/package.json b/package.json index c4eae34e..5870e337 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "1.5.0", "description": "New Relic Security Agent for Node.js", "main": "index.js", - "jsonVersion": "1.2.3", + "jsonVersion": "1.2.4", "contributors": [ { "name": "Sumit Suthar", From 89af191de3f26876e4d91d7cc925f981a4cd69ee Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 19 Sep 2024 11:25:54 +0530 Subject: [PATCH 06/50] fix: Handling for empty data in IAST fuzzing header (#237) --- lib/instrumentation-security/hooks/http/nr-http.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/instrumentation-security/hooks/http/nr-http.js b/lib/instrumentation-security/hooks/http/nr-http.js index 64142fc1..8eca6d15 100755 --- a/lib/instrumentation-security/hooks/http/nr-http.js +++ b/lib/instrumentation-security/hooks/http/nr-http.js @@ -173,8 +173,11 @@ function parseFuzzheaders(requestData, transactionId) { const additionalData = fuzzheaders[NR_CSEC_FUZZ_REQUEST_ID].split(CSEC_SEP); logger.debug('AdditionalData:', additionalData); if (additionalData.length >= 8) { - let encryptedData = additionalData[6]; - let hashVerifier = additionalData[7]; + let encryptedData = additionalData[6].trim(); + let hashVerifier = additionalData[7].trim(); + if(lodash.isEmpty(encryptedData)|| lodash.isEmpty(hashVerifier)){ + return; + } let decryptedData = secUtils.decryptData(encryptedData); let verifiedHash = secUtils.hashVerifier(decryptedData, hashVerifier); logger.debug("verifiedHash:", verifiedHash); From bf1e3b8b4f2bdd012aa62a4efb18ea55990878d0 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 19 Sep 2024 12:02:40 +0530 Subject: [PATCH 07/50] feat: Support for secure cookie security event generation (#220) --- .../core/constants.js | 9 +- .../core/event-constants.js | 8 +- .../hooks/http/nr-http.js | 91 ++++++++++++++++++- lib/nr-security-agent/lib/core/sec-util.js | 20 ++++ package.json | 2 +- 5 files changed, 123 insertions(+), 7 deletions(-) diff --git a/lib/instrumentation-security/core/constants.js b/lib/instrumentation-security/core/constants.js index 7b3c1ed0..b9a65d22 100644 --- a/lib/instrumentation-security/core/constants.js +++ b/lib/instrumentation-security/core/constants.js @@ -62,6 +62,13 @@ module.exports = { UNDEFINED: 'undefined', SELF_FD_PATH: '/proc/self/fd/', NR_CSEC_FUZZ_REQUEST_ID: 'nr-csec-fuzz-request-id', - ASTERISK: "*" + ASTERISK: "*", + COMMA_SPACE: ", ", + SEMI_COLON: ';', + EQUAL: '=', + SECURE: 'secure', + HTTPONLY: 'httponly', + SAMESITE: 'samesite', + STRICT: 'strict' }; diff --git a/lib/instrumentation-security/core/event-constants.js b/lib/instrumentation-security/core/event-constants.js index 30dd0323..4c867058 100644 --- a/lib/instrumentation-security/core/event-constants.js +++ b/lib/instrumentation-security/core/event-constants.js @@ -20,9 +20,10 @@ const EVENT_TYPE = { UNVALIDATED_REDIRECT: 'UNVALIDATED_REDIRECT', REFLECTED_XSS: 'REFLECTED_XSS', XPATH: 'XPATH', - LDAP: 'LDAP' + LDAP: 'LDAP', + SECURE_COOKIE: 'SECURE_COOKIE' } -const EVENT_CATEGORY = { +const EVENT_CATEGORY = { MYSQL: 'MYSQL', POSTGRES: 'POSTGRES', ORACLE: 'ORACLE', @@ -40,7 +41,8 @@ const EVENT_CATEGORY = { UNVALIDATED_REDIRECT: 'UNVALIDATED_REDIRECT', REFLECTED_XSS: 'REFLECTED_XSS', XPATH: 'XPATH', - LDAP: 'LDAP' + LDAP: 'LDAP', + SECURE_COOKIE: 'SECURE_COOKIE' } module.exports = { diff --git a/lib/instrumentation-security/hooks/http/nr-http.js b/lib/instrumentation-security/hooks/http/nr-http.js index 8eca6d15..e3f947ce 100755 --- a/lib/instrumentation-security/hooks/http/nr-http.js +++ b/lib/instrumentation-security/hooks/http/nr-http.js @@ -5,7 +5,7 @@ module.exports = initialize const requestManager = require('../../core/request-manager'); -const { NR_CSEC_FUZZ_REQUEST_ID, QUESTION_MARK, EMPTY_STRING, UTF8, CONTENT_TYPE, TEXT_HTML, APPLICATION_JSON, APPLICATION_XML, APPLICATION_XHTML, TEXT_PLAIN, APPLICATION_X_FORM_URLENCODED, MULTIPART_FORM_DATA, COMMA } = require('../../core/constants'); +const { NR_CSEC_FUZZ_REQUEST_ID, QUESTION_MARK, EMPTY_STRING, UTF8, CONTENT_TYPE, TEXT_HTML, APPLICATION_JSON, APPLICATION_XML, APPLICATION_XHTML, TEXT_PLAIN, APPLICATION_X_FORM_URLENCODED, MULTIPART_FORM_DATA, COMMA, SEMI_COLON, EQUAL, SECURE, HTTPONLY, SAMESITE, STRICT } = require('../../core/constants'); const ARRAY_TYPE = 'Array'; const STRING_TYPE = 'string'; const BUFFER_TYPE = 'Buffer'; @@ -175,7 +175,8 @@ function parseFuzzheaders(requestData, transactionId) { if (additionalData.length >= 8) { let encryptedData = additionalData[6].trim(); let hashVerifier = additionalData[7].trim(); - if(lodash.isEmpty(encryptedData)|| lodash.isEmpty(hashVerifier)){ + + if (lodash.isEmpty(encryptedData) || lodash.isEmpty(hashVerifier)) { return; } let decryptedData = secUtils.decryptData(encryptedData); @@ -437,6 +438,11 @@ function responseHook(resp, req, shim) { } catch (error) { logger.debug("Error while reporting error", error); } + try { + secureCookieCheck(response, shim); + } catch (error) { + logger.debug("Error while generating secure cookie event"); + } responseBodyCompute(response, arguments); @@ -625,6 +631,86 @@ process.on('uncaughtException', (err, origin) => { uncaughtExceptionReportFlag = true; }); +/** + * utility to parse response headers for cookie check + * @param {*} headersString + * @returns + */ +function responseRawHeaderParsing(headersString) { + let setCookieValue; + try { + const headersArray = headersString.split('\r\n'); + for (const header of headersArray) { + if (header.toLowerCase().startsWith('set-cookie:')) { + setCookieValue = header.trim().replace('set-cookie:', ''); + break; + } + } + } catch (error) { + + } + return setCookieValue; +} + +/** + * Utility to check insecure cookie settings + * @param {*} response + * @param {*} shim + */ +function secureCookieCheck(response, shim) { + let cookieHeader = response.getHeader('set-cookie') ? response.getHeader('set-cookie') : responseRawHeaderParsing(response._header); + let cookieHeaderList = []; + if (!cookieHeader) { + return; + } + if (typeof cookieHeader === 'string') { + cookieHeaderList.push(cookieHeader) + } + else { + cookieHeaderList = cookieHeaderList.concat(cookieHeader); + } + let csec_request = requestManager.getRequest(shim); + try { + let parameters = []; + for (const cookieString of cookieHeaderList) { + if (cookieString) { + const keyValuePairs = cookieString.split(SEMI_COLON); + let params = { + "isHttpOnly": false, + "isSecure": false, + "isSameSiteStrict": false, + }; + for (let i = 0; i < keyValuePairs.length; i++) { + const pair = keyValuePairs[i]; + const [key, value] = pair.trim().split(EQUAL); + if (i == 0) { + params.name = key; + params.value = value; + } + + if (key.toLowerCase() === SECURE) { + params.isSecure = true; + } + else if (key.toLowerCase() === HTTPONLY) { + params.isHttpOnly = true; + } + else if (key.toLowerCase() === SAMESITE && value.toLowerCase() === STRICT) { + params.isSameSiteStrict = true; + } + } + parameters.push(params); + } + } + const traceObject = secUtils.getTraceObject(shim); + const secMetadata = securityMetaData.getSecurityMetaData(csec_request, parameters, traceObject, secUtils.getExecutionId(), EVENT_TYPE.SECURE_COOKIE, EVENT_CATEGORY.SECURE_COOKIE) + const secEvent = API.generateSecEvent(secMetadata); + API.sendEvent(secEvent); + } catch (error) { + logger.debug("Error while generating secure cookie event:", error); + } + +} + function truncateStringToBytes(inputString, maxBytes) { if (!inputString || maxBytes <= 0) { return EMPTY_STRING; // Return an empty string if input is invalid @@ -637,3 +723,4 @@ function truncateStringToBytes(inputString, maxBytes) { const truncatedString = truncatedBuffer.toString(UTF8); return truncatedString; } + diff --git a/lib/nr-security-agent/lib/core/sec-util.js b/lib/nr-security-agent/lib/core/sec-util.js index 20d7c7bc..6d9a0fae 100644 --- a/lib/nr-security-agent/lib/core/sec-util.js +++ b/lib/nr-security-agent/lib/core/sec-util.js @@ -27,6 +27,20 @@ let logger = logs.getLogger(); const initLogger = logs.getInitLogger(); const NODE_SER = 'node-serialize/lib/serialize.js'; +const SECURE_COOKIE = 'SECURE_COOKIE'; + +const insecureSettingApiIdSet = new Set(); + +/** + * Utility to remove insecureSettingAPIIds after 30 mins from the set. + * @param {*} entry + */ +function addInsecureSettingApiId(entry) { + insecureSettingApiIdSet.add(entry); + setTimeout(() => { + insecureSettingApiIdSet.delete(entry); + }, 30 * 60 * 1000); +} function getSecEventEmitter() { if (eventEmitter) { @@ -84,6 +98,12 @@ function generateSecEvent(securityMetadata) { let apiId = shaUtil.getSHA256ForData(traceObject.stacktrace.join('|') + uri); apiId = securityMetadata.eventType + HYPHEN + apiId; + if (securityMetadata.eventType == SECURE_COOKIE) { + if (insecureSettingApiIdSet.has(apiId)) { + return; + } + addInsecureSettingApiId(apiId); + } const agentModule = Agent.getAgent(); const metaData = {}; if (traceObject.sourceDetails && traceObject.sourceDetails.evalObj) { diff --git a/package.json b/package.json index 5870e337..88c0d6d8 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "1.5.0", "description": "New Relic Security Agent for Node.js", "main": "index.js", - "jsonVersion": "1.2.4", + "jsonVersion": "1.2.5", "contributors": [ { "name": "Sumit Suthar", From f892201ad01d2df05a76f5ead0285697b54709bc Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 19 Sep 2024 12:06:12 +0530 Subject: [PATCH 08/50] feat!: Dropped functionality to generate snapshot file (#241) Co-authored-by: pratik-k2 --- lib/nr-security-agent/lib/core/Policy.js | 12 -- lib/nr-security-agent/lib/core/commonUtils.js | 43 +---- .../response/fuzz-request-handler.js | 2 - .../core/connections/websocket/websocket.js | 10 +- .../lib/core/sec-agent-constants.js | 5 +- lib/nr-security-agent/lib/core/sec-util.js | 4 +- lib/nr-security-agent/lib/core/statusUtils.js | 165 ------------------ .../lib/core/websocket-client.js | 4 - 8 files changed, 5 insertions(+), 240 deletions(-) delete mode 100644 lib/nr-security-agent/lib/core/statusUtils.js diff --git a/lib/nr-security-agent/lib/core/Policy.js b/lib/nr-security-agent/lib/core/Policy.js index a45cf543..615de3bd 100644 --- a/lib/nr-security-agent/lib/core/Policy.js +++ b/lib/nr-security-agent/lib/core/Policy.js @@ -17,7 +17,6 @@ const logger = logs.getLogger(); const initLogger = logs.getInitLogger(); const jsonValidator = require('./jsonValidator'); const LOG_MESSAGES = require('./sec-agent-constants').LOG_MESSAGES; -const statusUtils = require('./statusUtils'); function Policy() { this.data = {}; @@ -72,7 +71,6 @@ function setDefaultPolicy() { logger.info(LOG_MESSAGES.DEFAULT_POL_SET, JSON.stringify(policy.data)); } catch (e) { logger.error(LOG_MESSAGES.UNABLE_SET_DEFAULT_POL, e); - statusUtils.addErrortoBuffer(e); }; } @@ -90,16 +88,6 @@ function appInfoVersionUpdate(policy, data) { } } -/** - * Function to send updated policy to validator - * @param {*} data - */ -function sendUpdatedPolicy(data) { - const wsClient = Agent.getAgent().client; - let updatedPolicy = Object.assign({}, data); - updatedPolicy.jsonName = 'lc-policy'; - wsClient.dispatcher(updatedPolicy); -} module.exports = { getInstance, setPolicyData, diff --git a/lib/nr-security-agent/lib/core/commonUtils.js b/lib/nr-security-agent/lib/core/commonUtils.js index 514f72d9..a9616c37 100644 --- a/lib/nr-security-agent/lib/core/commonUtils.js +++ b/lib/nr-security-agent/lib/core/commonUtils.js @@ -133,7 +133,6 @@ function getOS() { function createDirectories() { createPathIfNotExist(`${CSEC_HOME}${SLASH}nr-security-home`); createPathIfNotExist(`${CSEC_HOME}${SLASH}nr-security-home${SLASH}logs`); - createPathIfNotExist(`${CSEC_HOME}${SLASH}nr-security-home${SLASH}logs${SLASH}snapshots`); createPathIfNotExist(`${CSEC_HOME}${SLASH}nr-security-home${SLASH}tmp`); createPathIfNotExist(`${CSEC_HOME}${SLASH}nr-security-home${SLASH}tmp${SLASH}language-agent`); createPathIfNotExist(`${CSEC_HOME}${SLASH}nr-security-home${SLASH}tmp${SLASH}language-agent${SLASH}${getUUID()}`); @@ -159,14 +158,11 @@ async function initialSetup() { */ function isLogAccessible(logFileName) { return new Promise((resolve) => { - if (logFileName === njsAgentConstants.STATUS_LOG_FILE && require('./statusUtils').getBufferedHC().length === 0) { - resolve('OK'); - } fs.access(logFileName, fs.constants.F_OK | fs.constants.W_OK, (err) => { if (err) { resolve('Error'); } - else if ((!logs.isLoggerOk || logger.level.levelStr == 'OFF') && logFileName != njsAgentConstants.STATUS_LOG_FILE) { + else if ((!logs.isLoggerOk || logger.level.levelStr == 'OFF')) { resolve('Error'); } else { @@ -256,42 +252,6 @@ function isAgentActiveState() { function iastRestClientStatus() { return 'OK'; } -/** - * Utiltity to remove older snapshots - */ -function removeOlderSnapshots() { - try { - const basePath = njsAgentConstants.LOG_DIR + 'snapshots' + SLASH; - const directoryContent = fs.readdirSync(basePath); - const files = directoryContent.filter((filename) => { - return fs.statSync(`${basePath}${SLASH}${filename}`).isFile(); - }); - const sorted = files.sort((a, b) => { - const firstStat = fs.statSync(`${basePath}${SLASH}${a}`); - const secondStat = fs.statSync(`${basePath}${SLASH}${b}`); - return new Date(secondStat.mtime).getTime() - new Date(firstStat.mtime).getTime(); - }); - for (let i = 99; i < sorted.length; i++) { - const fileToDelete = basePath + sorted[i]; - try { - fs.unlink(fileToDelete, (err) => { - if (err) { - logger.error(err); - } else { - logger.debug('Snapshot deleted:', fileToDelete); - } - }); - } catch (error) { - logger.error(error); - } - } - } catch (error) { - logger.debug(error); - const LogMessage = require('./LogMessage'); - const logMessage = new LogMessage.logMessage("DEBUG", 'Error in processing snapshot files', __filename, error); - addLogEventtoBuffer(logMessage); - } -} /** * Utilty to remove older log files. */ @@ -475,7 +435,6 @@ module.exports = { getHCStats, isAgentActiveState, iastRestClientStatus, - removeOlderSnapshots, logRollOver, getValidatorServiceEndpointURL, getCSECmode, diff --git a/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js b/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js index 74ad4cb3..f4325c4b 100644 --- a/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js +++ b/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js @@ -21,7 +21,6 @@ const LogMessage = require('../../../LogMessage'); require('dns').setDefaultResultOrder('ipv4first') const PolicyManager = require('../../../Policy'); -const statusUtils = require('../../../statusUtils'); const find = `${SLASH}{{NR_CSEC_VALIDATOR_HOME_TMP}}`; const CSEC_HOME_TMP_CONST = new RegExp(find, 'g'); @@ -158,7 +157,6 @@ function handleFuzzRequest(fuzzDetails) { handleFuzzResponse(response, fuzzDetails); } } catch (err) { - statusUtils.addErrortoBuffer(err); const fuzzFailEvent = new FuzzFailEvent(fuzzRequest.headers[NR_CSEC_FUZZ_REQUEST_ID]); logger.error(stringify(fuzzFailEvent)); try { diff --git a/lib/nr-security-agent/lib/core/connections/websocket/websocket.js b/lib/nr-security-agent/lib/core/connections/websocket/websocket.js index 15ffb2dd..128899f5 100644 --- a/lib/nr-security-agent/lib/core/connections/websocket/websocket.js +++ b/lib/nr-security-agent/lib/core/connections/websocket/websocket.js @@ -17,8 +17,7 @@ const hc = require('../../health-check'); const fs = require('fs'); const { promisify } = require('../../sec-util'); const ResponseHandler = require('./response'); -const { EMPTY_APPLICATION_UUID, LOG_MESSAGES, CSEC_SEP, NR_CSEC_FUZZ_REQUEST_ID, EXITEVENT, JSON_NAME, RASP, SEVERE } = require('../../sec-agent-constants'); -const statusUtils = require('../../statusUtils'); +const { EMPTY_APPLICATION_UUID, LOG_MESSAGES, CSEC_SEP, NR_CSEC_FUZZ_REQUEST_ID, EXITEVENT, JSON_NAME, SEVERE } = require('../../sec-agent-constants'); const commonUtils = require('../../commonUtils'); const IASTUtil = require('../websocket/response/IASTUtils'); const LogMessage = require('../../LogMessage'); @@ -211,13 +210,11 @@ SecWebSocket.prototype.pingWS = async function pingWS() { if (err) { logger.debug("Error while pinging:", err); commonUtils.setWSHealthStatus('Error'); - statusUtils.addErrortoBuffer(err); } }); } catch (err) { logger.debug("error in ping:", err); - statusUtils.addErrortoBuffer(err); commonUtils.setWSHealthStatus('Error'); return; } @@ -273,7 +270,6 @@ SecWebSocket.prototype.dispatch = async function dispatch(event) { }) } catch (error) { logger.debug(LOG_MESSAGES.ERROR_WHILE_SEND_EVENT, eventStr, error); - statusUtils.addErrortoBuffer(error); handleDispatchFailure(this, event, eventStr); } }; @@ -293,7 +289,6 @@ SecWebSocket.prototype.dispatchApplicationInfo = async function dispatchApplicat try { await promisify(this.instance, this.instance.send)(eventStr, { mask: true }); } catch (error) { - statusUtils.addErrortoBuffer(error); logger.warn('Error while sending applicationInfo:', error); this.obeyReconnect(); } @@ -332,7 +327,6 @@ SecWebSocket.prototype.flushEventQueue = async function flushEventQueue() { const results = await Promise.all(sentEvents); hc.getInstance().registerEventsSent(results.length); } catch (err) { - statusUtils.addErrortoBuffer(err); logger.debug('Flush failed, reception of all events on IC couldn\'t be ensured.'); } }; @@ -405,7 +399,6 @@ const defaultOnOpenCB = () => async function onOpen() { initLogger.info(LOG_MESSAGES.SENDING_APPINFO_COMPLETE, JSON.stringify(applicationInfo)); } catch (err) { logger.error(`Connection broken: ${err.message}`); - statusUtils.addErrortoBuffer(err); commonUtils.setWSHealthStatus('Error') setWebSocketConn(); self.setValidatorNotReadyForEvents(); @@ -438,7 +431,6 @@ const defaultOnMsgCB = () => function onMessage(data) { */ const defaultOnErrCB = () => function onClose(error) { commonUtils.setWSHealthStatus('Error'); - statusUtils.addErrortoBuffer(error); const self = this; logger.error("Error while connecting to validator:", error.message) const logMessage = new LogMessage.logMessage(SEVERE, 'Error while connecting to validator', __filename, error); diff --git a/lib/nr-security-agent/lib/core/sec-agent-constants.js b/lib/nr-security-agent/lib/core/sec-agent-constants.js index 3ce1ba70..af270068 100644 --- a/lib/nr-security-agent/lib/core/sec-agent-constants.js +++ b/lib/nr-security-agent/lib/core/sec-agent-constants.js @@ -24,15 +24,14 @@ module.exports = { CSEC_HOME_TMP: `${CSEC_HOME}${sep}nr-security-home${sep}tmp${sep}language-agent${sep}${process.env.applicationUUID}`, AGENT_START_TIME: agentStartTime, FRAMEWORK: '', - STATUS_LOG_FILE: `${CSEC_HOME}${sep}nr-security-home${sep}logs${sep}snapshots${sep}node-security-collector-status-${process.env.applicationUUID}.log`, - + DB_LIST: { MYSQL: 'MYSQL', MYSQL2: 'MYSQL', POSTGRES: 'POSTGRES', MONGODB: 'MONGODB', ORACLEDB: 'ORACLEDB', - MSSQL: 'MSSQL', + MSSQL: 'MSSQL', SQLITE3: 'SQLITE3' }, SERVER_COMMAND: { diff --git a/lib/nr-security-agent/lib/core/sec-util.js b/lib/nr-security-agent/lib/core/sec-util.js index 6d9a0fae..61e391f3 100644 --- a/lib/nr-security-agent/lib/core/sec-util.js +++ b/lib/nr-security-agent/lib/core/sec-util.js @@ -9,14 +9,13 @@ const { SecEvent } = require('./event'); const logs = require('./logging'); const { Agent } = require('./agent'); const shaUtil = require('./sha-size-util'); -const { LOG_MESSAGES, NR_CSEC_FUZZ_REQUEST_ID, COLON, VULNERABLE, EXITEVENT, EMPTY_STR, RASP, SEVERE, HYPHEN } = require('./sec-agent-constants'); +const { NR_CSEC_FUZZ_REQUEST_ID, COLON, VULNERABLE, EXITEVENT, EMPTY_STR, SEVERE, HYPHEN } = require('./sec-agent-constants'); const API = require('../../../nr-security-api'); const NRAgent = API.getNRAgent(); const HC = require('./health-check'); const LogMessage = require('./LogMessage'); const commonUtils = require('./commonUtils'); -const statusUtils = require('./statusUtils'); let firstEventSent = false; @@ -124,7 +123,6 @@ function generateSecEvent(securityMetadata) { event.httpRequest.route = uri; return event; } catch (e) { - statusUtils.addErrortoBuffer(e); logger.error("Error in generating event:", e); const logMessage = new LogMessage.logMessage(SEVERE, 'Error while generating event', __filename, e); diff --git a/lib/nr-security-agent/lib/core/statusUtils.js b/lib/nr-security-agent/lib/core/statusUtils.js deleted file mode 100644 index 5edf5091..00000000 --- a/lib/nr-security-agent/lib/core/statusUtils.js +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2023 New Relic Corporation. All rights reserved. - * SPDX-License-Identifier: New Relic Software License v1.0 - */ - -/* eslint-disable new-cap */ - -const njsAgentConstants = require('./sec-agent-constants'); -const agentConfig = require('../../resources/config'); -const { AGENT_DIR } = agentConfig; -const lodash = require('lodash'); - -let errors = []; - -const ringBuffer = require('ringbufferjs'); -const bufferedHC = new ringBuffer(5); -const bufferedErrors = new ringBuffer(5); -const fs = require('fs'); -const util = require('util'); -let HC = []; -let lastHC = {}; -const logs = require('./logging'); -const commonUtils = require('./commonUtils'); -const logger = logs.getLogger(); -const statusFile = njsAgentConstants.STATUS_LOG_FILE; -const sep = require('path').sep; - -const statusTemplate = 'Snapshot timestamp: : %s\n' + - `CSEC Agent start timestamp: ${njsAgentConstants.AGENT_START_TIME} with application uuid:${commonUtils.getUUID()}\n` + - `CSEC_HOME: ${njsAgentConstants.CSEC_HOME}${sep}nr-security-home${sep}\n` + - `Agent location: ${AGENT_DIR}\n` + - `Using CSEC Agent for Node.js, Node version:${process.version}, PID:${process.pid}\n` + - `Process title: ${process.title}\n` + - `Process binary: ${process.execPath}\n` + - 'Application location: %s\n' + - `Current working directory: ${process.cwd()}\n` + - `Agent mode: ${commonUtils.getCSECmode()}\n` + - 'Application server: %s\n' + - `Application Framework: %s\n` + - `Websocket connection to Prevent Web: ${commonUtils.getValidatorServiceEndpointURL()}, Status: %s\n` + - 'Instrumentation successful\n' + - 'Tracking loaded modules in the application\n' + - 'Policy applied successfully. Policy version is: %s\n' + - 'Started Health Check for Agent\n' + - 'Started Inbound and Outbound monitoring \n' + - '\nProcess stats:\n%s\n' + - '\nService stats:\n%s\n' + - '\nLast 5 errors: \n%s\n' + - '\nLast 5 Health Checks are:\n %s \n'; - -/** - * Utility to add hc in hc buffer - * @param {*} healthCheck - */ -function addHCtoBuffer(healthCheck) { - try { - bufferedHC.enq(healthCheck); - lastHC = healthCheck; - } catch (error) { - logger.debug(error); - } -} - -/** - * Utility to add error object in error buffer - * @param {*} error - */ -function addErrortoBuffer(error) { - try { - let errorObj = { - 'error': error.stack - } - bufferedErrors.enq(errorObj); - } catch (error) { - logger.debug(error); - } -} - -/** - * utility to format status template with dynamic values - */ -function getFormattedData() { - const Agent = require('./agent').Agent.getAgent(); - const appInfo = Agent.applicationInfo; - const deployedApplications = appInfo && appInfo.serverInfo && appInfo.serverInfo.deployedApplications; - const appLoc = deployedApplications[0].deployedPath; - const formattedSnapshot = util.format(statusTemplate, new Date().toString(), appLoc, appInfo.serverInfo.name, commonUtils.getFramework(), commonUtils.getWSHealthStatus(), appInfo.policyVersion, getKeyValPairs(lastHC.stats), getKeyValPairs(lastHC.serviceStatus), JSON.stringify(getBufferedErrors()), JSON.stringify(getBufferedHC())); - return formattedSnapshot; -} - -/** - * utility to write snapshot in snapshot file - */ -function writeSnapshot() { - const snapshot = getFormattedData(); - commonUtils.removeOlderSnapshots(); - fs.writeFile(statusFile, snapshot, { mode: 0o660 }, function (err) { - if (err) { - logger.debug(err.message); - const LogMessage = require('./LogMessage'); - const logMessage = new LogMessage.logMessage("DEBUG", 'Error in creating snapshot file', __filename, err); - commonUtils.addLogEventtoBuffer(logMessage); - } else { - logger.info('Snapshot updated to file: %s', statusFile); - fs.chmod(statusFile, 0o660, (err) => { - if (err) { - addErrortoBuffer(err); - } - }); - } - }); -} -/** - * return buffered error instance. - */ -function getRingBufferedErrors() { - return bufferedErrors; -} - -/** - * return buffered HC list without null, undefined - */ -function getBufferedHC() { - try { - HC = lodash.compact(bufferedHC._elements); - } catch (error) { - logger.debug(error); - } - - return HC; -} -/** - * returns buffered error list without null, undefined - */ -function getBufferedErrors() { - try { - errors = lodash.compact(bufferedErrors._elements); - } catch (error) { - logger.debug(error); - } - return errors; -} - -/** - * Utility to get key val pairs from json object - * @param {*} jsonObject - */ -function getKeyValPairs(jsonObject) { - let statStr = njsAgentConstants.EMPTY_STR; - for (const key in jsonObject) { - statStr = statStr + key + ': ' + jsonObject[key] + '\n'; - } - return statStr; -} - -module.exports = { - statusTemplate, - addHCtoBuffer, - getFormattedData, - writeSnapshot, - addErrortoBuffer, - getRingBufferedErrors, - getBufferedHC, - getBufferedErrors -}; diff --git a/lib/nr-security-agent/lib/core/websocket-client.js b/lib/nr-security-agent/lib/core/websocket-client.js index ad451baa..1fba63ad 100644 --- a/lib/nr-security-agent/lib/core/websocket-client.js +++ b/lib/nr-security-agent/lib/core/websocket-client.js @@ -25,7 +25,6 @@ const { } = require('./connections/websocket'); const { HC_INTERVAL_MS } = require('../../resources/config'); const { LOG_DIR, EXITEVENT, JSON_NAME } = require('./sec-agent-constants'); -const statusUtils = require('./statusUtils'); const njsAgentConstants = require('./sec-agent-constants'); let wsInstance; @@ -131,7 +130,6 @@ const sendHC = async function () { json.serviceStatus.websocket = commonUtils.getWSHealthStatus(); json.serviceStatus.logWriter = await commonUtils.isLogAccessible(`${LOG_DIR}node-security-collector.log`); json.serviceStatus.initLogWriter = await commonUtils.isLogAccessible(`${LOG_DIR}node-security-collector-init.log`); - json.serviceStatus.statusLogWriter = await commonUtils.isLogAccessible(njsAgentConstants.STATUS_LOG_FILE); json.serviceStatus.agentActiveStat = commonUtils.isAgentActiveState(); json.serviceStatus.iastRestClient = commonUtils.iastRestClientStatus(); @@ -148,8 +146,6 @@ const sendHC = async function () { hc.getInstance().resetEventStats(); logger.info('Health Check Status:', JSON.stringify(json)); - statusUtils.addHCtoBuffer(json); - statusUtils.writeSnapshot(); getDispatcherAndSendEvent(json); } }; From 423dfee65c69798f31c28d880658eb2f872aed56 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 19 Sep 2024 12:09:06 +0530 Subject: [PATCH 09/50] feat!: Dropped support for Node.js v16 (#240) --- .github/workflows/ci-workflow.yml | 2 +- package.json | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index a6a0ba81..70dc66a9 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -21,7 +21,7 @@ jobs: strategy: matrix: - node-version: [16.x, 18.x, 20.x, 22.x] + node-version: [18.x, 20.x, 22.x] steps: - uses: actions/checkout@v3 diff --git a/package.json b/package.json index 88c0d6d8..5c7dc4a7 100644 --- a/package.json +++ b/package.json @@ -8,12 +8,12 @@ { "name": "Sumit Suthar", "email": "ssuthar@newrelic.com", - "web": "http://newrelic.com" + "web": "https://newrelic.com" }, { "name": "Pratik Gunjetiya", "email": "pgunjetiya@newrelic.com", - "web": "http://newrelic.com" + "web": "https://newrelic.com" } ], "scripts": { @@ -28,6 +28,10 @@ "New Relic Security Agent", "Node.js Application Security" ], + "engines": { + "node": ">=18", + "npm": ">=6.0.0" + }, "author": "newrelic", "license": "New Relic Software License v1.0", "repository": { From d39b2c6bca052c4b0535c1236207a370d2bbbb5a Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 19 Sep 2024 12:38:07 +0530 Subject: [PATCH 10/50] feat: Support to detect application and server path (#224) --- lib/nr-security-agent/lib/core/sec-util.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/nr-security-agent/lib/core/sec-util.js b/lib/nr-security-agent/lib/core/sec-util.js index 61e391f3..bde653bc 100644 --- a/lib/nr-security-agent/lib/core/sec-util.js +++ b/lib/nr-security-agent/lib/core/sec-util.js @@ -16,8 +16,10 @@ const HC = require('./health-check'); const LogMessage = require('./LogMessage'); const commonUtils = require('./commonUtils'); +const appInfo = require('./applicationinfo').getInstance(); let firstEventSent = false; +let appDir = EMPTY_STR; const events = require('events'); const eventEmitter = undefined; @@ -81,6 +83,7 @@ const sleep = (timeout) => new Promise((resolve) => { function generateSecEvent(securityMetadata) { const traceObject = securityMetadata.traceObject; const request = securityMetadata.request; + let appServerInfo = {}; if (request && request.headers[NR_CSEC_FUZZ_REQUEST_ID]) { HC.getInstance().iastEventStats.processed++; @@ -88,6 +91,16 @@ function generateSecEvent(securityMetadata) { else { HC.getInstance().raspEventStats.processed++; } + + try { + appDir = appInfo.serverInfo.deployedApplications[0].deployedPath; + appServerInfo.applicationDirectory = appDir; + appServerInfo.serverBaseDirectory = appDir; + appServerInfo.connectionConfiguration = { [request.serverPort]: request.protocol }; + + } catch (error) { + } + try { let stakTrace = traceObject.stacktrace; let uri = EMPTY_STR; @@ -105,6 +118,7 @@ function generateSecEvent(securityMetadata) { } const agentModule = Agent.getAgent(); const metaData = {}; + metaData.appServerInfo = appServerInfo; if (traceObject.sourceDetails && traceObject.sourceDetails.evalObj) { metaData.triggerViaRCI = true; metaData.rciMethodsCalls = traceObject.sourceDetails.evalObj.invokedCalls; From 5b613dc92ecffa6e6efe4f4a439de40662d6227c Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 19 Sep 2024 13:09:16 +0530 Subject: [PATCH 11/50] feat: Report error to Error Inbox upon connection failure to Security Engine (#248) Co-authored-by: pratik-k2 --- lib/nr-security-agent/lib/core/Auth-headers.js | 1 + lib/nr-security-agent/lib/core/commonUtils.js | 11 ++++++++++- .../lib/core/connections/websocket/websocket.js | 4 ++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/nr-security-agent/lib/core/Auth-headers.js b/lib/nr-security-agent/lib/core/Auth-headers.js index 568628c3..5a820087 100644 --- a/lib/nr-security-agent/lib/core/Auth-headers.js +++ b/lib/nr-security-agent/lib/core/Auth-headers.js @@ -43,6 +43,7 @@ function AuthHeaders() { commonUtils.addLogEventtoBuffer(logMessage); } + return authHeaders; } AuthHeaders.prototype.constructor = AuthHeaders; diff --git a/lib/nr-security-agent/lib/core/commonUtils.js b/lib/nr-security-agent/lib/core/commonUtils.js index a9616c37..1ba1d334 100644 --- a/lib/nr-security-agent/lib/core/commonUtils.js +++ b/lib/nr-security-agent/lib/core/commonUtils.js @@ -419,6 +419,14 @@ function getFramework(){ return framework; } +/** + * Utility to send error to error inbox of APM + * @param {*} error + */ +function sendErrorToErrorInbox(error){ + API.newrelic.noticeError(error); +} + module.exports = { getUUID, @@ -443,5 +451,6 @@ module.exports = { setWSHealthStatus, addLogEventtoBuffer, getLogEvents, - getFramework + getFramework, + sendErrorToErrorInbox }; diff --git a/lib/nr-security-agent/lib/core/connections/websocket/websocket.js b/lib/nr-security-agent/lib/core/connections/websocket/websocket.js index 128899f5..fe34da83 100644 --- a/lib/nr-security-agent/lib/core/connections/websocket/websocket.js +++ b/lib/nr-security-agent/lib/core/connections/websocket/websocket.js @@ -111,6 +111,7 @@ SecWebSocket.prototype.init = function init() { cert = fs.readFileSync(certPath, 'utf8'); } catch (error) { logger.error("Error in reading certificate:", error); + commonUtils.sendErrorToErrorInbox(error) const logMessage = new LogMessage.logMessage(SEVERE, 'Error in reading certificate for websocket', __filename, error); commonUtils.addLogEventtoBuffer(logMessage); @@ -168,6 +169,7 @@ SecWebSocket.prototype.reconnect = function reconnect() { return; } commonUtils.setWSHealthStatus('Error'); + commonUtils.sendErrorToErrorInbox(new Error("Unable to connect to Security Engine")) logger.debug(LOG_MESSAGES.DETECTED_BROKEN_CONN); this.obeyReconnect(); @@ -399,6 +401,7 @@ const defaultOnOpenCB = () => async function onOpen() { initLogger.info(LOG_MESSAGES.SENDING_APPINFO_COMPLETE, JSON.stringify(applicationInfo)); } catch (err) { logger.error(`Connection broken: ${err.message}`); + commonUtils.sendErrorToErrorInbox(err); commonUtils.setWSHealthStatus('Error') setWebSocketConn(); self.setValidatorNotReadyForEvents(); @@ -434,6 +437,7 @@ const defaultOnErrCB = () => function onClose(error) { const self = this; logger.error("Error while connecting to validator:", error.message) const logMessage = new LogMessage.logMessage(SEVERE, 'Error while connecting to validator', __filename, error); + commonUtils.sendErrorToErrorInbox(error); commonUtils.addLogEventtoBuffer(logMessage); logger.warn("Security Agent INACTIVE!!!") if (error && error.code && (error.code === 'ECONNREFUSED' || error.code === 'EPIPE' || error.code === 'ECONNRESET')) { From fb7491fd779c2cba2ba5b766f6bc176b4fa7fc29 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 19 Sep 2024 17:20:20 +0530 Subject: [PATCH 12/50] Fix: fix for missing identifiers in iast-data-request JSON (#252) --- .../core/connections/websocket/response/IASTUtils.js | 10 ++++++---- lib/nr-security-agent/lib/core/websocket-client.js | 4 ++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/nr-security-agent/lib/core/connections/websocket/response/IASTUtils.js b/lib/nr-security-agent/lib/core/connections/websocket/response/IASTUtils.js index f24f80a7..9af7bec2 100644 --- a/lib/nr-security-agent/lib/core/connections/websocket/response/IASTUtils.js +++ b/lib/nr-security-agent/lib/core/connections/websocket/response/IASTUtils.js @@ -31,7 +31,7 @@ function completedRequestsMapInit(id) { function addCompletedRequests(id, eventId) { let data = completedRequestsMap.get(id); - if(!data){ + if (!data) { return; } data.push(eventId); @@ -42,15 +42,15 @@ function getCompletedRequestsMap() { return completedRequestsMap; } -function clearCompletedRequestMap(){ +function clearCompletedRequestMap() { completedRequestsMap.clear(); } -function clearPendingRequestIdSet(){ +function clearPendingRequestIdSet() { pendingRequestIds.clear(); } -function IASTCleanup(){ +function IASTCleanup() { clearCompletedRequestMap(); clearPendingRequestIdSet(); } @@ -69,6 +69,8 @@ function generateIASTDataRequest() { let object = {}; object['jsonName'] = 'iast-data-request'; object['applicationUUID'] = Agent.getAgent().applicationInfo.applicationUUID; + object['appEntityGuid'] = Agent.getAgent().applicationInfo.appEntityGuid; + object['appAccountId'] = Agent.getAgent().applicationInfo.appAccountId; object["batchSize"] = batchSize ? batchSize : 300; object['pendingRequestIds'] = getPendingRequestIds(); object['completedRequests'] = Object.fromEntries(getCompletedRequestsMap()); diff --git a/lib/nr-security-agent/lib/core/websocket-client.js b/lib/nr-security-agent/lib/core/websocket-client.js index 1fba63ad..7fc16da8 100644 --- a/lib/nr-security-agent/lib/core/websocket-client.js +++ b/lib/nr-security-agent/lib/core/websocket-client.js @@ -119,6 +119,10 @@ const sendHC = async function () { json = JSON.parse(json); json.policyVersion = applicationInfo.policyVersion; json.entityGuid = applicationInfo.entityGuid; + if (NRAgent && NRAgent.config) { + json.appEntityGuid = NRAgent.config.entity_guid; + json.appAccountId = NRAgent.config.account_id; + } try { json.stats = await commonUtils.getHCStats(); From a5602db905027547bf64efc4f36188e5e52a2041 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 15:53:56 +0530 Subject: [PATCH 13/50] Release v2.0.0 (#253) Co-authored-by: pratik-k2 Co-authored-by: pratik-k2 Co-authored-by: Sumit Suthar --- CHANGELOG.md | 18 ++++++++++++++++++ THIRD_PARTY_NOTICES.md | 19 ++++++++++++++++++- package-lock.json | 4 ++-- package.json | 2 +- third_party_manifest.json | 24 +++++++++++++++++++----- 5 files changed, 58 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1603b79b..fea7c8ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ +### v2.0.0 (2024-09-20) +### âš  BREAKING CHANGES +* Dropped support for Node.js v16 +* Dropped functionality to generate snapshot file +#### Features +* Support to honour proxy settings via config +* Support for secure cookie security event generation +* Report error to Error Inbox upon connection failure to Security Engine +* Support to detect application and server path +* Functionality to truncate Incoming HTTP request upto default limit +* Dropped support for Node.js v16 +* Dropped functionality to generate snapshot file +#### Bug fixes +* Handling for empty data in IAST fuzzing header +* Added identifiers in events +* Fix for file integrity security event generation +* Fix for missing identifiers in iast-data-request JSON + ### v1.5.0 (2024-08-14) #### Features * Support for Node.js v22.x diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index 3f6b7de9..4fc58c99 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -21,6 +21,7 @@ code, the source code can be found at [https://github.com/newrelic/csec-node-age * [find-package-json](#find-package-json) * [hash.js](#hashjs) * [html-entities](#html-entities) +* [https-proxy-agent](#https-proxy-agent) * [is-invalid-path](#is-invalid-path) * [js-yaml](#js-yaml) * [jsonschema](#jsonschema) @@ -239,6 +240,22 @@ THE SOFTWARE. ``` +### https-proxy-agent + +This product includes source derived from [https-proxy-agent](https://github.com/TooTallNate/node-https-proxy-agent) ([v5.0.1](https://github.com/TooTallNate/node-https-proxy-agent/tree/v5.0.1)), distributed under the [MIT License](https://github.com/TooTallNate/node-https-proxy-agent/blob/v5.0.1/README.md): + +``` +MIT License + +Copyright (c) + +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: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +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. +``` + ### is-invalid-path This product includes source derived from [is-invalid-path](https://github.com/jonschlinkert/is-invalid-path) ([v1.0.2](https://github.com/jonschlinkert/is-invalid-path/tree/v1.0.2)), distributed under the [MIT License](https://github.com/jonschlinkert/is-invalid-path/blob/v1.0.2/LICENSE): @@ -588,7 +605,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI ### ws -This product includes source derived from [ws](https://github.com/websockets/ws) ([v8.17.1](https://github.com/websockets/ws/tree/v8.17.1)), distributed under the [MIT License](https://github.com/websockets/ws/blob/v8.17.1/LICENSE): +This product includes source derived from [ws](https://github.com/websockets/ws) ([v8.18.0](https://github.com/websockets/ws/tree/v8.18.0)), distributed under the [MIT License](https://github.com/websockets/ws/blob/v8.18.0/LICENSE): ``` Copyright (c) 2011 Einar Otto Stangvik diff --git a/package-lock.json b/package-lock.json index 7621f345..82042eba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@newrelic/security-agent", - "version": "1.5.0", + "version": "2.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@newrelic/security-agent", - "version": "1.5.0", + "version": "2.0.0", "license": "New Relic Software License v1.0", "dependencies": { "axios": "^1.7.4", diff --git a/package.json b/package.json index 5c7dc4a7..7fdbbedb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@newrelic/security-agent", - "version": "1.5.0", + "version": "2.0.0", "description": "New Relic Security Agent for Node.js", "main": "index.js", "jsonVersion": "1.2.5", diff --git a/third_party_manifest.json b/third_party_manifest.json index b596340c..acab06b0 100644 --- a/third_party_manifest.json +++ b/third_party_manifest.json @@ -1,5 +1,5 @@ { - "lastUpdated": "Wed Aug 14 2024 10:38:44 GMT+0530 (India Standard Time)", + "lastUpdated": "Fri Sep 20 2024 15:51:01 GMT+0530 (India Standard Time)", "projectName": "@newrelic/security-agent", "projectUrl": "https://github.com/newrelic/csec-node-agent.git", "includeOptDeps": false, @@ -94,6 +94,20 @@ "publisher": "Marat Dulin", "email": "mdevils@yandex.ru" }, + "https-proxy-agent@5.0.1": { + "name": "https-proxy-agent", + "version": "5.0.1", + "range": "^7.0.4", + "licenses": "MIT", + "repoUrl": "https://github.com/TooTallNate/node-https-proxy-agent", + "versionedRepoUrl": "https://github.com/TooTallNate/node-https-proxy-agent/tree/v5.0.1", + "licenseFile": "node_modules/https-proxy-agent/README.md", + "licenseUrl": "https://github.com/TooTallNate/node-https-proxy-agent/blob/v5.0.1/README.md", + "licenseTextSource": "spdx", + "publisher": "Nathan Rajlich", + "email": "nathan@tootallnate.net", + "url": "http://n8.io/" + }, "is-invalid-path@1.0.2": { "name": "is-invalid-path", "version": "1.0.2", @@ -260,15 +274,15 @@ "licenseUrl": "https://github.com/uuidjs/uuid/blob/v9.0.1/LICENSE.md", "licenseTextSource": "file" }, - "ws@8.17.1": { + "ws@8.18.0": { "name": "ws", - "version": "8.17.1", + "version": "8.18.0", "range": "^8.17.1", "licenses": "MIT", "repoUrl": "https://github.com/websockets/ws", - "versionedRepoUrl": "https://github.com/websockets/ws/tree/v8.17.1", + "versionedRepoUrl": "https://github.com/websockets/ws/tree/v8.18.0", "licenseFile": "node_modules/ws/LICENSE", - "licenseUrl": "https://github.com/websockets/ws/blob/v8.17.1/LICENSE", + "licenseUrl": "https://github.com/websockets/ws/blob/v8.18.0/LICENSE", "licenseTextSource": "file", "publisher": "Einar Otto Stangvik", "email": "einaros@gmail.com", From 54dec2fdde7a9ecd6e8c65fc000e85d4a381fa41 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Sat, 21 Sep 2024 11:16:57 +0530 Subject: [PATCH 14/50] fix for exclusion based on regex --- .../core/request-manager.js | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/instrumentation-security/core/request-manager.js b/lib/instrumentation-security/core/request-manager.js index a86ca826..2cd96586 100644 --- a/lib/instrumentation-security/core/request-manager.js +++ b/lib/instrumentation-security/core/request-manager.js @@ -6,6 +6,7 @@ const requestMap = new Map(); const API = require("../../nr-security-api"); const NRAgent = API.getNRAgent(); +const logger = API.getLogger(); const regexPatterns = NRAgent && NRAgent.config.security.exclude_from_iast_scan.api /** @@ -24,11 +25,28 @@ function getRequestFromId(id) { */ function setRequest(id, requestData) { requestMap.set(id, requestData); - const stringToMatch = requestData.uri ? requestData.uri : requestData.url; - const filteredString = stringToMatch.split('?')[0]; - if (regexPatterns.some(regex => filteredString.match(regex))) { - requestMap.delete(id); + try { + const stringToMatch = requestData.url; + const filteredString = stringToMatch.split('?')[0]; + let isRegexMatchestoURL = false; + for (let index = 0; index < regexPatterns.length; index++) { + const regex = new RegExp(regexPatterns[index], 'gm'); + const matchResult = filteredString.match(regex); + if (matchResult && matchResult.length > 0) { + const data = matchResult[0]; + if (filteredString === data) { + isRegexMatchestoURL = true; + } + } + } + if (isRegexMatchestoURL) { + requestMap.delete(id); + logger.debug("Excluding URL %s from IAST processing due to ignore API setting", filteredString); + } + } catch (error) { + logger.debug("Error while processing API regex for restriction", error); } + } /** From 9fb117e1f68cfbb2c910de549990433741b0f74d Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Wed, 25 Sep 2024 16:11:48 +0530 Subject: [PATCH 15/50] fix: Handling to not resolve file path in fs module instrumentation (#257) --- .../hooks/fs/nr-fs.js | 27 ++----------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/lib/instrumentation-security/hooks/fs/nr-fs.js b/lib/instrumentation-security/hooks/fs/nr-fs.js index 76882aae..79edd2f2 100644 --- a/lib/instrumentation-security/hooks/fs/nr-fs.js +++ b/lib/instrumentation-security/hooks/fs/nr-fs.js @@ -142,9 +142,8 @@ function openHook(shim, mod, moduleName) { parameters[0] = API.getSecAgent().applicationInfo.serverInfo.deployedApplications[0].deployedPath + SLASH + parameters[0]; } else if (parameters[0].startsWith(SLASHDOTDOT)) { parameters[0] = API.getSecAgent().applicationInfo.serverInfo.deployedApplications[0].deployedPath + parameters[0]; - } else { - parameters[0] = path.resolve(parameters[0]); - } + } + } catch (error) { } @@ -188,11 +187,6 @@ function probableToFAHooks(shim, mod, moduleName) { const request = requestManager.getRequest(shim); if (request && typeof arguments[0] === STRING && !lodash.isEmpty(arguments[0])) { const traceObject = secUtils.getTraceObject(shim); - try { - parameters[0] = path.resolve(parameters[0]); - } catch (error) { - - } let absoluteParameters = [parameters[0]]; const secMetadata = securityMetaData.getSecurityMetaData(request, absoluteParameters, traceObject, secUtils.getExecutionId(), EVENT_TYPE.FILE_OPERATION, EVENT_CATEGORY.FILE) this.secEvent = API.generateSecEvent(secMetadata); @@ -228,12 +222,6 @@ function probableToFIHooks(shim, mod, moduleName) { const request = requestManager.getRequest(shim); if (request && typeof arguments[0] === STRING && !lodash.isEmpty(arguments[0])) { const traceObject = secUtils.getTraceObject(shim); - try { - parameters[0] = path.resolve(parameters[0]); - parameters[1] = path.resolve(parameters[1]); - } catch (error) { - - } let absoluteParameters = [parameters[0]]; if (fun === COPY_FILE || fun === RENAME) { const secMetadata = securityMetaData.getSecurityMetaData(request, parameters[1], traceObject, secUtils.getExecutionId(), getCase(arguments[1]), EVENT_CATEGORY.FILE) @@ -271,11 +259,6 @@ function probablePromiseToFAHooks(shim, mod, moduleName) { const request = requestManager.getRequest(shim); if (request && typeof arguments[0] === STRING && !lodash.isEmpty(arguments[0])) { const traceObject = secUtils.getTraceObject(shim); - try { - parameters[0] = path.resolve(parameters[0]); - } catch (error) { - - } let absoluteParameters = [parameters[0]]; const secMetadata = securityMetaData.getSecurityMetaData(request, absoluteParameters, traceObject, secUtils.getExecutionId(), EVENT_TYPE.FILE_OPERATION, EVENT_CATEGORY.FILE) this.secEvent = API.generateSecEvent(secMetadata); @@ -304,12 +287,6 @@ function probablePromiseToFIHooks(shim, mod, moduleName) { const request = requestManager.getRequest(shim); if (request && typeof arguments[0] === STRING && !lodash.isEmpty(arguments[0])) { const traceObject = secUtils.getTraceObject(shim); - try { - parameters[0] = path.resolve(parameters[0]); - parameters[1] = path.resolve(parameters[1]); - } catch (error) { - - } let absoluteParameters = [parameters[0]]; if (fun === COPY_FILE || fun === RENAME) { const secMetadata = securityMetaData.getSecurityMetaData(request, parameters[1], traceObject, secUtils.getExecutionId(), getCase(arguments[1]), EVENT_CATEGORY.FILE) From 6b50fc589f441dae576985fe26d5ed145113361c Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Wed, 25 Sep 2024 16:16:24 +0530 Subject: [PATCH 16/50] fix: Fix for security home placeholder replacement in fuzz requests (#256) --- .../hooks/http/nr-http.js | 4 +++- .../websocket/response/fuzz-request-handler.js | 15 ++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/instrumentation-security/hooks/http/nr-http.js b/lib/instrumentation-security/hooks/http/nr-http.js index e3f947ce..3c71a775 100755 --- a/lib/instrumentation-security/hooks/http/nr-http.js +++ b/lib/instrumentation-security/hooks/http/nr-http.js @@ -34,7 +34,8 @@ const semver = require('semver'); const ExceptionReporting = require('../../../nr-security-agent/lib/core/ExceptionReporting'); const CSEC_SEP = ':IAST:'; -const find = '{{NR_CSEC_VALIDATOR_HOME_TMP}}'; +const sep = require('path').sep; +const find = `${sep}{{NR_CSEC_VALIDATOR_HOME_TMP}}`; const CSEC_HOME_TMP_CONST = new RegExp(find, 'g'); let CSEC_HOME = NRAgent && NRAgent.config.newrelic_home ? NRAgent.config.newrelic_home : NRAgent && NRAgent.config.logging.filepath ? path.dirname(NRAgent.config.logging.filepath) : require('path').join(process.cwd()); const CSEC_HOME_TMP = `${CSEC_HOME}/nr-security-home/tmp/language-agent/${process.env.applicationUUID}` @@ -189,6 +190,7 @@ function parseFuzzheaders(requestData, transactionId) { logger.debug("fliesTocreate:", filesToCreate); for (let i = 0; i < filesToCreate.length; i++) { let file = filesToCreate[i].trim(); + file = decodeURIComponent(file); file = file.replace(CSEC_HOME_TMP_CONST, CSEC_HOME_TMP); file = path.resolve(file); const parentDir = path.dirname(file); diff --git a/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js b/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js index f4325c4b..bbd70189 100644 --- a/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js +++ b/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js @@ -25,6 +25,8 @@ const PolicyManager = require('../../../Policy'); const find = `${SLASH}{{NR_CSEC_VALIDATOR_HOME_TMP}}`; const CSEC_HOME_TMP_CONST = new RegExp(find, 'g'); +const CSEC_HOME_TMP_CONST_ENCODED = new RegExp('%7B%7BNR_CSEC_VALIDATOR_HOME_TMP%7D%7D', 'g'); + let logger; let lastFuzzEventTime = 0; let iastIntervalConst; @@ -50,7 +52,7 @@ function startIASTSchedular() { if (isNaN(probingInterval)) { probingInterval = 5; } - + iastIntervalConst = setInterval(() => { let data = IASTUtil.generateIASTDataRequest(); let currentTime = Date.now(); @@ -88,7 +90,14 @@ function logScannedApiId(fuzzHeader, requestURL) { function handler(json) { setLastFuzzEventTime(); let rawFuzzRequest = json.arguments[0]; - rawFuzzRequest = rawFuzzRequest.replace(CSEC_HOME_TMP_CONST, CSEC_HOME_TMP); + + try { + rawFuzzRequest = rawFuzzRequest.replace(CSEC_HOME_TMP_CONST, CSEC_HOME_TMP); + rawFuzzRequest = rawFuzzRequest.replace(CSEC_HOME_TMP_CONST_ENCODED, encodeURI(CSEC_HOME_TMP)); + } catch (error) { + logger.debug("Error while replacing place holder", error); + } + let fuzzRequest; try { fuzzRequest = JSON.parse(rawFuzzRequest); @@ -96,7 +105,7 @@ function handler(json) { IASTUtil.addPendingRequestId(json.id); } catch (error) { logger.error('Parsing exeception in fuzz request: ', error); - + const logMessage = new LogMessage.logMessage(SEVERE, 'Parsing exeception in fuzz request', __filename, error); require('../../../commonUtils').addLogEventtoBuffer(logMessage); } From 6d0cd8b3aa23a44701f6701af7d33ca3962d48a5 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 26 Sep 2024 16:00:42 +0530 Subject: [PATCH 17/50] added handling to log delay scan time and iast data pull request time --- lib/nr-security-agent/index.js | 3 +- lib/nr-security-agent/lib/core/commonUtils.js | 28 ++++++++++++++++++- .../response/fuzz-request-handler.js | 15 ++++++++-- package-lock.json | 4 +++ 4 files changed, 45 insertions(+), 5 deletions(-) diff --git a/lib/nr-security-agent/index.js b/lib/nr-security-agent/index.js index 61758b29..ba414e8a 100644 --- a/lib/nr-security-agent/index.js +++ b/lib/nr-security-agent/index.js @@ -123,11 +123,12 @@ function initialize() { const delay = NRAgent.config.security.scan_schedule.delay; const allowSampling = NRAgent.config.security.scan_schedule.always_sample_traces logger.info("IAST scan delay is set to %s minute", delay); + logger.info("Security Agent scan time is set to :", commonUtils.getScheduledScanTime(delay)) if (delay > 0) { Agent.getAgent().delayed = true; setTimeout(() => { Agent.getAgent().delayed = false; - logger.info("IAST scanning delay over"); + logger.info("IAST scanning delay of %s minutes over", delay); }, delay * 60000); } let tempDelay = delay; diff --git a/lib/nr-security-agent/lib/core/commonUtils.js b/lib/nr-security-agent/lib/core/commonUtils.js index 4d3d3a9d..19c1d22f 100644 --- a/lib/nr-security-agent/lib/core/commonUtils.js +++ b/lib/nr-security-agent/lib/core/commonUtils.js @@ -492,6 +492,31 @@ function sendErrorToErrorInbox(error) { API.newrelic.noticeError(error); } +const getScheduledScanTime = (delayInMinutes) => { + // Get the current time + const currentTime = new Date(); + + // Add the given minutes to the current time + currentTime.setMinutes(currentTime.getMinutes() + delayInMinutes); + + // Format the result as a human-readable string + const formattedTime = `${currentTime.toLocaleTimeString()} ${currentTime.toLocaleDateString()}`; + + const year = currentTime.getFullYear(); + const month = currentTime.toLocaleString("default", { month: "long" }); + const day = currentTime.toLocaleString("default", { weekday: "long" }); + const date = currentTime.getDate(); + const hours = currentTime.getHours(); + const minutes = currentTime.getMinutes(); + const seconds = currentTime.getSeconds(); + const futureUpdatedTime = `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`; + const futureDateTime = `${day}, ${month} ${date} ${year} ${futureUpdatedTime}`; + return futureDateTime + + + return formattedTime; +}; + module.exports = { getUUID, @@ -520,5 +545,6 @@ module.exports = { listSkipDetectionCategory, executeCronSchedule, honourDurationConfiguration, - sendErrorToErrorInbox + sendErrorToErrorInbox, + getScheduledScanTime }; \ No newline at end of file diff --git a/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js b/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js index 1695fa05..e267b5a5 100644 --- a/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js +++ b/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js @@ -33,13 +33,22 @@ let iastIntervalConst; let coolDownIntervalConst; let additionalCoolDownTime = 0; let fuzzedApiIDSet = new Set(); +const API = require('../../../../../../nr-security-api'); +const NRAgent = API.getNRAgent(); /** * utility to start IAST Schedular */ function startIASTSchedular() { - Agent.getAgent().client.dispatcher(IASTUtil.generateIASTDataRequest()); + if (Agent.getAgent().delayed){ + const delay = NRAgent.config.security.scan_schedule.delay; + logger.info("IAST data pull request is scheduled at %s", require('../../../commonUtils').getScheduledScanTime(delay)) + } + if (!Agent.getAgent().delayed) { + Agent.getAgent().client.dispatcher(IASTUtil.generateIASTDataRequest()); + } + if (iastIntervalConst) { clearInterval(iastIntervalConst); } @@ -66,7 +75,7 @@ function startIASTSchedular() { logger.trace("Completed requests so far:", completedListSize); logger.trace("Pending requests so far:", pendingListSize); - if (timeDiffInSeconds > 5 && additionalCoolDownTime == 0) { + if (timeDiffInSeconds > 1 && additionalCoolDownTime == 0) { Agent.getAgent().client.dispatcher(data); } }, probingInterval * 1000); @@ -91,7 +100,7 @@ function logScannedApiId(fuzzHeader, requestURL) { // handler function to parse fuzz event and prepare fuzz request function handler(json) { - if (Agent.getAgent().status.getStatus() == 'disabled'){ + if (Agent.getAgent().status.getStatus() == 'disabled') { return; } setLastFuzzEventTime(); diff --git a/package-lock.json b/package-lock.json index beb9fa64..7438717f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -67,6 +67,10 @@ "xmldom": "^0.6.0", "xpath": "^0.0.32", "xpath.js": "^1.1.0" + }, + "engines": { + "node": ">=18", + "npm": ">=6.0.0" } }, "node_modules/@aashutoshrathi/word-wrap": { From ca280ebe33593fb212f65eec5a9b96534862da4a Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 26 Sep 2024 16:02:45 +0530 Subject: [PATCH 18/50] debug log added --- .../core/connections/websocket/response/fuzz-request-handler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js b/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js index e267b5a5..d2b05d22 100644 --- a/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js +++ b/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js @@ -43,7 +43,7 @@ const NRAgent = API.getNRAgent(); function startIASTSchedular() { if (Agent.getAgent().delayed){ const delay = NRAgent.config.security.scan_schedule.delay; - logger.info("IAST data pull request is scheduled at %s", require('../../../commonUtils').getScheduledScanTime(delay)) + logger.debug("IAST data pull request is scheduled at %s", require('../../../commonUtils').getScheduledScanTime(delay)) } if (!Agent.getAgent().delayed) { Agent.getAgent().client.dispatcher(IASTUtil.generateIASTDataRequest()); From b75bc167c145f72692f9b10b99f98a543bcea154 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 26 Sep 2024 16:05:04 +0530 Subject: [PATCH 19/50] minor fix --- lib/nr-security-agent/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nr-security-agent/index.js b/lib/nr-security-agent/index.js index ba414e8a..a30d180b 100644 --- a/lib/nr-security-agent/index.js +++ b/lib/nr-security-agent/index.js @@ -122,7 +122,7 @@ function initialize() { if (NRAgent.config.security.enabled || !NRAgent.config.high_security) { const delay = NRAgent.config.security.scan_schedule.delay; const allowSampling = NRAgent.config.security.scan_schedule.always_sample_traces - logger.info("IAST scan delay is set to %s minute", delay); + logger.debug("IAST scan delay is set to %s minute", delay); logger.info("Security Agent scan time is set to :", commonUtils.getScheduledScanTime(delay)) if (delay > 0) { Agent.getAgent().delayed = true; From 09567c55d7b9869f9a21a3b5a9100c5a2b35c41f Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 26 Sep 2024 16:06:09 +0530 Subject: [PATCH 20/50] remove logger for scan delay --- lib/nr-security-agent/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/nr-security-agent/index.js b/lib/nr-security-agent/index.js index a30d180b..0f48cade 100644 --- a/lib/nr-security-agent/index.js +++ b/lib/nr-security-agent/index.js @@ -122,7 +122,6 @@ function initialize() { if (NRAgent.config.security.enabled || !NRAgent.config.high_security) { const delay = NRAgent.config.security.scan_schedule.delay; const allowSampling = NRAgent.config.security.scan_schedule.always_sample_traces - logger.debug("IAST scan delay is set to %s minute", delay); logger.info("Security Agent scan time is set to :", commonUtils.getScheduledScanTime(delay)) if (delay > 0) { Agent.getAgent().delayed = true; From 5083e47be5a8ff56c3bfea88063b85206f15efc3 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 3 Oct 2024 09:50:55 +0530 Subject: [PATCH 21/50] added handling to parse duration and delay to integer --- lib/nr-security-agent/index.js | 9 +++++++-- lib/nr-security-agent/lib/core/commonUtils.js | 7 ++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/nr-security-agent/index.js b/lib/nr-security-agent/index.js index 0f48cade..088503f1 100644 --- a/lib/nr-security-agent/index.js +++ b/lib/nr-security-agent/index.js @@ -120,8 +120,13 @@ function initialize() { logger.info('NR Agent started with agent_run_id:', NRAgent.config.run_id, NRAgent.config.account_id); if (NRAgent.config.security.enabled || !NRAgent.config.high_security) { - const delay = NRAgent.config.security.scan_schedule.delay; - const allowSampling = NRAgent.config.security.scan_schedule.always_sample_traces + let delayFromConfig = parseInt(NRAgent.config.security.scan_schedule.delay); + let delay = delayFromConfig; + if (isNaN(delay) || delay < 0) { + delay = 0; + } + const allowSampling = NRAgent.config.security.scan_schedule.always_sample_traces; + logger.debug("IAST delay is set to:", delay); logger.info("Security Agent scan time is set to :", commonUtils.getScheduledScanTime(delay)) if (delay > 0) { Agent.getAgent().delayed = true; diff --git a/lib/nr-security-agent/lib/core/commonUtils.js b/lib/nr-security-agent/lib/core/commonUtils.js index 19c1d22f..6c0e6ecb 100644 --- a/lib/nr-security-agent/lib/core/commonUtils.js +++ b/lib/nr-security-agent/lib/core/commonUtils.js @@ -472,7 +472,12 @@ function executeCronSchedule() { } function honourDurationConfiguration() { - const duration = NRAgent.config.security.scan_schedule.duration; + let durationFromConfig = parseInt(NRAgent.config.security.scan_schedule.duration); + let duration = durationFromConfig; + if (isNaN(duration) || duration < 0) { + duration = 0; + } + logger.debug("IAST duratoin is set to:", duration); if (duration < 1) { return; } From 868ef8a6a88beeb9b5ee4ba4a37008592c1e7342 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 3 Oct 2024 10:34:57 +0530 Subject: [PATCH 22/50] disable agent if cron expression is wrong --- lib/nr-security-agent/lib/core/commonUtils.js | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/lib/nr-security-agent/lib/core/commonUtils.js b/lib/nr-security-agent/lib/core/commonUtils.js index 6c0e6ecb..3ac2c86d 100644 --- a/lib/nr-security-agent/lib/core/commonUtils.js +++ b/lib/nr-security-agent/lib/core/commonUtils.js @@ -456,19 +456,26 @@ function refreshAgent() { } function executeCronSchedule() { - const schedule = NRAgent.config.security.scan_schedule.schedule; - if (lodash.isEmpty(schedule)) { - return; + try { + const schedule = NRAgent.config.security.scan_schedule.schedule; + logger.debug("schedule is set to:", schedule); + if (lodash.isEmpty(schedule)) { + return; + } + const job = new CronJob( + schedule, // cronTime + function () { + logger.debug('Cron schedule invoked'); + refreshAgent() + }, // onTick + null, // onComplete + true, // start + ); + } catch (error) { + logger.error("Error while processing schedule. Please check schedule cron expression", error); + shutDownAgent(); } - const job = new CronJob( - schedule, // cronTime - function () { - logger.debug('Cron schedule invoked'); - refreshAgent() - }, // onTick - null, // onComplete - true, // start - ); + } function honourDurationConfiguration() { @@ -517,11 +524,16 @@ const getScheduledScanTime = (delayInMinutes) => { const futureUpdatedTime = `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`; const futureDateTime = `${day}, ${month} ${date} ${year} ${futureUpdatedTime}`; return futureDateTime - - - return formattedTime; }; +function shutDownAgent(){ + const { Agent } = require('./agent'); + Agent.getAgent().status.setStatus('disabled'); + logger.warn("Security Agent status is disabled"); + const wsClient = Agent.getAgent().client; + wsClient.closeWS(); +} + module.exports = { getUUID, From 34cbed7c2cb8a087f501a610d3dfe113dcd280c0 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 3 Oct 2024 11:50:03 +0530 Subject: [PATCH 23/50] calling utility to shutdonw agent --- lib/nr-security-agent/lib/core/commonUtils.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/nr-security-agent/lib/core/commonUtils.js b/lib/nr-security-agent/lib/core/commonUtils.js index 3ac2c86d..327be97d 100644 --- a/lib/nr-security-agent/lib/core/commonUtils.js +++ b/lib/nr-security-agent/lib/core/commonUtils.js @@ -488,12 +488,8 @@ function honourDurationConfiguration() { if (duration < 1) { return; } - const { Agent } = require('./agent'); setTimeout(() => { - Agent.getAgent().status.setStatus('disabled'); - logger.warn("Security Agent status is disabled"); - const wsClient = Agent.getAgent().client; - wsClient.closeWS(); + shutDownAgent(); }, duration * 60000); } /** @@ -528,6 +524,9 @@ const getScheduledScanTime = (delayInMinutes) => { function shutDownAgent(){ const { Agent } = require('./agent'); + if(Agent.getAgent().status.getStatus()==='disabled'){ + return; + } Agent.getAgent().status.setStatus('disabled'); logger.warn("Security Agent status is disabled"); const wsClient = Agent.getAgent().client; From 1d4ec8a34e8e12e42c09a4ed559da400389b88b1 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 3 Oct 2024 11:59:56 +0530 Subject: [PATCH 24/50] log the delay message if the delay is greater than 0 --- lib/nr-security-agent/index.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/nr-security-agent/index.js b/lib/nr-security-agent/index.js index 088503f1..f683adcc 100644 --- a/lib/nr-security-agent/index.js +++ b/lib/nr-security-agent/index.js @@ -126,9 +126,10 @@ function initialize() { delay = 0; } const allowSampling = NRAgent.config.security.scan_schedule.always_sample_traces; - logger.debug("IAST delay is set to:", delay); - logger.info("Security Agent scan time is set to :", commonUtils.getScheduledScanTime(delay)) + if (delay > 0) { + logger.debug("IAST delay is set to:", delay); + logger.info("Security Agent scan time is set to :", commonUtils.getScheduledScanTime(delay)) Agent.getAgent().delayed = true; setTimeout(() => { Agent.getAgent().delayed = false; From f792ba37d56f1a81d299e8ae07e4f2f26b49111e Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 3 Oct 2024 12:03:09 +0530 Subject: [PATCH 25/50] fix to log schedule config if non empty --- lib/nr-security-agent/lib/core/commonUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nr-security-agent/lib/core/commonUtils.js b/lib/nr-security-agent/lib/core/commonUtils.js index 327be97d..a3df5b95 100644 --- a/lib/nr-security-agent/lib/core/commonUtils.js +++ b/lib/nr-security-agent/lib/core/commonUtils.js @@ -458,10 +458,10 @@ function refreshAgent() { function executeCronSchedule() { try { const schedule = NRAgent.config.security.scan_schedule.schedule; - logger.debug("schedule is set to:", schedule); if (lodash.isEmpty(schedule)) { return; } + logger.debug("Schedule config is set to:", schedule); const job = new CronJob( schedule, // cronTime function () { From e3161c7cee6041c05bb4c3d9f380a54f2c68904f Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 3 Oct 2024 12:10:17 +0530 Subject: [PATCH 26/50] Added log for agent shutdown message --- lib/nr-security-agent/lib/core/commonUtils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/nr-security-agent/lib/core/commonUtils.js b/lib/nr-security-agent/lib/core/commonUtils.js index a3df5b95..54d6f8d6 100644 --- a/lib/nr-security-agent/lib/core/commonUtils.js +++ b/lib/nr-security-agent/lib/core/commonUtils.js @@ -485,6 +485,7 @@ function honourDurationConfiguration() { duration = 0; } logger.debug("IAST duratoin is set to:", duration); + logger.info("Security Agent shutdown is set to :", getScheduledScanTime(duration)) if (duration < 1) { return; } From 65a2b21006bdf4ba098e1b9b5ffd04d14606d990 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 3 Oct 2024 12:15:15 +0530 Subject: [PATCH 27/50] minor log update --- lib/nr-security-agent/lib/core/commonUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nr-security-agent/lib/core/commonUtils.js b/lib/nr-security-agent/lib/core/commonUtils.js index 54d6f8d6..4ba041ba 100644 --- a/lib/nr-security-agent/lib/core/commonUtils.js +++ b/lib/nr-security-agent/lib/core/commonUtils.js @@ -529,9 +529,9 @@ function shutDownAgent(){ return; } Agent.getAgent().status.setStatus('disabled'); - logger.warn("Security Agent status is disabled"); const wsClient = Agent.getAgent().client; wsClient.closeWS(); + logger.warn("Security Agent status is disabled"); } From 80b460325e0e721810ecb18b8ba067dec1a63d0f Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 3 Oct 2024 13:42:43 +0530 Subject: [PATCH 28/50] spell fix --- lib/nr-security-agent/lib/core/commonUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nr-security-agent/lib/core/commonUtils.js b/lib/nr-security-agent/lib/core/commonUtils.js index 4ba041ba..49984bf3 100644 --- a/lib/nr-security-agent/lib/core/commonUtils.js +++ b/lib/nr-security-agent/lib/core/commonUtils.js @@ -484,7 +484,7 @@ function honourDurationConfiguration() { if (isNaN(duration) || duration < 0) { duration = 0; } - logger.debug("IAST duratoin is set to:", duration); + logger.debug("IAST duration is set to:", duration); logger.info("Security Agent shutdown is set to :", getScheduledScanTime(duration)) if (duration < 1) { return; From 650c311f5e7320aa19d9630dd421f31adef88070 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 3 Oct 2024 13:46:08 +0530 Subject: [PATCH 29/50] delay parsing udpate --- .../websocket/response/fuzz-request-handler.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js b/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js index d2b05d22..bd84123f 100644 --- a/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js +++ b/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js @@ -41,8 +41,12 @@ const NRAgent = API.getNRAgent(); * utility to start IAST Schedular */ function startIASTSchedular() { - if (Agent.getAgent().delayed){ - const delay = NRAgent.config.security.scan_schedule.delay; + if (Agent.getAgent().delayed) { + let delayFromConfig = parseInt(NRAgent.config.security.scan_schedule.delay); + let delay = delayFromConfig; + if (isNaN(delay) || delay < 0) { + delay = 0; + } logger.debug("IAST data pull request is scheduled at %s", require('../../../commonUtils').getScheduledScanTime(delay)) } if (!Agent.getAgent().delayed) { From 07826693b43d9fd585e8bcf597a724a68f7b477b Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 3 Oct 2024 13:50:39 +0530 Subject: [PATCH 30/50] added logger for SA config --- lib/nr-security-agent/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/nr-security-agent/index.js b/lib/nr-security-agent/index.js index f683adcc..0f2bfd6b 100644 --- a/lib/nr-security-agent/index.js +++ b/lib/nr-security-agent/index.js @@ -148,6 +148,8 @@ function initialize() { commonUtils.honourDurationConfiguration(); }, tempDelay * 60000); + logger.info("Security Agent is running with config:", JSON.stringify(NRAgent.config.security)); + } else { logger.warn("security.enabled flag is set to false"); From d33af0946ed0bdb01b963a5b06fef6476eba713a Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 3 Oct 2024 13:54:08 +0530 Subject: [PATCH 31/50] updates to main config for delay and duration --- lib/nr-security-agent/index.js | 4 +++- lib/nr-security-agent/lib/core/commonUtils.js | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/nr-security-agent/index.js b/lib/nr-security-agent/index.js index 0f2bfd6b..8192745d 100644 --- a/lib/nr-security-agent/index.js +++ b/lib/nr-security-agent/index.js @@ -125,6 +125,7 @@ function initialize() { if (isNaN(delay) || delay < 0) { delay = 0; } + NRAgent.config.security.scan_schedule.delay = delay; const allowSampling = NRAgent.config.security.scan_schedule.always_sample_traces; if (delay > 0) { @@ -146,9 +147,10 @@ function initialize() { Agent.setNRAgent(NRAgent); commonUtils.executeCronSchedule(); commonUtils.honourDurationConfiguration(); + logger.info("Security Agent is running with config:", JSON.stringify(NRAgent.config.security)); }, tempDelay * 60000); - logger.info("Security Agent is running with config:", JSON.stringify(NRAgent.config.security)); + } else { diff --git a/lib/nr-security-agent/lib/core/commonUtils.js b/lib/nr-security-agent/lib/core/commonUtils.js index 49984bf3..40a6c714 100644 --- a/lib/nr-security-agent/lib/core/commonUtils.js +++ b/lib/nr-security-agent/lib/core/commonUtils.js @@ -485,6 +485,7 @@ function honourDurationConfiguration() { duration = 0; } logger.debug("IAST duration is set to:", duration); + NRAgent.config.security.scan_schedule.duration = duration; logger.info("Security Agent shutdown is set to :", getScheduledScanTime(duration)) if (duration < 1) { return; From 8de9a1111bf370c3b13acb3b85d54c59decbb6ae Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 3 Oct 2024 14:02:53 +0530 Subject: [PATCH 32/50] log only when duration is greater than 1 --- lib/nr-security-agent/lib/core/commonUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nr-security-agent/lib/core/commonUtils.js b/lib/nr-security-agent/lib/core/commonUtils.js index 40a6c714..9b755551 100644 --- a/lib/nr-security-agent/lib/core/commonUtils.js +++ b/lib/nr-security-agent/lib/core/commonUtils.js @@ -486,10 +486,10 @@ function honourDurationConfiguration() { } logger.debug("IAST duration is set to:", duration); NRAgent.config.security.scan_schedule.duration = duration; - logger.info("Security Agent shutdown is set to :", getScheduledScanTime(duration)) if (duration < 1) { return; } + logger.info("Security Agent shutdown is set to:", getScheduledScanTime(duration)) setTimeout(() => { shutDownAgent(); }, duration * 60000); From e2654da49efce482b78d5f9fc09104f968cd7657 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Thu, 3 Oct 2024 15:30:11 +0530 Subject: [PATCH 33/50] minor space fix --- lib/nr-security-agent/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nr-security-agent/index.js b/lib/nr-security-agent/index.js index 8192745d..1854dfe5 100644 --- a/lib/nr-security-agent/index.js +++ b/lib/nr-security-agent/index.js @@ -130,7 +130,7 @@ function initialize() { if (delay > 0) { logger.debug("IAST delay is set to:", delay); - logger.info("Security Agent scan time is set to :", commonUtils.getScheduledScanTime(delay)) + logger.info("Security Agent scan time is set to:", commonUtils.getScheduledScanTime(delay)) Agent.getAgent().delayed = true; setTimeout(() => { Agent.getAgent().delayed = false; From 0f5c084e936a0ae02ec8dd56fda4508a4b182ffb Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Fri, 4 Oct 2024 09:56:27 +0530 Subject: [PATCH 34/50] Handling to generate event if allow sample flag is true regardless of duration and agent session fix --- lib/nr-security-agent/index.js | 7 +++++-- lib/nr-security-agent/lib/core/commonUtils.js | 5 +++++ lib/nr-security-agent/lib/core/websocket-client.js | 1 + 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/nr-security-agent/index.js b/lib/nr-security-agent/index.js index 1854dfe5..3bd9b1f9 100644 --- a/lib/nr-security-agent/index.js +++ b/lib/nr-security-agent/index.js @@ -118,7 +118,10 @@ function initialize() { NRAgent.on('started', () => { NRLogger.info("Started New Relic Node.js Security Agent"); logger.info('NR Agent started with agent_run_id:', NRAgent.config.run_id, NRAgent.config.account_id); - + if (Agent.getAgent().status.getStatus() != 'connecting') { + wsClient.obeyReconnect(); + return; + } if (NRAgent.config.security.enabled || !NRAgent.config.high_security) { let delayFromConfig = parseInt(NRAgent.config.security.scan_schedule.delay); let delay = delayFromConfig; @@ -150,7 +153,7 @@ function initialize() { logger.info("Security Agent is running with config:", JSON.stringify(NRAgent.config.security)); }, tempDelay * 60000); - + } else { diff --git a/lib/nr-security-agent/lib/core/commonUtils.js b/lib/nr-security-agent/lib/core/commonUtils.js index 9b755551..4bc3b774 100644 --- a/lib/nr-security-agent/lib/core/commonUtils.js +++ b/lib/nr-security-agent/lib/core/commonUtils.js @@ -526,6 +526,10 @@ const getScheduledScanTime = (delayInMinutes) => { function shutDownAgent(){ const { Agent } = require('./agent'); + if(NRAgent.config.security.scan_schedule.always_sample_traces){ + Agent.getAgent().delayed = true; + return; + } if(Agent.getAgent().status.getStatus()==='disabled'){ return; } @@ -536,6 +540,7 @@ function shutDownAgent(){ } + module.exports = { getUUID, getKindIdPair, diff --git a/lib/nr-security-agent/lib/core/websocket-client.js b/lib/nr-security-agent/lib/core/websocket-client.js index 005c5c24..2c388c7d 100644 --- a/lib/nr-security-agent/lib/core/websocket-client.js +++ b/lib/nr-security-agent/lib/core/websocket-client.js @@ -189,6 +189,7 @@ function sendEvent(event, callback = DEFAULT_EVENT_SEND_CB) { function obeyReconnect() { + Agent.getAgent().delayed = false; wsInstance.obeyReconnect(); } From 970eda6c43ef5e403a87ac869b30607d77088595 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Mon, 7 Oct 2024 09:03:44 +0530 Subject: [PATCH 35/50] fix for delay flag --- lib/nr-security-agent/index.js | 1 + lib/nr-security-agent/lib/core/websocket-client.js | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nr-security-agent/index.js b/lib/nr-security-agent/index.js index 3bd9b1f9..a3a77d6a 100644 --- a/lib/nr-security-agent/index.js +++ b/lib/nr-security-agent/index.js @@ -119,6 +119,7 @@ function initialize() { NRLogger.info("Started New Relic Node.js Security Agent"); logger.info('NR Agent started with agent_run_id:', NRAgent.config.run_id, NRAgent.config.account_id); if (Agent.getAgent().status.getStatus() != 'connecting') { + Agent.getAgent().delayed = false; wsClient.obeyReconnect(); return; } diff --git a/lib/nr-security-agent/lib/core/websocket-client.js b/lib/nr-security-agent/lib/core/websocket-client.js index 2c388c7d..005c5c24 100644 --- a/lib/nr-security-agent/lib/core/websocket-client.js +++ b/lib/nr-security-agent/lib/core/websocket-client.js @@ -189,7 +189,6 @@ function sendEvent(event, callback = DEFAULT_EVENT_SEND_CB) { function obeyReconnect() { - Agent.getAgent().delayed = false; wsInstance.obeyReconnect(); } From a444a61dfae742bd4a0e6743403970c32ce4b880 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Mon, 7 Oct 2024 09:17:27 +0530 Subject: [PATCH 36/50] cron express fix of ? --- lib/nr-security-agent/lib/core/commonUtils.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/nr-security-agent/lib/core/commonUtils.js b/lib/nr-security-agent/lib/core/commonUtils.js index 4bc3b774..1fd984c1 100644 --- a/lib/nr-security-agent/lib/core/commonUtils.js +++ b/lib/nr-security-agent/lib/core/commonUtils.js @@ -457,11 +457,12 @@ function refreshAgent() { function executeCronSchedule() { try { - const schedule = NRAgent.config.security.scan_schedule.schedule; + let schedule = NRAgent.config.security.scan_schedule.schedule; if (lodash.isEmpty(schedule)) { return; } logger.debug("Schedule config is set to:", schedule); + schedule = schedule.replace(/\?/g, '*'); const job = new CronJob( schedule, // cronTime function () { From 09fa058e4042f956a2c1cbc1acfc5a8fbd72ff84 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Mon, 7 Oct 2024 12:26:24 +0530 Subject: [PATCH 37/50] fix for invocation of duration and cron --- lib/nr-security-agent/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/nr-security-agent/index.js b/lib/nr-security-agent/index.js index a3a77d6a..2d95f11f 100644 --- a/lib/nr-security-agent/index.js +++ b/lib/nr-security-agent/index.js @@ -139,6 +139,8 @@ function initialize() { setTimeout(() => { Agent.getAgent().delayed = false; logger.info("IAST scanning delay of %s minutes over", delay); + commonUtils.executeCronSchedule(); + commonUtils.honourDurationConfiguration(); }, delay * 60000); } let tempDelay = delay; @@ -149,8 +151,6 @@ function initialize() { wsClient.initialize(); Agent.getAgent().status.setStatus('connecting'); Agent.setNRAgent(NRAgent); - commonUtils.executeCronSchedule(); - commonUtils.honourDurationConfiguration(); logger.info("Security Agent is running with config:", JSON.stringify(NRAgent.config.security)); }, tempDelay * 60000); From 390254697766542c12891038816fdd5f5ca0681b Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Mon, 7 Oct 2024 12:45:59 +0530 Subject: [PATCH 38/50] added logger for hibernate mode --- lib/nr-security-agent/lib/core/commonUtils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/nr-security-agent/lib/core/commonUtils.js b/lib/nr-security-agent/lib/core/commonUtils.js index 1fd984c1..dadddce4 100644 --- a/lib/nr-security-agent/lib/core/commonUtils.js +++ b/lib/nr-security-agent/lib/core/commonUtils.js @@ -529,6 +529,7 @@ function shutDownAgent(){ const { Agent } = require('./agent'); if(NRAgent.config.security.scan_schedule.always_sample_traces){ Agent.getAgent().delayed = true; + logger.warn('Scan duration completed, IAST going under hibernate mode') return; } if(Agent.getAgent().status.getStatus()==='disabled'){ From 48cab3935dca845e9b0e862b628dda67888484a8 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Mon, 7 Oct 2024 13:58:57 +0530 Subject: [PATCH 39/50] Handling to not start agent until the cron expression time --- lib/nr-security-agent/index.js | 3 ++ lib/nr-security-agent/lib/core/commonUtils.js | 47 +++++++++++++++++-- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/lib/nr-security-agent/index.js b/lib/nr-security-agent/index.js index 2d95f11f..94299bc2 100644 --- a/lib/nr-security-agent/index.js +++ b/lib/nr-security-agent/index.js @@ -148,6 +148,9 @@ function initialize() { tempDelay = 0; } setTimeout(() => { + if(commonUtils.honourCronExpression() && !allowSampling){ + return; + } wsClient.initialize(); Agent.getAgent().status.setStatus('connecting'); Agent.setNRAgent(NRAgent); diff --git a/lib/nr-security-agent/lib/core/commonUtils.js b/lib/nr-security-agent/lib/core/commonUtils.js index dadddce4..e4b29794 100644 --- a/lib/nr-security-agent/lib/core/commonUtils.js +++ b/lib/nr-security-agent/lib/core/commonUtils.js @@ -24,6 +24,7 @@ let websocketHealth; const ringBuffer = require('ringbufferjs'); const bufferedLogEvents = new ringBuffer(10); const { CronJob } = require('cron'); +const cron = require('cron'); const skip_detection_category_map = { insecure_settings: ['CRYPTO', 'HASH', 'RANDOM', 'SECURE_COOKIE', 'TRUSTBOUNDARY'], @@ -463,7 +464,7 @@ function executeCronSchedule() { } logger.debug("Schedule config is set to:", schedule); schedule = schedule.replace(/\?/g, '*'); - const job = new CronJob( + const job = new cron.CronJob( schedule, // cronTime function () { logger.debug('Cron schedule invoked'); @@ -525,14 +526,14 @@ const getScheduledScanTime = (delayInMinutes) => { return futureDateTime }; -function shutDownAgent(){ +function shutDownAgent() { const { Agent } = require('./agent'); - if(NRAgent.config.security.scan_schedule.always_sample_traces){ + if (NRAgent.config.security.scan_schedule.always_sample_traces) { Agent.getAgent().delayed = true; logger.warn('Scan duration completed, IAST going under hibernate mode') return; } - if(Agent.getAgent().status.getStatus()==='disabled'){ + if (Agent.getAgent().status.getStatus() === 'disabled') { return; } Agent.getAgent().status.setStatus('disabled'); @@ -541,6 +542,41 @@ function shutDownAgent(){ logger.warn("Security Agent status is disabled"); } +function honourCronExpression() { + let honourCronFlag = false; + try { + const { Agent } = require('./agent'); + const wsClient = Agent.getAgent().client; + let schedule = NRAgent.config.security.scan_schedule.schedule; + if (lodash.isEmpty(schedule)) { + return; + } + logger.debug("Schedule config is set to:", schedule); + + schedule = schedule.replace(/\?/g, '*'); + honourCronFlag = true; + Agent.getAgent().delayed = true; + logger.info("Security Agent scan time is set to:", getScheduledScanTime(Math.ceil(cron.timeout(schedule)/60000))) + setTimeout(() => { + Agent.getAgent().delayed = false; + if(!NRAgent.config.security.scan_schedule.always_sample_traces){ + wsClient.initialize(); + } + else{ + wsClient.obeyReconnect(); + } + Agent.getAgent().status.setStatus('connecting'); + Agent.setNRAgent(NRAgent); + logger.info("Security Agent is running with config:", JSON.stringify(NRAgent.config.security)); + }, cron.timeout(schedule)); + } catch (error) { + logger.debug("Error while processing cron expression:", error); + return false; + } + return honourCronFlag; + +} + module.exports = { @@ -571,5 +607,6 @@ module.exports = { executeCronSchedule, honourDurationConfiguration, sendErrorToErrorInbox, - getScheduledScanTime + getScheduledScanTime, + honourCronExpression }; \ No newline at end of file From 64512262980359cff14acfeb3963fb1a27cb8d60 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Mon, 7 Oct 2024 14:14:57 +0530 Subject: [PATCH 40/50] fix for cron --- lib/nr-security-agent/index.js | 1 + lib/nr-security-agent/lib/core/commonUtils.js | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/nr-security-agent/index.js b/lib/nr-security-agent/index.js index 94299bc2..b605cb79 100644 --- a/lib/nr-security-agent/index.js +++ b/lib/nr-security-agent/index.js @@ -151,6 +151,7 @@ function initialize() { if(commonUtils.honourCronExpression() && !allowSampling){ return; } + commonUtils.honourDurationConfiguration(); wsClient.initialize(); Agent.getAgent().status.setStatus('connecting'); Agent.setNRAgent(NRAgent); diff --git a/lib/nr-security-agent/lib/core/commonUtils.js b/lib/nr-security-agent/lib/core/commonUtils.js index e4b29794..50e2cf96 100644 --- a/lib/nr-security-agent/lib/core/commonUtils.js +++ b/lib/nr-security-agent/lib/core/commonUtils.js @@ -568,6 +568,7 @@ function honourCronExpression() { Agent.getAgent().status.setStatus('connecting'); Agent.setNRAgent(NRAgent); logger.info("Security Agent is running with config:", JSON.stringify(NRAgent.config.security)); + executeCronSchedule(); }, cron.timeout(schedule)); } catch (error) { logger.debug("Error while processing cron expression:", error); From 1e189aed0a7c735bc2d86134ce40d3dcbf5cdb5c Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Mon, 7 Oct 2024 14:39:31 +0530 Subject: [PATCH 41/50] handling to store request if agent is in active mode --- lib/instrumentation-security/core/request-manager.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/instrumentation-security/core/request-manager.js b/lib/instrumentation-security/core/request-manager.js index 2cd96586..8852f3e5 100644 --- a/lib/instrumentation-security/core/request-manager.js +++ b/lib/instrumentation-security/core/request-manager.js @@ -24,6 +24,9 @@ function getRequestFromId(id) { * @param {*} requestData */ function setRequest(id, requestData) { + if (API.getSecAgent().status.getStatus() != 'active') { + return; + } requestMap.set(id, requestData); try { const stringToMatch = requestData.url; From 3d81aa40abd4ea214c176e7d21e803b1df802938 Mon Sep 17 00:00:00 2001 From: pratik-k2 Date: Tue, 8 Oct 2024 13:43:22 +0530 Subject: [PATCH 42/50] updated rxss detection condition --- lib/instrumentation-security/hooks/http/nr-http.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/instrumentation-security/hooks/http/nr-http.js b/lib/instrumentation-security/hooks/http/nr-http.js index be480446..dc899e5b 100755 --- a/lib/instrumentation-security/hooks/http/nr-http.js +++ b/lib/instrumentation-security/hooks/http/nr-http.js @@ -296,7 +296,7 @@ function emitHook(shim, mod, moduleName) { const resp = arguments[2]; if (arguments[0] == 'request') { - if (NRAgent && NRAgent.config.security.detection.rxss.enabled && !NRAgent.config.security.exclude_from_iast_scan.iast_detection_category.rxss) { + if (NRAgent && !NRAgent.config.security.exclude_from_iast_scan.iast_detection_category.rxss && NRAgent.config.security.detection.rxss.enabled) { responseHook(resp, req, shim); } From c4c2e4dcffd3e861bdcf8ab717b8ac2556eb698e Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Tue, 8 Oct 2024 14:54:33 +0530 Subject: [PATCH 43/50] formatting fix --- lib/nr-security-agent/index.js | 5 +---- lib/nr-security-agent/lib/core/commonUtils.js | 11 ++++------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/lib/nr-security-agent/index.js b/lib/nr-security-agent/index.js index b605cb79..7753822e 100644 --- a/lib/nr-security-agent/index.js +++ b/lib/nr-security-agent/index.js @@ -148,7 +148,7 @@ function initialize() { tempDelay = 0; } setTimeout(() => { - if(commonUtils.honourCronExpression() && !allowSampling){ + if (commonUtils.honourCronExpression() && !allowSampling) { return; } commonUtils.honourDurationConfiguration(); @@ -157,9 +157,6 @@ function initialize() { Agent.setNRAgent(NRAgent); logger.info("Security Agent is running with config:", JSON.stringify(NRAgent.config.security)); }, tempDelay * 60000); - - - } else { logger.warn("security.enabled flag is set to false"); diff --git a/lib/nr-security-agent/lib/core/commonUtils.js b/lib/nr-security-agent/lib/core/commonUtils.js index 50e2cf96..8645c358 100644 --- a/lib/nr-security-agent/lib/core/commonUtils.js +++ b/lib/nr-security-agent/lib/core/commonUtils.js @@ -511,9 +511,6 @@ const getScheduledScanTime = (delayInMinutes) => { // Add the given minutes to the current time currentTime.setMinutes(currentTime.getMinutes() + delayInMinutes); - // Format the result as a human-readable string - const formattedTime = `${currentTime.toLocaleTimeString()} ${currentTime.toLocaleDateString()}`; - const year = currentTime.getFullYear(); const month = currentTime.toLocaleString("default", { month: "long" }); const day = currentTime.toLocaleString("default", { weekday: "long" }); @@ -552,17 +549,17 @@ function honourCronExpression() { return; } logger.debug("Schedule config is set to:", schedule); - + schedule = schedule.replace(/\?/g, '*'); honourCronFlag = true; Agent.getAgent().delayed = true; - logger.info("Security Agent scan time is set to:", getScheduledScanTime(Math.ceil(cron.timeout(schedule)/60000))) + logger.info("Security Agent scan time is set to:", getScheduledScanTime(Math.ceil(cron.timeout(schedule) / 60000))) setTimeout(() => { Agent.getAgent().delayed = false; - if(!NRAgent.config.security.scan_schedule.always_sample_traces){ + if (!NRAgent.config.security.scan_schedule.always_sample_traces) { wsClient.initialize(); } - else{ + else { wsClient.obeyReconnect(); } Agent.getAgent().status.setStatus('connecting'); From b615f14941bbe07be076ce2b0b48c6c606cee5c3 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Tue, 8 Oct 2024 16:21:48 +0530 Subject: [PATCH 44/50] fix for schedule with duration --- lib/nr-security-agent/index.js | 2 +- lib/nr-security-agent/lib/core/commonUtils.js | 12 ++++++++---- .../websocket/response/fuzz-request-handler.js | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/nr-security-agent/index.js b/lib/nr-security-agent/index.js index 7753822e..85ed6c4d 100644 --- a/lib/nr-security-agent/index.js +++ b/lib/nr-security-agent/index.js @@ -134,7 +134,7 @@ function initialize() { if (delay > 0) { logger.debug("IAST delay is set to:", delay); - logger.info("Security Agent scan time is set to:", commonUtils.getScheduledScanTime(delay)) + logger.info("Security Agent delay scan time is set to:", commonUtils.getScheduledScanTime(delay)) Agent.getAgent().delayed = true; setTimeout(() => { Agent.getAgent().delayed = false; diff --git a/lib/nr-security-agent/lib/core/commonUtils.js b/lib/nr-security-agent/lib/core/commonUtils.js index 8645c358..94b66910 100644 --- a/lib/nr-security-agent/lib/core/commonUtils.js +++ b/lib/nr-security-agent/lib/core/commonUtils.js @@ -451,9 +451,13 @@ function listSkipDetectionCategory() { function refreshAgent() { const { Agent } = require('./agent'); - const wsClient = Agent.getAgent().client; - Agent.getAgent().status.setStatus('connecting'); - wsClient.obeyReconnect(); + if (Agent.getAgent().status.getStatus() == 'disabled' || Agent.getAgent().delayed) { + Agent.getAgent().delayed = false; + const wsClient = Agent.getAgent().client; + Agent.getAgent().status.setStatus('connecting'); + wsClient.obeyReconnect(); + honourDurationConfiguration(); + } } function executeCronSchedule() { @@ -553,7 +557,7 @@ function honourCronExpression() { schedule = schedule.replace(/\?/g, '*'); honourCronFlag = true; Agent.getAgent().delayed = true; - logger.info("Security Agent scan time is set to:", getScheduledScanTime(Math.ceil(cron.timeout(schedule) / 60000))) + logger.info("Security Agent scheduled time is set to:", getScheduledScanTime(Math.floor(cron.timeout(schedule) / 60000))) setTimeout(() => { Agent.getAgent().delayed = false; if (!NRAgent.config.security.scan_schedule.always_sample_traces) { diff --git a/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js b/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js index bd84123f..1b5e7254 100644 --- a/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js +++ b/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js @@ -47,7 +47,7 @@ function startIASTSchedular() { if (isNaN(delay) || delay < 0) { delay = 0; } - logger.debug("IAST data pull request is scheduled at %s", require('../../../commonUtils').getScheduledScanTime(delay)) + // logger.debug("IAST data pull request is scheduled at %s", require('../../../commonUtils').getScheduledScanTime(delay)) } if (!Agent.getAgent().delayed) { Agent.getAgent().client.dispatcher(IASTUtil.generateIASTDataRequest()); From 3b99d403c3ccc2682423cc71846539ec6f4eed9c Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Tue, 8 Oct 2024 16:27:57 +0530 Subject: [PATCH 45/50] fix for schedule with duration --- lib/nr-security-agent/lib/core/commonUtils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/nr-security-agent/lib/core/commonUtils.js b/lib/nr-security-agent/lib/core/commonUtils.js index 94b66910..b52bee32 100644 --- a/lib/nr-security-agent/lib/core/commonUtils.js +++ b/lib/nr-security-agent/lib/core/commonUtils.js @@ -569,6 +569,7 @@ function honourCronExpression() { Agent.getAgent().status.setStatus('connecting'); Agent.setNRAgent(NRAgent); logger.info("Security Agent is running with config:", JSON.stringify(NRAgent.config.security)); + honourDurationConfiguration(); executeCronSchedule(); }, cron.timeout(schedule)); } catch (error) { From 0373daa255a03955120d73c3b8c848b438740d8c Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Tue, 8 Oct 2024 17:55:59 +0530 Subject: [PATCH 46/50] fix for delay as priority over schedule --- lib/nr-security-agent/index.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/nr-security-agent/index.js b/lib/nr-security-agent/index.js index 85ed6c4d..d45ba395 100644 --- a/lib/nr-security-agent/index.js +++ b/lib/nr-security-agent/index.js @@ -143,20 +143,23 @@ function initialize() { commonUtils.honourDurationConfiguration(); }, delay * 60000); } - let tempDelay = delay; + logger.info("Security Agent is running with config:", JSON.stringify(NRAgent.config.security)); if (allowSampling) { - tempDelay = 0; + wsClient.initialize(); + Agent.getAgent().status.setStatus('connecting'); + Agent.setNRAgent(NRAgent); } setTimeout(() => { if (commonUtils.honourCronExpression() && !allowSampling) { return; } commonUtils.honourDurationConfiguration(); - wsClient.initialize(); - Agent.getAgent().status.setStatus('connecting'); - Agent.setNRAgent(NRAgent); - logger.info("Security Agent is running with config:", JSON.stringify(NRAgent.config.security)); - }, tempDelay * 60000); + if (!allowSampling) { + wsClient.initialize(); + Agent.getAgent().status.setStatus('connecting'); + Agent.setNRAgent(NRAgent); + } + }, delay * 60000); } else { logger.warn("security.enabled flag is set to false"); From d82f1ce890ba973a08dead4077567dc684adabb9 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Tue, 8 Oct 2024 18:44:46 +0530 Subject: [PATCH 47/50] minor fix for dual calling of durationConfig --- lib/nr-security-agent/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/nr-security-agent/index.js b/lib/nr-security-agent/index.js index d45ba395..d6487658 100644 --- a/lib/nr-security-agent/index.js +++ b/lib/nr-security-agent/index.js @@ -153,7 +153,6 @@ function initialize() { if (commonUtils.honourCronExpression() && !allowSampling) { return; } - commonUtils.honourDurationConfiguration(); if (!allowSampling) { wsClient.initialize(); Agent.getAgent().status.setStatus('connecting'); From 1f7641961629376fe56c6a5c296287d3599ae864 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Tue, 8 Oct 2024 22:10:14 +0530 Subject: [PATCH 48/50] code refactoring --- lib/nr-security-agent/index.js | 20 ++++------ lib/nr-security-agent/lib/core/commonUtils.js | 39 +------------------ 2 files changed, 10 insertions(+), 49 deletions(-) diff --git a/lib/nr-security-agent/index.js b/lib/nr-security-agent/index.js index d6487658..ff60af74 100644 --- a/lib/nr-security-agent/index.js +++ b/lib/nr-security-agent/index.js @@ -132,15 +132,20 @@ function initialize() { NRAgent.config.security.scan_schedule.delay = delay; const allowSampling = NRAgent.config.security.scan_schedule.always_sample_traces; - if (delay > 0) { + if (delay >= 0) { logger.debug("IAST delay is set to:", delay); logger.info("Security Agent delay scan time is set to:", commonUtils.getScheduledScanTime(delay)) Agent.getAgent().delayed = true; setTimeout(() => { Agent.getAgent().delayed = false; logger.info("IAST scanning delay of %s minutes over", delay); - commonUtils.executeCronSchedule(); commonUtils.honourDurationConfiguration(); + commonUtils.executeCronSchedule(); + if (!allowSampling) { + wsClient.initialize(); + Agent.getAgent().status.setStatus('connecting'); + Agent.setNRAgent(NRAgent); + } }, delay * 60000); } logger.info("Security Agent is running with config:", JSON.stringify(NRAgent.config.security)); @@ -149,16 +154,7 @@ function initialize() { Agent.getAgent().status.setStatus('connecting'); Agent.setNRAgent(NRAgent); } - setTimeout(() => { - if (commonUtils.honourCronExpression() && !allowSampling) { - return; - } - if (!allowSampling) { - wsClient.initialize(); - Agent.getAgent().status.setStatus('connecting'); - Agent.setNRAgent(NRAgent); - } - }, delay * 60000); + } else { logger.warn("security.enabled flag is set to false"); diff --git a/lib/nr-security-agent/lib/core/commonUtils.js b/lib/nr-security-agent/lib/core/commonUtils.js index b52bee32..441de320 100644 --- a/lib/nr-security-agent/lib/core/commonUtils.js +++ b/lib/nr-security-agent/lib/core/commonUtils.js @@ -468,10 +468,12 @@ function executeCronSchedule() { } logger.debug("Schedule config is set to:", schedule); schedule = schedule.replace(/\?/g, '*'); + logger.info("Security Agent scheduled time is set to:", getScheduledScanTime(Math.ceil(cron.timeout(schedule) / 60000))) const job = new cron.CronJob( schedule, // cronTime function () { logger.debug('Cron schedule invoked'); + logger.info("Security Agent scheduled time is set to:", getScheduledScanTime(Math.ceil(cron.timeout(schedule) / 60000))) refreshAgent() }, // onTick null, // onComplete @@ -543,42 +545,6 @@ function shutDownAgent() { logger.warn("Security Agent status is disabled"); } -function honourCronExpression() { - let honourCronFlag = false; - try { - const { Agent } = require('./agent'); - const wsClient = Agent.getAgent().client; - let schedule = NRAgent.config.security.scan_schedule.schedule; - if (lodash.isEmpty(schedule)) { - return; - } - logger.debug("Schedule config is set to:", schedule); - - schedule = schedule.replace(/\?/g, '*'); - honourCronFlag = true; - Agent.getAgent().delayed = true; - logger.info("Security Agent scheduled time is set to:", getScheduledScanTime(Math.floor(cron.timeout(schedule) / 60000))) - setTimeout(() => { - Agent.getAgent().delayed = false; - if (!NRAgent.config.security.scan_schedule.always_sample_traces) { - wsClient.initialize(); - } - else { - wsClient.obeyReconnect(); - } - Agent.getAgent().status.setStatus('connecting'); - Agent.setNRAgent(NRAgent); - logger.info("Security Agent is running with config:", JSON.stringify(NRAgent.config.security)); - honourDurationConfiguration(); - executeCronSchedule(); - }, cron.timeout(schedule)); - } catch (error) { - logger.debug("Error while processing cron expression:", error); - return false; - } - return honourCronFlag; - -} @@ -611,5 +577,4 @@ module.exports = { honourDurationConfiguration, sendErrorToErrorInbox, getScheduledScanTime, - honourCronExpression }; \ No newline at end of file From 152da079443fcb36f7d855a669070bb8f3e849d8 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Wed, 9 Oct 2024 12:56:03 +0530 Subject: [PATCH 49/50] updated logic to include query param --- lib/instrumentation-security/core/request-manager.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/instrumentation-security/core/request-manager.js b/lib/instrumentation-security/core/request-manager.js index 8852f3e5..8be02bdd 100644 --- a/lib/instrumentation-security/core/request-manager.js +++ b/lib/instrumentation-security/core/request-manager.js @@ -30,7 +30,8 @@ function setRequest(id, requestData) { requestMap.set(id, requestData); try { const stringToMatch = requestData.url; - const filteredString = stringToMatch.split('?')[0]; + // const filteredString = stringToMatch.split('?')[0]; + const filteredString = stringToMatch; let isRegexMatchestoURL = false; for (let index = 0; index < regexPatterns.length; index++) { const regex = new RegExp(regexPatterns[index], 'gm'); From 15cfbacec988a77af347a5d3e6ea7b0b8fa2eed8 Mon Sep 17 00:00:00 2001 From: Sumit Suthar Date: Wed, 9 Oct 2024 13:07:31 +0530 Subject: [PATCH 50/50] update log for exclude API --- lib/instrumentation-security/core/request-manager.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/instrumentation-security/core/request-manager.js b/lib/instrumentation-security/core/request-manager.js index 8be02bdd..1b23a60f 100644 --- a/lib/instrumentation-security/core/request-manager.js +++ b/lib/instrumentation-security/core/request-manager.js @@ -24,14 +24,12 @@ function getRequestFromId(id) { * @param {*} requestData */ function setRequest(id, requestData) { - if (API.getSecAgent().status.getStatus() != 'active') { - return; - } + requestMap.set(id, requestData); try { const stringToMatch = requestData.url; // const filteredString = stringToMatch.split('?')[0]; - const filteredString = stringToMatch; + const filteredString = stringToMatch; let isRegexMatchestoURL = false; for (let index = 0; index < regexPatterns.length; index++) { const regex = new RegExp(regexPatterns[index], 'gm'); @@ -45,7 +43,9 @@ function setRequest(id, requestData) { } if (isRegexMatchestoURL) { requestMap.delete(id); - logger.debug("Excluding URL %s from IAST processing due to ignore API setting", filteredString); + if (API.getSecAgent().status.getStatus() !== 'disabled') { + logger.debug("Excluding URL %s from IAST processing due to ignore API setting", filteredString); + } } } catch (error) { logger.debug("Error while processing API regex for restriction", error);