@newrelic/security-agent 2.0.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +1 -1
  3. package/THIRD_PARTY_NOTICES.md +36 -6
  4. package/lib/instrumentation-security/core/request-manager.js +37 -7
  5. package/lib/instrumentation-security/core/sec-utils.js +5 -5
  6. package/lib/instrumentation-security/hooks/director/nr-director.js +6 -6
  7. package/lib/instrumentation-security/hooks/express/nr-express.js +11 -8
  8. package/lib/instrumentation-security/hooks/fastify/nr-fastify.js +6 -6
  9. package/lib/instrumentation-security/hooks/fs/nr-fs.js +6 -27
  10. package/lib/instrumentation-security/hooks/grpc-js/nr-grpc.js +4 -4
  11. package/lib/instrumentation-security/hooks/hapi/nr-hapi.js +7 -7
  12. package/lib/instrumentation-security/hooks/http/nr-http.js +15 -9
  13. package/lib/instrumentation-security/hooks/koa/@koa/nr-@koa-router.js +5 -5
  14. package/lib/instrumentation-security/hooks/ldap/nr-ldap.js +4 -0
  15. package/lib/instrumentation-security/hooks/mongodb/nr-mongodb.js +4 -0
  16. package/lib/instrumentation-security/hooks/mysql/nr-mysql.js +4 -0
  17. package/lib/instrumentation-security/hooks/native/nr-childProcess.js +4 -0
  18. package/lib/instrumentation-security/hooks/postgres/nr-postgres.js +4 -0
  19. package/lib/instrumentation-security/hooks/restify/nr-restify.js +7 -7
  20. package/lib/instrumentation-security/hooks/undici/nr-undici.js +4 -0
  21. package/lib/instrumentation-security/hooks/xpath/nr-xpath.js +4 -0
  22. package/lib/nr-security-agent/index.js +38 -5
  23. package/lib/nr-security-agent/lib/core/Auth-headers.js +19 -0
  24. package/lib/nr-security-agent/lib/core/ExceptionReporting.js +1 -0
  25. package/lib/nr-security-agent/lib/core/agent.js +3 -0
  26. package/lib/nr-security-agent/lib/core/commonUtils.js +132 -4
  27. package/lib/nr-security-agent/lib/core/connections/websocket/response/IASTUtils.js +28 -2
  28. package/lib/nr-security-agent/lib/core/connections/websocket/response/fuzz-request-handler.js +36 -4
  29. package/lib/nr-security-agent/lib/core/connections/websocket/response/startup-handshake-handler.js +5 -1
  30. package/lib/nr-security-agent/lib/core/connections/websocket/response/ws-reconnect.js +7 -4
  31. package/lib/nr-security-agent/lib/core/connections/websocket/websocket.js +17 -2
  32. package/lib/nr-security-agent/lib/core/health-check.js +6 -1
  33. package/lib/nr-security-agent/lib/core/sec-util.js +5 -1
  34. package/lib/nr-security-agent/lib/core/websocket-client.js +31 -8
  35. package/lib/nr-security-api/index.js +47 -15
  36. package/package.json +3 -2
