@newrelic/security-agent 1.5.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/THIRD_PARTY_NOTICES.md +48 -1
  3. package/lib/instrumentation-security/core/constants.js +8 -1
  4. package/lib/instrumentation-security/core/event-constants.js +5 -3
  5. package/lib/instrumentation-security/core/request-manager.js +40 -8
  6. package/lib/instrumentation-security/core/sec-utils.js +6 -5
  7. package/lib/instrumentation-security/hooks/director/nr-director.js +6 -6
  8. package/lib/instrumentation-security/hooks/express/nr-express.js +11 -8
  9. package/lib/instrumentation-security/hooks/fastify/nr-fastify.js +6 -6
  10. package/lib/instrumentation-security/hooks/fs/nr-fs.js +11 -28
  11. package/lib/instrumentation-security/hooks/grpc-js/nr-grpc.js +4 -4
  12. package/lib/instrumentation-security/hooks/hapi/nr-hapi.js +7 -7
  13. package/lib/instrumentation-security/hooks/http/nr-http.js +137 -13
  14. package/lib/instrumentation-security/hooks/koa/@koa/nr-@koa-router.js +5 -5
  15. package/lib/instrumentation-security/hooks/ldap/nr-ldap.js +4 -0
  16. package/lib/instrumentation-security/hooks/mongodb/nr-mongodb.js +4 -0
  17. package/lib/instrumentation-security/hooks/mysql/nr-mysql.js +4 -0
  18. package/lib/instrumentation-security/hooks/native/nr-childProcess.js +4 -0
  19. package/lib/instrumentation-security/hooks/postgres/nr-postgres.js +4 -0
  20. package/lib/instrumentation-security/hooks/restify/nr-restify.js +7 -7
  21. package/lib/instrumentation-security/hooks/undici/nr-undici.js +4 -0
  22. package/lib/instrumentation-security/hooks/xpath/nr-xpath.js +4 -0
  23. package/lib/nr-security-agent/index.js +38 -5
  24. package/lib/nr-security-agent/lib/core/Auth-headers.js +20 -0
  25. package/lib/nr-security-agent/lib/core/ExceptionReporting.js +1 -0
  26. package/lib/nr-security-agent/lib/core/Policy.js +0 -12
  27. package/lib/nr-security-agent/lib/core/agent.js +5 -1
  28. package/lib/nr-security-agent/lib/core/applicationinfo.js +2 -2
  29. package/lib/nr-security-agent/lib/core/commonUtils.js +141 -45
  30. package/lib/nr-security-agent/lib/core/connections/websocket/proxy-util.js +61 -0
  31. package/lib/nr-security-agent/lib/core/connections/websocket/response/IASTUtils.js +34 -6
  32. package/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js +36 -6
  33. package/lib/nr-security-agent/lib/core/connections/websocket/response/startup-handshake-handler.js +5 -1
  34. package/lib/nr-security-agent/lib/core/connections/websocket/response/ws-reconnect.js +7 -4
  35. package/lib/nr-security-agent/lib/core/connections/websocket/websocket.js +32 -14
  36. package/lib/nr-security-agent/lib/core/event.js +2 -2
  37. package/lib/nr-security-agent/lib/core/health-check.js +8 -2
  38. package/lib/nr-security-agent/lib/core/sec-agent-constants.js +2 -3
  39. package/lib/nr-security-agent/lib/core/sec-util.js +40 -4
  40. package/lib/nr-security-agent/lib/core/websocket-client.js +35 -12
  41. package/lib/nr-security-api/index.js +47 -15
  42. package/package.json +10 -4
  43. package/lib/nr-security-agent/lib/core/statusUtils.js +0 -165