@@ -66,17 +66,17 @@ function initialize(shim, mod, moduleName) {
66
66
  * @param {*} req
67
67
  */
68
68
  function extractParams(shim, req) {
69
- const segment = shim.getActiveSegment();
70
- if (segment && segment.transaction) {
69
+ const transaction = shim.tracer.getTransaction();
70
+ if (transaction) {
71
71
 
72
- let request = requestManager.getRequestFromId(segment.transaction.id);
72
+ let request = requestManager.getRequestFromId(transaction.id);
73
73
  if (req.params && request) {
74
74
  try {
75
75
  Object.keys(req.params).forEach(function (key) {
76
76
  if (req.params[key]) {
77
77
  if (!request.parameterMap[key]) {
78
78
  request.parameterMap[key] = new Array(req.params[key].toString());
79
- requestManager.setRequest(segment.transaction.id, request);
79
+ requestManager.setRequest(transaction.id, request);
80
80
  }
81
81
  }
82
82
  });
@@ -91,7 +91,7 @@ function extractParams(shim, req) {
91
91
  Object.keys(query).forEach(function (key) {
92
92
  if (query[key]) {
93
93
  request.parameterMap[key] = new Array(query[key].toString());
94
- requestManager.setRequest(segment.transaction.id, request);
94
+ requestManager.setRequest(transaction.id, request);
95
95
  }
96
96
  });
97
97
  } catch (error) {
@@ -100,7 +100,7 @@ function extractParams(shim, req) {
100
100
  }
101
101
  if (req.route && req.route.path && request) {
102
102
  request.uri = req.route.path;
103
- requestManager.setRequest(segment.transaction.id, request);
103
+ requestManager.setRequest(transaction.id, request);
104
104
  }
105
105
  }
106
- }
106
+ }
@@ -24,6 +24,10 @@ const url = require('url');
24
24
  * @param {*} moduleName
25
25
  */
26
26
  function initialize(shim, mod, moduleName) {
27
+ if(API && API.getNRAgent() && API.getNRAgent().config.security.exclude_from_iast_scan.iast_detection_category.ssrf){
28
+ logger.warn('ssrf detection is disabled');
29
+ return;
30
+ }
27
31
  logger.info('Instrumenting ' + moduleName);
28
32
  fetchHook(shim, mod, "fetch");
29
33
  let util = shim.require('./lib/core/util');
@@ -19,6 +19,10 @@ const logger = API.getLogger();
19
19
  * @param {*} moduleName
20
20
  */
21
21
  function initialize(shim, mod, moduleName){
22
+ if(API && API.getNRAgent() && API.getNRAgent().config.security.exclude_from_iast_scan.iast_detection_category.xpath_injection){
23
+ logger.warn('xpath_injection detection is disabled');
24
+ return;
25
+ }
22
26
  logger.info('Instrumenting '+ moduleName)
23
27
 
24
28
  if(moduleName==='xpath'){
@@ -17,7 +17,7 @@ const njsAgentConstants = require('./lib/core/sec-agent-constants');
17
17
  const NRLogger = API.newrelic.shim.logger.child({ component: 'security-agent' });
18
18
  NRLogger.info("Starting New Relic Node.js Security Agent ");
19
19
  try {
20
- if (NRAgent.config.security.enabled){
20
+ if (NRAgent.config.security.enabled) {
21
21
  require('../instrumentation-security');
22
22
  }
23
23
  } catch (error) {
@@ -117,11 +117,44 @@ function initialize() {
117
117
  if (NRAgent) {
118
118
  NRAgent.on('started', () => {
119
119
  NRLogger.info("Started New Relic Node.js Security Agent");
120
+ logger.info('NR Agent started with agent_run_id:', NRAgent.config.run_id, NRAgent.config.account_id);
121
+ if (Agent.getAgent().status.getStatus() != 'connecting') {
122
+ Agent.getAgent().delayed = false;
123
+ wsClient.obeyReconnect();
124
+ return;
125
+ }
120
126
  if (NRAgent.config.security.enabled || !NRAgent.config.high_security) {
121
- wsClient.initialize();
122
- logger.info('NR Agent started with agent_run_id:', NRAgent.config.run_id, NRAgent.config.account_id);
123
- Agent.getAgent().status.setStatus('connecting');
124
- Agent.setNRAgent(NRAgent);
127
+ let delayFromConfig = parseInt(NRAgent.config.security.scan_schedule.delay);
128
+ let delay = delayFromConfig;
129
+ if (isNaN(delay) || delay < 0) {
130
+ delay = 0;
131
+ }
132
+ NRAgent.config.security.scan_schedule.delay = delay;
133
+ const allowSampling = NRAgent.config.security.scan_schedule.always_sample_traces;
134
+
135
+ if (delay >= 0) {
136
+ logger.debug("IAST delay is set to:", delay);
137
+ logger.info("Security Agent delay scan time is set to:", commonUtils.getScheduledScanTime(delay))
138
+ Agent.getAgent().delayed = true;
139
+ setTimeout(() => {
140
+ Agent.getAgent().delayed = false;
141
+ logger.info("IAST scanning delay of %s minutes over", delay);
142
+ commonUtils.honourDurationConfiguration();
143
+ commonUtils.executeCronSchedule();
144
+ if (!allowSampling) {
145
+ wsClient.initialize();
146
+ Agent.getAgent().status.setStatus('connecting');
147
+ Agent.setNRAgent(NRAgent);
148
+ }
149
+ }, delay * 60000);
150
+ }
151
+ logger.info("Security Agent is running with config:", JSON.stringify(NRAgent.config.security));
152
+ if (allowSampling) {
153
+ wsClient.initialize();
154
+ Agent.getAgent().status.setStatus('connecting');
155
+ Agent.setNRAgent(NRAgent);
156
+ }
157
+
125
158
  }
126
159
  else {
127
160
  logger.warn("security.enabled flag is set to false");
@@ -11,6 +11,7 @@ const logger = logs.getLogger();
11
11
  const initLogger = logs.getInitLogger();
12
12
  const LinkingMetaData = require('./LinkingMetadata');
13
13
  const LogMessage = require('./LogMessage');
14
+ const lodash = require('lodash');
14
15
 
15
16
 
16
17
  /* eslint-disable camelcase */
@@ -37,6 +38,22 @@ function AuthHeaders() {
37
38
  authHeaders["NR-CSEC-IAST-DATA-TRANSFER-MODE"] = "PULL";
38
39
  authHeaders['NR-CSEC-ENTITY-NAME'] = metadata['entity.name'] ? metadata['entity.name'] : '';
39
40
  authHeaders['NR-CSEC-ENTITY-GUID'] = metadata['entity.guid'] ? metadata['entity.guid'] : '';
41
+ let instanceCount = parseInt(NRAgent.config.security.scan_controllers.scan_instance_count);
42
+ if (isNaN(instanceCount)) {
43
+ instanceCount = 0;
44
+ }
45
+ if (instanceCount < 0 || instanceCount > 1) {
46
+ instanceCount = 0;
47
+ }
48
+ authHeaders['NR-CSEC-IAST-SCAN-INSTANCE-COUNT'] = instanceCount ? instanceCount : 0
49
+ if ((NRAgent.config.security.iast_test_identifier && !lodash.isEmpty(NRAgent.config.security.iast_test_identifier)) || process.env.NEW_RELIC_SECURITY_IAST_TEST_IDENTIFIER) {
50
+ let iast_test_identifier = NRAgent.config.security.iast_test_identifier || process.env.NEW_RELIC_SECURITY_IAST_TEST_IDENTIFIER
51
+ authHeaders['NR-CSEC-IAST-TEST-IDENTIFIER'] = iast_test_identifier;
52
+ logger.debug("iast_test_identifier is:", iast_test_identifier);
53
+ authHeaders['NR-CSEC-IAST-SCAN-INSTANCE-COUNT'] = 1;
54
+ }
55
+ authHeaders['NR-CSEC-PROCESS-START-TIME'] = Date.now() - Math.floor(process.uptime() * 1000);
56
+ authHeaders['NR-CSEC-IGNORED-VUL-CATEGORIES'] = commonUtils.listSkipDetectionCategory();
40
57
  } catch (error) {
41
58
  logger.error("Exception in preparing auth headers:", error);
42
59
  const logMessage = new LogMessage.logMessage("SEVERE", 'Exception in preparing auth headers', __filename, error);
@@ -76,6 +93,8 @@ function getInstance() {
76
93
  return authHeaders;
77
94
  }
78
95
 
96
+
97
+
79
98
  module.exports = {
80
99
  getInstance
81
100
  };
@@ -89,6 +89,7 @@ function exceptionReporting(exception, request, responseCode) {
89
89
  this.timestamp = Date.now();
90
90
  this.httpRequest = request;
91
91
  this.httpRequest.route = request.uri ? request.uri : request.url;
92
+ this.httpRequest.requestURI = request.url.split('?')[0];
92
93
  this.exception = null;
93
94
  this.counter = 1;
94
95
  this.responseCode = responseCode ? responseCode : null
@@ -42,6 +42,7 @@ function Agent(applicationInfo, logger, client, status) {
42
42
  this.logger = logger;
43
43
  this.status = status;
44
44
  this.wsStatus = 0;
45
+ this.delayed = false;
45
46
  }
46
47
 
47
48
  Agent.prototype = {};
@@ -96,6 +97,7 @@ Agent.prototype.setAgentStatus = function setAgentStatus(status) {
96
97
  Agent.eventEmitter.emit(EVENTS.AGENT_STATUS_UPDATED_EVENT, status);
97
98
  };
98
99
 
100
+
99
101
  Agent.EVENTS = EVENTS;
100
102
 
101
103
  Agent.eventEmitter = new EventEmitter();
@@ -138,6 +140,7 @@ Agent.setNRAgent = function setNRAgent(agent) {
138
140
  }
139
141
  };
140
142
 
143
+
141
144
  module.exports = {
142
145
  Agent
143
146
  };
@@ -23,6 +23,23 @@ let websocketHealth;
23
23
 
24
24
  const ringBuffer = require('ringbufferjs');
25
25
  const bufferedLogEvents = new ringBuffer(10);
26
+ const { CronJob } = require('cron');
27
+ let scanStartTime = 0;
28
+ let trafficStartedTime = 0;
29
+ const cron = require('cron');
30
+
31
+ const skip_detection_category_map = {
32
+ insecure_settings: ['CRYPTO', 'HASH', 'RANDOM', 'SECURE_COOKIE', 'TRUSTBOUNDARY'],
33
+ invalid_file_access: ['FILE_OPERATION', 'FILE_INTEGRITY'],
34
+ sql_injection: ['SQL_DB_COMMAND'],
35
+ nosql_injection: ['NOSQL_DB_COMMAND'],
36
+ ldap_injection: ['LDAP'],
37
+ javascript_injection: ['JS_INJECTION'],
38
+ command_injection: ['SYSTEM_COMMAND'],
39
+ xpath_injection: ['XPATH'],
40
+ ssrf: ['HTTP_REQUEST'],
41
+ rxss: ['REFLECTED_XSS']
42
+ }
26
43
 
27
44
 
28
45
  /**
@@ -271,7 +288,7 @@ function removeOlderlogfiles() {
271
288
  return new Date(secondStat.mtime).getTime() - new Date(firstStat.mtime).getTime();
272
289
  });
273
290
  let maxLogfile = process.env.NR_CSEC_DEBUG_LOGFILE_MAX_COUNT;
274
- if(isNaN(maxLogfile)){
291
+ if (isNaN(maxLogfile)) {
275
292
  maxLogfile = 2;
276
293
  }
277
294
  for (let i = maxLogfile; i < sorted.length; i++) {
@@ -409,7 +426,7 @@ function addLogEventtoBuffer(logMessage) {
409
426
  * Utility to get framework from APM
410
427
  * @returns
411
428
  */
412
- function getFramework(){
429
+ function getFramework() {
413
430
  let framework = EMPTY_STR;
414
431
  try {
415
432
  framework = NRAgent.environment.get('Framework')[0];
@@ -419,14 +436,119 @@ function getFramework(){
419
436
  return framework;
420
437
  }
421
438
 
439
+ function listSkipDetectionCategory() {
440
+ let skipList = [];
441
+ try {
442
+ let skipCataegories = NRAgent.config.security.exclude_from_iast_scan.iast_detection_category;
443
+ for (const key in skipCataegories) {
444
+ if (skipCataegories[key]) {
445
+ skipList = skipList.concat(skip_detection_category_map[key]);
446
+ }
447
+ }
448
+ } catch (error) {
449
+ logger.error("Error while processing skip detection categories:", error);
450
+ }
451
+ return skipList;
452
+ }
453
+
454
+ function refreshAgent() {
455
+ const { Agent } = require('./agent');
456
+ if (Agent.getAgent().status.getStatus() == 'disabled' || Agent.getAgent().delayed) {
457
+ Agent.getAgent().delayed = false;
458
+ const wsClient = Agent.getAgent().client;
459
+ Agent.getAgent().status.setStatus('connecting');
460
+ wsClient.obeyReconnect();
461
+ honourDurationConfiguration();
462
+ }
463
+ }
464
+
465
+ function executeCronSchedule() {
466
+ try {
467
+ let schedule = NRAgent.config.security.scan_schedule.schedule;
468
+ if (lodash.isEmpty(schedule)) {
469
+ return;
470
+ }
471
+ logger.debug("Schedule config is set to:", schedule);
472
+ schedule = schedule.replace(/\?/g, '*');
473
+ logger.info("Security Agent scheduled time is set to:", getScheduledScanTime(Math.ceil(cron.timeout(schedule) / 60000)))
474
+ const job = new cron.CronJob(
475
+ schedule, // cronTime
476
+ function () {
477
+ logger.debug('Cron schedule invoked');
478
+ logger.info("Security Agent scheduled time is set to:", getScheduledScanTime(Math.ceil(cron.timeout(schedule) / 60000)))
479
+ refreshAgent()
480
+ }, // onTick
481
+ null, // onComplete
482
+ true, // start
483
+ );
484
+ } catch (error) {
485
+ logger.error("Error while processing schedule. Please check schedule cron expression", error);
486
+ shutDownAgent();
487
+ }
488
+
489
+ }
490
+
491
+ function honourDurationConfiguration() {
492
+ let durationFromConfig = parseInt(NRAgent.config.security.scan_schedule.duration);
493
+ let duration = durationFromConfig;
494
+ if (isNaN(duration) || duration < 0) {
495
+ duration = 0;
496
+ }
497
+ logger.debug("IAST duration is set to:", duration);
498
+ NRAgent.config.security.scan_schedule.duration = duration;
499
+ if (duration < 1) {
500
+ return;
501
+ }
502
+ logger.info("Security Agent shutdown is set to:", getScheduledScanTime(duration))
503
+ setTimeout(() => {
504
+ shutDownAgent();
505
+ }, duration * 60000);
506
+ }
422
507
  /**
423
508
  * Utility to send error to error inbox of APM
424
509
  * @param {*} error
425
510
  */
426
- function sendErrorToErrorInbox(error){
511
+ function sendErrorToErrorInbox(error) {
427
512
  API.newrelic.noticeError(error);
428
513
  }
429
514
 
515
+ const getScheduledScanTime = (delayInMinutes) => {
516
+ // Get the current time
517
+ const currentTime = new Date();
518
+
519
+ // Add the given minutes to the current time
520
+ currentTime.setMinutes(currentTime.getMinutes() + delayInMinutes);
521
+
522
+ const year = currentTime.getFullYear();
523
+ const month = currentTime.toLocaleString("default", { month: "long" });
524
+ const day = currentTime.toLocaleString("default", { weekday: "long" });
525
+ const date = currentTime.getDate();
526
+ const hours = currentTime.getHours();
527
+ const minutes = currentTime.getMinutes();
528
+ const seconds = currentTime.getSeconds();
529
+ const futureUpdatedTime = `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
530
+ const futureDateTime = `${day}, ${month} ${date} ${year} ${futureUpdatedTime}`;
531
+ return futureDateTime
532
+ };
533
+
534
+ function shutDownAgent() {
535
+ const { Agent } = require('./agent');
536
+ if (NRAgent.config.security.scan_schedule.always_sample_traces) {
537
+ Agent.getAgent().delayed = true;
538
+ logger.warn('Scan duration completed, IAST going under hibernate mode')
539
+ return;
540
+ }
541
+ if (Agent.getAgent().status.getStatus() === 'disabled') {
542
+ return;
543
+ }
544
+ Agent.getAgent().status.setStatus('disabled');
545
+ const wsClient = Agent.getAgent().client;
546
+ wsClient.closeWS();
547
+ logger.warn("Security Agent status is disabled");
548
+ }
549
+
550
+
551
+
430
552
 
431
553
  module.exports = {
432
554
  getUUID,
@@ -452,5 +574,11 @@ module.exports = {
452
574
  addLogEventtoBuffer,
453
575
  getLogEvents,
454
576
  getFramework,
455
- sendErrorToErrorInbox
577
+ listSkipDetectionCategory,
578
+ executeCronSchedule,
579
+ honourDurationConfiguration,
580
+ scanStartTime,
581
+ trafficStartedTime,
582
+ sendErrorToErrorInbox,
583
+ getScheduledScanTime,
456
584
  };
@@ -6,8 +6,13 @@ const { Agent } = require('../../../agent');
6
6
  let pendingRequestIds = new Set();
7
7
  let completedRequestsMap = new Map();
8
8
  const PolicyManager = require('../../../Policy');
9
+ const API = require('../../../../../../nr-security-api');
9
10
  let batchSize;
10
- const batchthreshold = 160;
11
+ const batchthreshold = 200;
12
+ const logs = require('../../../logging');
13
+ let logger = logs.getLogger();
14
+ const commonUtils = require('../../../commonUtils');
15
+
11
16
  function getPendingRequestIds() {
12
17
  return [...pendingRequestIds];
13
18
  }
@@ -56,6 +61,7 @@ function IASTCleanup() {
56
61
  }
57
62
 
58
63
  function generateIASTDataRequest() {
64
+
59
65
  const policyInstance = PolicyManager.getInstance();
60
66
  if (policyInstance.data && policyInstance.data.vulnerabilityScan && policyInstance.data.vulnerabilityScan.iastScan) {
61
67
  batchSize = batchSize ? batchSize : policyInstance.data.vulnerabilityScan.iastScan.probing.batchSize;
@@ -64,13 +70,33 @@ function generateIASTDataRequest() {
64
70
  }
65
71
  }
66
72
  if (getCompletedRequestsMap().size >= batchSize || batchSize < batchthreshold || getPendingRequestIds().length < batchSize) {
67
- batchSize = (2 * batchSize);
73
+ batchSize = (2 * batchSize) - getPendingRequestIds().length;
74
+ }
75
+
76
+ const NRAgent = API.getNRAgent();
77
+ let scanRateLimit = 3600;
78
+ let scanRateLimitFromConfig = parseInt(NRAgent.config.security.scan_controllers.iast_scan_request_rate_limit);
79
+ scanRateLimit = scanRateLimitFromConfig
80
+ if (isNaN(scanRateLimitFromConfig)) {
81
+ scanRateLimit = 3600;
68
82
  }
83
+ if (scanRateLimit >= 0 || scanRateLimit < 0) {
84
+ batchSize = parseInt(scanRateLimit / 12);
85
+ if (scanRateLimit < 12) {
86
+ batchSize = 1;
87
+ } else if (scanRateLimit > 3600) {
88
+ batchSize = 300;
89
+ }
90
+ }
91
+
69
92
  let object = {};
70
93
  object['jsonName'] = 'iast-data-request';
71
94
  object['applicationUUID'] = Agent.getAgent().applicationInfo.applicationUUID;
72
95
  object['appEntityGuid'] = Agent.getAgent().applicationInfo.appEntityGuid;
73
96
  object['appAccountId'] = Agent.getAgent().applicationInfo.appAccountId;
97
+ if (batchSize && batchSize > 100) {
98
+ batchSize = 100;
99
+ }
74
100
  object["batchSize"] = batchSize ? batchSize : 300;
75
101
  object['pendingRequestIds'] = getPendingRequestIds();
76
102
  object['completedRequests'] = Object.fromEntries(getCompletedRequestsMap());
@@ -24,6 +24,9 @@ const PolicyManager = require('../../../Policy');
24
24
 
25
25
  const find = `${SLASH}{{NR_CSEC_VALIDATOR_HOME_TMP}}`;
26
26
  const CSEC_HOME_TMP_CONST = new RegExp(find, 'g');
27
+ const commonUtils = require('../../../commonUtils');
28
+
29
+ const CSEC_HOME_TMP_CONST_ENCODED = new RegExp('%7B%7BNR_CSEC_VALIDATOR_HOME_TMP%7D%7D', 'g');
27
30
 
28
31
  let logger;
29
32
  let lastFuzzEventTime = 0;
@@ -31,13 +34,26 @@ let iastIntervalConst;
31
34
  let coolDownIntervalConst;
32
35
  let additionalCoolDownTime = 0;
33
36
  let fuzzedApiIDSet = new Set();
37
+ const API = require('../../../../../../nr-security-api');
38
+ const NRAgent = API.getNRAgent();
34
39
 
35
40
 
36
41
  /**
37
42
  * utility to start IAST Schedular
38
43
  */
39
44
  function startIASTSchedular() {
40
- Agent.getAgent().client.dispatcher(IASTUtil.generateIASTDataRequest());
45
+ if (Agent.getAgent().delayed) {
46
+ let delayFromConfig = parseInt(NRAgent.config.security.scan_schedule.delay);
47
+ let delay = delayFromConfig;
48
+ if (isNaN(delay) || delay < 0) {
49
+ delay = 0;
50
+ }
51
+ // logger.debug("IAST data pull request is scheduled at %s", require('../../../commonUtils').getScheduledScanTime(delay))
52
+ }
53
+ if (!Agent.getAgent().delayed) {
54
+ Agent.getAgent().client.dispatcher(IASTUtil.generateIASTDataRequest());
55
+ }
56
+
41
57
  if (iastIntervalConst) {
42
58
  clearInterval(iastIntervalConst);
43
59
  }
@@ -50,8 +66,11 @@ function startIASTSchedular() {
50
66
  if (isNaN(probingInterval)) {
51
67
  probingInterval = 5;
52
68
  }
53
-
69
+
54
70
  iastIntervalConst = setInterval(() => {
71
+ if (Agent.getAgent().status.getStatus() == 'disabled' || Agent.getAgent().delayed) {
72
+ return;
73
+ }
55
74
  let data = IASTUtil.generateIASTDataRequest();
56
75
  let currentTime = Date.now();
57
76
  let completedListSize = IASTUtil.getCompletedRequestsMap().size;
@@ -86,9 +105,19 @@ function logScannedApiId(fuzzHeader, requestURL) {
86
105
 
87
106
  // handler function to parse fuzz event and prepare fuzz request
88
107
  function handler(json) {
108
+ if (Agent.getAgent().status.getStatus() == 'disabled') {
109
+ return;
110
+ }
89
111
  setLastFuzzEventTime();
90
112
  let rawFuzzRequest = json.arguments[0];
91
- rawFuzzRequest = rawFuzzRequest.replace(CSEC_HOME_TMP_CONST, CSEC_HOME_TMP);
113
+
114
+ try {
115
+ rawFuzzRequest = rawFuzzRequest.replace(CSEC_HOME_TMP_CONST, CSEC_HOME_TMP);
116
+ rawFuzzRequest = rawFuzzRequest.replace(CSEC_HOME_TMP_CONST_ENCODED, encodeURI(CSEC_HOME_TMP));
117
+ } catch (error) {
118
+ logger.debug("Error while replacing place holder", error);
119
+ }
120
+
92
121
  let fuzzRequest;
93
122
  try {
94
123
  fuzzRequest = JSON.parse(rawFuzzRequest);
@@ -96,7 +125,7 @@ function handler(json) {
96
125
  IASTUtil.addPendingRequestId(json.id);
97
126
  } catch (error) {
98
127
  logger.error('Parsing exeception in fuzz request: ', error);
99
-
128
+
100
129
  const logMessage = new LogMessage.logMessage(SEVERE, 'Parsing exeception in fuzz request', __filename, error);
101
130
  require('../../../commonUtils').addLogEventtoBuffer(logMessage);
102
131
  }
@@ -177,6 +206,9 @@ function handleFuzzResponse(response, fuzzDetails) {
177
206
  const { rawFuzzRequest, fuzzRequest } = fuzzDetails;
178
207
  if (response) {
179
208
  IASTUtil.removePendingRequestId(fuzzRequest.id);
209
+ if (commonUtils.scanStartTime == 0) {
210
+ commonUtils.scanStartTime = Date.now();
211
+ }
180
212
  response.then(() => {
181
213
  logger.info('Fuzz success: ' + rawFuzzRequest);
182
214
  }).catch(() => {
@@ -10,6 +10,10 @@ const initLogger = logs.getInitLogger();
10
10
  const LOG_MESSAGES = require('../../../sec-agent-constants').LOG_MESSAGES;
11
11
  const applicationInfoModule = require('../../../applicationinfo');
12
12
  const LogMessage = require('../../../LogMessage');
13
+ const API = require('../../../../../../nr-security-api');
14
+ const NRAgent = API.getNRAgent();
15
+ const { Agent } = require('../../../agent');
16
+
13
17
 
14
18
  module.exports.handler = function handler(json) {
15
19
  try {
@@ -20,7 +24,7 @@ module.exports.handler = function handler(json) {
20
24
  initLogger.info('Security Agent is now ACTIVE for', applicationInfoModule.getInstance().applicationUUID);
21
25
  const logMessage = new LogMessage.logMessage("INFO", `Security Agent is ACTIVE for ${ applicationInfoModule.getInstance().applicationUUID}`, __filename, null);
22
26
  require('../../../commonUtils').addLogEventtoBuffer(logMessage);
23
-
27
+
24
28
  } catch (error) {
25
29
  logger.error(LOG_MESSAGES.PARSING_EXP_WELCOME_MSG, error);
26
30
  }
@@ -4,11 +4,14 @@
4
4
  */
5
5
 
6
6
  let logger;
7
+ const { Agent } = require('../../../agent');
7
8
  module.exports.handler = function handler (json) {
8
- logger.info('WS reconnect received', json);
9
- const { Agent } = require('../../../agent');
10
- const wsClient = Agent.getAgent().client;
11
- wsClient.obeyReconnect();
9
+ if (Agent.getAgent().status.getStatus() != 'disabled'){
10
+ logger.info('WS reconnect received', json);
11
+ const wsClient = Agent.getAgent().client;
12
+ wsClient.obeyReconnect();
13
+ }
14
+
12
15
  };
13
16
 
14
17
  module.exports.setLogger = l => { logger = l };
@@ -176,6 +176,9 @@ SecWebSocket.prototype.reconnect = function reconnect() {
176
176
  };
177
177
 
178
178
  SecWebSocket.prototype.obeyReconnect = function obeyReconnect() {
179
+ if (Agent.getAgent().status.getStatus() == 'disabled') {
180
+ return;
181
+ }
179
182
  const { instance } = this;
180
183
  if (initTimeOut) {
181
184
  clearTimeout(initTimeOut);
@@ -194,13 +197,25 @@ SecWebSocket.prototype.obeyReconnect = function obeyReconnect() {
194
197
 
195
198
  }
196
199
 
200
+ SecWebSocket.prototype.closeWS = function closeWS() {
201
+ const { instance } = this;
202
+ try {
203
+ instance.close();
204
+ } catch (error) {
205
+ logger.error("Error while closing websocket", error);
206
+ }
207
+ }
208
+
197
209
  SecWebSocket.prototype.pingWS = async function pingWS() {
210
+ if (Agent.getAgent().status.getStatus() != 'active') {
211
+ return;
212
+ }
198
213
  const self = this;
199
214
  let currentTime = Date.now();
200
215
 
201
216
  let timeDiffInPing = (currentTime - lastPongtime) / 1000;
202
- logger.debug("Websocket ready state is:",self.instance.readyState)
203
-
217
+ logger.debug("Websocket ready state is:", self.instance.readyState)
218
+
204
219
  if (timeDiffInPing > 40 && lastPongtime != 0 && self.instance.readyState > 1) {
205
220
  self.obeyReconnect();
206
221
  lastPongtime = 0;
@@ -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
+ let 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
  *
@@ -63,6 +65,9 @@ function HC(info) {
63
65
  this.iastEventStats = EventStats.getInstance();
64
66
  this.raspEventStats = EventStats.getInstance();
65
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);
66
71
 
67
72
 
68
73
  /**
@@ -134,6 +134,7 @@ function generateSecEvent(securityMetadata) {
134
134
  const isAPIBlocked = false;
135
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);
136
136
  event.metaData.isClientDetectedFromXFF = isClientDetectedFromXFF;
137
+ event.metaData.skipScanParameters = NRAgent.config.security.exclude_from_iast_scan.http_request_parameters;
137
138
  event.httpRequest.route = uri;
138
139
  return event;
139
140
  } catch (e) {
@@ -191,9 +192,12 @@ function generateExitEvent(secEvent) {
191
192
 
192
193
  function sendEvent(secEvent) {
193
194
  const agentModule = Agent.getAgent();
194
- if (agentModule.status.getStatus() != 'connecting' && NRAgent.config.security.enabled) {
195
+ if (agentModule.status.getStatus() != 'connecting' && NRAgent.config.security.enabled && agentModule.status.getStatus() == 'active') {
195
196
  agentModule.client.dispatcher(secEvent);
196
197
  if (!firstEventSent && agentModule.status.getStatus() === 'active') {
198
+ if(commonUtils.trafficStartedTime == 0){
199
+ commonUtils.trafficStartedTime = Date.now();
200
+ }
197
201
  initLogger.info("[STEP-8] => First event sent for validation. Security Agent started successfully", JSON.stringify(secEvent));
198
202
  firstEventSent = true;
199
203
  }