@@ -34,8 +34,8 @@ function BasicInfo() {
34
34
  this.policyVersion = (!lodash.isEmpty(policyManager.getInstance().data)) ? policyManager.getInstance().data.version : 'DEFAULT';
35
35
 
36
36
  if (NRAgent && NRAgent.config) {
37
- this.accountId = NRAgent.config.account_id;
38
- this.entityGuid = NRAgent.config.entity_guid;
37
+ this.appAccountId = NRAgent.config.account_id;
38
+ this.appEntityGuid = NRAgent.config.entity_guid;
39
39
  this.linkingMetadata = LinkingMetaData.getLinkingMetadata();
40
40
  this.linkingMetadata.agentRunId = NRAgent.config.run_id;
41
41
  }
@@ -14,7 +14,8 @@ const NODE_JS_LITERAL = 'Node.js:';
14
14
 
15
15
  let NODE_SERVER;
16
16
  let instance;
17
- let logger;
17
+ const logs = require('./logging');
18
+ const logger = logs.getLogger();
18
19
  const API = require('../../../nr-security-api');
19
20
  const NRAgent = API.getNRAgent();
20
21
 
@@ -35,6 +36,7 @@ module.exports.getInstance = function () {
35
36
  return instance;
36
37
  };
37
38
 
39
+
38
40
  /**
39
41
  * Creates a new HealthCheck object.
40
42
  *
@@ -46,7 +48,8 @@ function HC(info) {
46
48
  this.applicationUUID = info.applicationUUID;
47
49
  this.eventType = 'sec_health_check_lc';
48
50
  if (NRAgent && NRAgent.config) {
49
- this.entityGuid = NRAgent.config.entity_guid;
51
+ this.appEntityGuid = NRAgent.config.entity_guid;
52
+ this.appAccountId = NRAgent.config.account_id;
50
53
  }
51
54
  this.protectedServer = NODE_SERVER;
52
55
  this.eventDropCount = 0;
@@ -62,6 +65,9 @@ function HC(info) {
62
65
  this.iastEventStats = EventStats.getInstance();
63
66
  this.raspEventStats = EventStats.getInstance();
64
67
  this.exitEventStats = EventStats.getInstance();
68
+ this.scanStartTime = require('./commonUtils').scanStartTime;
69
+ this.trafficStartedTime = require('./commonUtils').trafficStartedTime;
70
+ this.procStartTime = Date.now() - Math.floor(process.uptime() * 1000);
65
71
 
66
72
 
67
73
  /**
@@ -24,15 +24,14 @@ module.exports = {
24
24
  CSEC_HOME_TMP: `${CSEC_HOME}${sep}nr-security-home${sep}tmp${sep}language-agent${sep}${process.env.applicationUUID}`,
25
25
  AGENT_START_TIME: agentStartTime,
26
26
  FRAMEWORK: '',
27
- STATUS_LOG_FILE: `${CSEC_HOME}${sep}nr-security-home${sep}logs${sep}snapshots${sep}node-security-collector-status-${process.env.applicationUUID}.log`,
28
-
27
+
29
28
  DB_LIST: {
30
29
  MYSQL: 'MYSQL',
31
30
  MYSQL2: 'MYSQL',
32
31
  POSTGRES: 'POSTGRES',
33
32
  MONGODB: 'MONGODB',
34
33
  ORACLEDB: 'ORACLEDB',
35
- MSSQL: 'MSSQL',
34
+ MSSQL: 'MSSQL',
36
35
  SQLITE3: 'SQLITE3'
37
36
  },
38
37
  SERVER_COMMAND: {
@@ -9,16 +9,17 @@ const { SecEvent } = require('./event');
9
9
  const logs = require('./logging');
10
10
  const { Agent } = require('./agent');
11
11
  const shaUtil = require('./sha-size-util');
12
- const { LOG_MESSAGES, NR_CSEC_FUZZ_REQUEST_ID, COLON, VULNERABLE, EXITEVENT, EMPTY_STR, RASP, SEVERE, HYPHEN } = require('./sec-agent-constants');
12
+ const { NR_CSEC_FUZZ_REQUEST_ID, COLON, VULNERABLE, EXITEVENT, EMPTY_STR, SEVERE, HYPHEN } = require('./sec-agent-constants');
13
13
  const API = require('../../../nr-security-api');
14
14
  const NRAgent = API.getNRAgent();
15
15
  const HC = require('./health-check');
16
16
  const LogMessage = require('./LogMessage');
17
17
  const commonUtils = require('./commonUtils');
18
18
 
19
- const statusUtils = require('./statusUtils');
19
+ const appInfo = require('./applicationinfo').getInstance();
20
20
 
21
21
  let firstEventSent = false;
22
+ let appDir = EMPTY_STR;
22
23
 
23
24
  const events = require('events');
24
25
  const eventEmitter = undefined;
@@ -27,6 +28,20 @@ let logger = logs.getLogger();
27
28
  const initLogger = logs.getInitLogger();
28
29
 
29
30
  const NODE_SER = 'node-serialize/lib/serialize.js';
31
+ const SECURE_COOKIE = 'SECURE_COOKIE';
32
+
33
+ const insecureSettingApiIdSet = new Set();
34
+
35
+ /**
36
+ * Utility to remove insecureSettingAPIIds after 30 mins from the set.
37
+ * @param {*} entry
38
+ */
39
+ function addInsecureSettingApiId(entry) {
40
+ insecureSettingApiIdSet.add(entry);
41
+ setTimeout(() => {
42
+ insecureSettingApiIdSet.delete(entry);
43
+ }, 30 * 60 * 1000);
44
+ }
30
45
 
31
46
  function getSecEventEmitter() {
32
47
  if (eventEmitter) {
@@ -68,6 +83,7 @@ const sleep = (timeout) => new Promise((resolve) => {
68
83
  function generateSecEvent(securityMetadata) {
69
84
  const traceObject = securityMetadata.traceObject;
70
85
  const request = securityMetadata.request;
86
+ let appServerInfo = {};
71
87
 
72
88
  if (request && request.headers[NR_CSEC_FUZZ_REQUEST_ID]) {
73
89
  HC.getInstance().iastEventStats.processed++;
@@ -75,6 +91,16 @@ function generateSecEvent(securityMetadata) {
75
91
  else {
76
92
  HC.getInstance().raspEventStats.processed++;
77
93
  }
94
+
95
+ try {
96
+ appDir = appInfo.serverInfo.deployedApplications[0].deployedPath;
97
+ appServerInfo.applicationDirectory = appDir;
98
+ appServerInfo.serverBaseDirectory = appDir;
99
+ appServerInfo.connectionConfiguration = { [request.serverPort]: request.protocol };
100
+
101
+ } catch (error) {
102
+ }
103
+
78
104
  try {
79
105
  let stakTrace = traceObject.stacktrace;
80
106
  let uri = EMPTY_STR;
@@ -84,8 +110,15 @@ function generateSecEvent(securityMetadata) {
84
110
 
85
111
  let apiId = shaUtil.getSHA256ForData(traceObject.stacktrace.join('|') + uri);
86
112
  apiId = securityMetadata.eventType + HYPHEN + apiId;
113
+ if (securityMetadata.eventType == SECURE_COOKIE) {
114
+ if (insecureSettingApiIdSet.has(apiId)) {
115
+ return;
116
+ }
117
+ addInsecureSettingApiId(apiId);
118
+ }
87
119
  const agentModule = Agent.getAgent();
88
120
  const metaData = {};
121
+ metaData.appServerInfo = appServerInfo;
89
122
  if (traceObject.sourceDetails && traceObject.sourceDetails.evalObj) {
90
123
  metaData.triggerViaRCI = true;
91
124
  metaData.rciMethodsCalls = traceObject.sourceDetails.evalObj.invokedCalls;
@@ -101,10 +134,10 @@ function generateSecEvent(securityMetadata) {
101
134
  const isAPIBlocked = false;
102
135
  const event = new SecEvent(traceObject.sourceDetails.fileName, traceObject.sourceDetails.funcName, traceObject.sourceDetails.lineNumber, securityMetadata.interceptedArgs, securityMetadata.executionId, agentModule.applicationInfo, securityMetadata.request, securityMetadata.eventType, traceObject.sourceDetails.source, securityMetadata.eventCategory, metaData, stakTrace, apiId, isAPIBlocked);
103
136
  event.metaData.isClientDetectedFromXFF = isClientDetectedFromXFF;
137
+ event.metaData.skipScanParameters = NRAgent.config.security.exclude_from_iast_scan.http_request_parameters;
104
138
  event.httpRequest.route = uri;
105
139
  return event;
106
140
  } catch (e) {
107
- statusUtils.addErrortoBuffer(e);
108
141
  logger.error("Error in generating event:", e);
109
142
 
110
143
  const logMessage = new LogMessage.logMessage(SEVERE, 'Error while generating event', __filename, e);
@@ -159,9 +192,12 @@ function generateExitEvent(secEvent) {
159
192
 
160
193
  function sendEvent(secEvent) {
161
194
  const agentModule = Agent.getAgent();
162
- if (agentModule.status.getStatus() != 'connecting' && NRAgent.config.security.enabled) {
195
+ if (agentModule.status.getStatus() != 'connecting' && NRAgent.config.security.enabled && agentModule.status.getStatus() == 'active') {
163
196
  agentModule.client.dispatcher(secEvent);
164
197
  if (!firstEventSent && agentModule.status.getStatus() === 'active') {
198
+ if(commonUtils.trafficStartedTime == 0){
199
+ commonUtils.trafficStartedTime = Date.now();
200
+ }
165
201
  initLogger.info("[STEP-8] => First event sent for validation. Security Agent started successfully", JSON.stringify(secEvent));
166
202
  firstEventSent = true;
167
203
  }
@@ -25,7 +25,6 @@ const {
25
25
  } = require('./connections/websocket');
26
26
  const { HC_INTERVAL_MS } = require('../../resources/config');
27
27
  const { LOG_DIR, EXITEVENT, JSON_NAME } = require('./sec-agent-constants');
28
- const statusUtils = require('./statusUtils');
29
28
  const njsAgentConstants = require('./sec-agent-constants');
30
29
 
31
30
  let wsInstance;
@@ -71,22 +70,22 @@ const initialize = function () {
71
70
  setInterval(sendHC, HC_INTERVAL_MS);
72
71
  sendHC();
73
72
  try {
74
- let apiEndpoints = require('../../../instrumentation-security/core/route-manager').getAllAPIEndPoints();
75
- let data = require('./apiEndpoints').APIEndPoint(apiEndpoints);
76
- logger.debug("All API end points of the application is:",JSON.stringify(data));
73
+ let apiEndpoints = require('../../../instrumentation-security/core/route-manager').getAllAPIEndPoints();
74
+ let data = require('./apiEndpoints').APIEndPoint(apiEndpoints);
75
+ logger.debug("All API end points of the application is:", JSON.stringify(data));
77
76
  getDispatcherAndSendEvent(data);
78
77
  require('../core/ExceptionReporting').startExceptionSendingSchedular();
79
78
  } catch (error) {
80
- logger.debug("Error while processing API endpoints",error);
79
+ logger.debug("Error while processing API endpoints", error);
81
80
  }
82
-
81
+
83
82
  try {
84
83
  const framework = NRAgent.environment.get('Framework')[0];
85
84
  const dispatcher = NRAgent.environment.get('Dispatcher')[0];
86
85
  const logMessage = new LogMessage.logMessage("INFO", `Detected framework: ${framework} and dispatcher: ${dispatcher}`, __filename, null);
87
86
  commonUtils.addLogEventtoBuffer(logMessage);
88
87
  } catch (error) {
89
- logger.debug("Error while extracting data from APM environment",error);
88
+ logger.debug("Error while extracting data from APM environment", error);
90
89
  }
91
90
  }, 20000);
92
91
 
@@ -104,13 +103,26 @@ function initializeInMainThread() {
104
103
  const validatorService = commonUtils.getValidatorServiceEndpointURL();
105
104
  wsInstance = new SecWebSocket(validatorService, {}, logger);
106
105
  dispatcher = function dispatcher(message) {
107
- wsInstance.dispatch(message);
106
+ if (Agent.getAgent().status.getStatus() == 'active') {
107
+ wsInstance.dispatch(message);
108
+ }
108
109
  };
109
110
  } else {
110
111
  return wsInstance;
111
112
  }
112
113
  }
113
114
 
115
+ function getTestIdentifier() {
116
+ try {
117
+ let authHeaders = require('./Auth-headers').getInstance();
118
+ let testIdentifer = authHeaders['NR-CSEC-IAST-TEST-IDENTIFIER'] ? authHeaders['NR-CSEC-IAST-TEST-IDENTIFIER'] : '';
119
+ return testIdentifer
120
+ } catch (error) {
121
+ logger.debug("unable to get test identifier", error);
122
+ }
123
+
124
+ }
125
+
114
126
  /**
115
127
  * Sends Agent HelthCheck to Validator.
116
128
  */
@@ -120,6 +132,10 @@ const sendHC = async function () {
120
132
  json = JSON.parse(json);
121
133
  json.policyVersion = applicationInfo.policyVersion;
122
134
  json.entityGuid = applicationInfo.entityGuid;
135
+ if (NRAgent && NRAgent.config) {
136
+ json.appEntityGuid = NRAgent.config.entity_guid;
137
+ json.appAccountId = NRAgent.config.account_id;
138
+ }
123
139
 
124
140
  try {
125
141
  json.stats = await commonUtils.getHCStats();
@@ -131,7 +147,6 @@ const sendHC = async function () {
131
147
  json.serviceStatus.websocket = commonUtils.getWSHealthStatus();
132
148
  json.serviceStatus.logWriter = await commonUtils.isLogAccessible(`${LOG_DIR}node-security-collector.log`);
133
149
  json.serviceStatus.initLogWriter = await commonUtils.isLogAccessible(`${LOG_DIR}node-security-collector-init.log`);
134
- json.serviceStatus.statusLogWriter = await commonUtils.isLogAccessible(njsAgentConstants.STATUS_LOG_FILE);
135
150
  json.serviceStatus.agentActiveStat = commonUtils.isAgentActiveState();
136
151
  json.serviceStatus.iastRestClient = commonUtils.iastRestClientStatus();
137
152
 
@@ -141,15 +156,18 @@ const sendHC = async function () {
141
156
  json.eventSendRejectionCount = json.eventRejectionCount;
142
157
  json.eventSendErrorCount = json.eventProcessingErrorCount;
143
158
 
159
+ json.scanStartTime = commonUtils.scanStartTime;
160
+ json.trafficStartedTime = commonUtils.trafficStartedTime;
161
+ json.iastTestIdentifer = getTestIdentifier();
162
+
144
163
  hc.getInstance().resetDropCount();
145
164
  hc.getInstance().resetProcessedCount();
146
165
  hc.getInstance().resetEventSentCount();
147
166
  hc.getInstance().resetHttpRequestCount();
148
167
  hc.getInstance().resetEventStats();
149
168
 
169
+
150
170
  logger.info('Health Check Status:', JSON.stringify(json));
151
- statusUtils.addHCtoBuffer(json);
152
- statusUtils.writeSnapshot();
153
171
  getDispatcherAndSendEvent(json);
154
172
  }
155
173
  };
@@ -190,9 +208,14 @@ function obeyReconnect() {
190
208
  wsInstance.obeyReconnect();
191
209
  }
192
210
 
211
+ function closeWS() {
212
+ wsInstance.closeWS();
213
+ }
214
+
193
215
  module.exports = {
194
216
  initialize,
195
217
  write: sendEvent,
196
218
  dispatcher: getDispatcherAndSendEvent,
197
- obeyReconnect
219
+ obeyReconnect,
220
+ closeWS
198
221
  };
@@ -10,7 +10,39 @@ let NRAgent;
10
10
  *
11
11
  * @returns NewRelic Agent instance
12
12
  */
13
- function getNRAgent(){
13
+ function getNRAgent() {
14
+ if (NRAgent && NRAgent.config && !NRAgent.config.security.scan_schedule) {
15
+ NRAgent.config.security.scan_schedule = {};
16
+ NRAgent.config.security.scan_schedule.delay = 0;
17
+ NRAgent.config.security.scan_schedule.duration = 0;
18
+ NRAgent.config.security.scan_schedule.schedule = '';
19
+ NRAgent.config.security.scan_schedule.always_sample_traces = false;
20
+
21
+ }
22
+ if ( NRAgent && NRAgent.config && !NRAgent.config.security.scan_controllers) {
23
+ NRAgent.config.security.scan_controllers = {};
24
+ NRAgent.config.security.scan_controllers.iast_scan_request_rate_limit = 3600;
25
+ NRAgent.config.security.scan_controllers.scan_instance_count = 0;
26
+ }
27
+ if (NRAgent && NRAgent.config && !NRAgent.config.security.exclude_from_iast_scan) {
28
+ NRAgent.config.security.exclude_from_iast_scan = {};
29
+ NRAgent.config.security.exclude_from_iast_scan.api = [];
30
+ NRAgent.config.security.exclude_from_iast_scan.http_request_parameters = {};
31
+ NRAgent.config.security.exclude_from_iast_scan.http_request_parameters.header = [];
32
+ NRAgent.config.security.exclude_from_iast_scan.http_request_parameters.query = [];
33
+ NRAgent.config.security.exclude_from_iast_scan.http_request_parameters.body = [];
34
+ NRAgent.config.security.exclude_from_iast_scan.iast_detection_category = {};
35
+ NRAgent.config.security.exclude_from_iast_scan.iast_detection_category.insecure_settings = false;
36
+ NRAgent.config.security.exclude_from_iast_scan.iast_detection_category.invalid_file_access = false;
37
+ NRAgent.config.security.exclude_from_iast_scan.iast_detection_category.sql_injection = false;
38
+ NRAgent.config.security.exclude_from_iast_scan.iast_detection_category.nosql_injection = false;
39
+ NRAgent.config.security.exclude_from_iast_scan.iast_detection_category.ldap_injection = false;
40
+ NRAgent.config.security.exclude_from_iast_scan.iast_detection_category.javascript_injection = false;
41
+ NRAgent.config.security.exclude_from_iast_scan.iast_detection_category.command_injection = false;
42
+ NRAgent.config.security.exclude_from_iast_scan.iast_detection_category.xpath_injection = false;
43
+ NRAgent.config.security.exclude_from_iast_scan.iast_detection_category.ssrf = false;
44
+ NRAgent.config.security.exclude_from_iast_scan.iast_detection_category.rxss = false;
45
+ }
14
46
  return NRAgent;
15
47
  }
16
48
 
@@ -18,7 +50,7 @@ function getNRAgent(){
18
50
  * API to set newrelic agent object.
19
51
  * @param {*} agent
20
52
  */
21
- function setNRAgent(agent){
53
+ function setNRAgent(agent) {
22
54
  NRAgent = agent;
23
55
  }
24
56
 
@@ -26,11 +58,11 @@ function setNRAgent(agent){
26
58
  * API to get security agent
27
59
  * @returns Security Agent instanace
28
60
  */
29
- function getSecAgent(){
61
+ function getSecAgent() {
30
62
  const Agent = require('../nr-security-agent/lib/core/agent').Agent;
31
63
  const csecAgent = Agent.getAgent();
32
- if(csecAgent){
33
- return csecAgent;
64
+ if (csecAgent) {
65
+ return csecAgent;
34
66
  }
35
67
  }
36
68
 
@@ -38,11 +70,11 @@ function getSecAgent(){
38
70
  * API to get status of security agent
39
71
  * @returns Security Agent status
40
72
  */
41
- function getSecAgentStatus(){
73
+ function getSecAgentStatus() {
42
74
  const Agent = require('../nr-security-agent/lib/core/agent').Agent;
43
- if(Agent.getAgent()){
75
+ if (Agent.getAgent()) {
44
76
  return Agent.getAgent().status.getStatus()
45
- }
77
+ }
46
78
  }
47
79
 
48
80
  /**
@@ -50,15 +82,15 @@ function getSecAgentStatus(){
50
82
  * @param {*} securityMetadata
51
83
  * @returns security event object
52
84
  */
53
- function generateSecEvent(securityMetadata){
54
- return require('../nr-security-agent/lib/core/sec-util').generateSecEvent(securityMetadata);
85
+ function generateSecEvent(securityMetadata) {
86
+ return require('../nr-security-agent/lib/core/sec-util').generateSecEvent(securityMetadata);
55
87
  }
56
88
 
57
89
  /**
58
90
  * API to send security event
59
91
  * @param {*} secEvent
60
92
  */
61
- function sendEvent(secEvent){
93
+ function sendEvent(secEvent) {
62
94
  require('../nr-security-agent/lib/core/sec-util').sendEvent(secEvent);
63
95
  }
64
96
 
@@ -66,7 +98,7 @@ function sendEvent(secEvent){
66
98
  * API to get logger instance
67
99
  * @returns
68
100
  */
69
- function getLogger(){
101
+ function getLogger() {
70
102
  return require('../nr-security-agent/lib/core/logging').getLogger();
71
103
  }
72
104
  /**
@@ -76,7 +108,7 @@ function getLogger(){
76
108
  * @param {*} responseHeaders
77
109
  * @returns
78
110
  */
79
- function checkForReflectedXSS(secRequest, responseBody, responseHeaders){
111
+ function checkForReflectedXSS(secRequest, responseBody, responseHeaders) {
80
112
  return require('../nr-security-agent/lib/core/xss-utils').checkForReflectedXSS(secRequest, responseBody, responseHeaders);
81
113
  }
82
114
 
@@ -84,7 +116,7 @@ function checkForReflectedXSS(secRequest, responseBody, responseHeaders){
84
116
  * API to get security agent policy
85
117
  * @returns security agent policy
86
118
  */
87
- function getPolicy(){
119
+ function getPolicy() {
88
120
  return require('../nr-security-agent/lib/core/Policy').getInstance();
89
121
  }
90
122
 
@@ -92,7 +124,7 @@ function getPolicy(){
92
124
  * API to generate Exit event
93
125
  * @param {*} event
94
126
  */
95
- function generateExitEvent(event){
127
+ function generateExitEvent(event) {
96
128
  require('../nr-security-agent/lib/core/sec-util').generateExitEvent(event);
97
129
  }
98
130
 
package/package.json CHANGED
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "@newrelic/security-agent",
3
- "version": "1.5.0",
3
+ "version": "2.1.0",
4
4
  "description": "New Relic Security Agent for Node.js",
5
5
  "main": "index.js",
6
- "jsonVersion": "1.2.3",
6
+ "jsonVersion": "1.2.9",
7
7
  "contributors": [
8
8
  {
9
9
  "name": "Sumit Suthar",
10
10
  "email": "ssuthar@newrelic.com",
11
- "web": "http://newrelic.com"
11
+ "web": "https://newrelic.com"
12
12
  },
13
13
  {
14
14
  "name": "Pratik Gunjetiya",
15
15
  "email": "pgunjetiya@newrelic.com",
16
- "web": "http://newrelic.com"
16
+ "web": "https://newrelic.com"
17
17
  }
18
18
  ],
19
19
  "scripts": {
@@ -28,6 +28,10 @@
28
28
  "New Relic Security Agent",
29
29
  "Node.js Application Security"
30
30
  ],
31
+ "engines": {
32
+ "node": ">=18",
33
+ "npm": ">=6.0.0"
34
+ },
31
35
  "author": "newrelic",
32
36
  "license": "New Relic Software License v1.0",
33
37
  "repository": {
@@ -38,10 +42,12 @@
38
42
  "axios": "^1.7.4",
39
43
  "check-disk-space": "^3.4.0",
40
44
  "content-type": "^1.0.5",
45
+ "cron": "^3.1.7",
41
46
  "fast-safe-stringify": "^2.1.1",
42
47
  "find-package-json": "^1.2.0",
43
48
  "hash.js": "^1.1.7",
44
49
  "html-entities": "^2.3.6",
50
+ "https-proxy-agent": "^7.0.4",
45
51
  "is-invalid-path": "^1.0.2",
46
52
  "js-yaml": "^4.1.0",
47
53
  "jsonschema": "^1.4.1",
@@ -1,165 +0,0 @@
1
- /*
2
- * Copyright 2023 New Relic Corporation. All rights reserved.
3
- * SPDX-License-Identifier: New Relic Software License v1.0
4
- */
5
-
6
- /* eslint-disable new-cap */
7
-
8
- const njsAgentConstants = require('./sec-agent-constants');
9
- const agentConfig = require('../../resources/config');
10
- const { AGENT_DIR } = agentConfig;
11
- const lodash = require('lodash');
12
-
13
- let errors = [];
14
-
15
- const ringBuffer = require('ringbufferjs');
16
- const bufferedHC = new ringBuffer(5);
17
- const bufferedErrors = new ringBuffer(5);
18
- const fs = require('fs');
19
- const util = require('util');
20
- let HC = [];
21
- let lastHC = {};
22
- const logs = require('./logging');
23
- const commonUtils = require('./commonUtils');
24
- const logger = logs.getLogger();
25
- const statusFile = njsAgentConstants.STATUS_LOG_FILE;
26
- const sep = require('path').sep;
27
-
28
- const statusTemplate = 'Snapshot timestamp: : %s\n' +
29
- `CSEC Agent start timestamp: ${njsAgentConstants.AGENT_START_TIME} with application uuid:${commonUtils.getUUID()}\n` +
30
- `CSEC_HOME: ${njsAgentConstants.CSEC_HOME}${sep}nr-security-home${sep}\n` +
31
- `Agent location: ${AGENT_DIR}\n` +
32
- `Using CSEC Agent for Node.js, Node version:${process.version}, PID:${process.pid}\n` +
33
- `Process title: ${process.title}\n` +
34
- `Process binary: ${process.execPath}\n` +
35
- 'Application location: %s\n' +
36
- `Current working directory: ${process.cwd()}\n` +
37
- `Agent mode: ${commonUtils.getCSECmode()}\n` +
38
- 'Application server: %s\n' +
39
- `Application Framework: %s\n` +
40
- `Websocket connection to Prevent Web: ${commonUtils.getValidatorServiceEndpointURL()}, Status: %s\n` +
41
- 'Instrumentation successful\n' +
42
- 'Tracking loaded modules in the application\n' +
43
- 'Policy applied successfully. Policy version is: %s\n' +
44
- 'Started Health Check for Agent\n' +
45
- 'Started Inbound and Outbound monitoring \n' +
46
- '\nProcess stats:\n%s\n' +
47
- '\nService stats:\n%s\n' +
48
- '\nLast 5 errors: \n%s\n' +
49
- '\nLast 5 Health Checks are:\n %s \n';
50
-
51
- /**
52
- * Utility to add hc in hc buffer
53
- * @param {*} healthCheck
54
- */
55
- function addHCtoBuffer(healthCheck) {
56
- try {
57
- bufferedHC.enq(healthCheck);
58
- lastHC = healthCheck;
59
- } catch (error) {
60
- logger.debug(error);
61
- }
62
- }
63
-
64
- /**
65
- * Utility to add error object in error buffer
66
- * @param {*} error
67
- */
68
- function addErrortoBuffer(error) {
69
- try {
70
- let errorObj = {
71
- 'error': error.stack
72
- }
73
- bufferedErrors.enq(errorObj);
74
- } catch (error) {
75
- logger.debug(error);
76
- }
77
- }
78
-
79
- /**
80
- * utility to format status template with dynamic values
81
- */
82
- function getFormattedData() {
83
- const Agent = require('./agent').Agent.getAgent();
84
- const appInfo = Agent.applicationInfo;
85
- const deployedApplications = appInfo && appInfo.serverInfo && appInfo.serverInfo.deployedApplications;
86
- const appLoc = deployedApplications[0].deployedPath;
87
- 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()));
88
- return formattedSnapshot;
89
- }
90
-
91
- /**
92
- * utility to write snapshot in snapshot file
93
- */
94
- function writeSnapshot() {
95
- const snapshot = getFormattedData();
96
- commonUtils.removeOlderSnapshots();
97
- fs.writeFile(statusFile, snapshot, { mode: 0o660 }, function (err) {
98
- if (err) {
99
- logger.debug(err.message);
100
- const LogMessage = require('./LogMessage');
101
- const logMessage = new LogMessage.logMessage("DEBUG", 'Error in creating snapshot file', __filename, err);
102
- commonUtils.addLogEventtoBuffer(logMessage);
103
- } else {
104
- logger.info('Snapshot updated to file: %s', statusFile);
105
- fs.chmod(statusFile, 0o660, (err) => {
106
- if (err) {
107
- addErrortoBuffer(err);
108
- }
109
- });
110
- }
111
- });
112
- }
113
- /**
114
- * return buffered error instance.
115
- */
116
- function getRingBufferedErrors() {
117
- return bufferedErrors;
118
- }
119
-
120
- /**
121
- * return buffered HC list without null, undefined
122
- */
123
- function getBufferedHC() {
124
- try {
125
- HC = lodash.compact(bufferedHC._elements);
126
- } catch (error) {
127
- logger.debug(error);
128
- }
129
-
130
- return HC;
131
- }
132
- /**
133
- * returns buffered error list without null, undefined
134
- */
135
- function getBufferedErrors() {
136
- try {
137
- errors = lodash.compact(bufferedErrors._elements);
138
- } catch (error) {
139
- logger.debug(error);
140
- }
141
- return errors;
142
- }
143
-
144
- /**
145
- * Utility to get key val pairs from json object
146
- * @param {*} jsonObject
147
- */
148
- function getKeyValPairs(jsonObject) {
149
- let statStr = njsAgentConstants.EMPTY_STR;
150
- for (const key in jsonObject) {
151
- statStr = statStr + key + ': ' + jsonObject[key] + '\n';
152
- }
153
- return statStr;
154
- }
155
-
156
- module.exports = {
157
- statusTemplate,
158
- addHCtoBuffer,
159
- getFormattedData,
160
- writeSnapshot,
161
- addErrortoBuffer,
162
- getRingBufferedErrors,
163
- getBufferedHC,
164
- getBufferedErrors
165
- };