@contrast/agent 4.28.1 → 4.29.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/app-info.js CHANGED
@@ -18,22 +18,35 @@ const fs = require('fs');
18
18
  const path = require('path');
19
19
  const parentPackageJson = require('parent-package-json');
20
20
  const semver = require('semver');
21
+ const { v4: uuid } = require('uuid');
21
22
  const { AGENT_INFO } = require('./constants');
22
23
  const logger = require('./core/logger')('contrast:appInfo');
23
24
 
24
- const isContainer = () => {
25
+ const MOUNTINFO_REGEX = /\/docker\/containers\/(.*?)\//;
26
+ const CGROUP_REGEX = /:\/docker\/([^/]+)$/;
27
+
28
+ const getContainerId = () => {
25
29
  try {
26
- fs.statSync('/.dockerenv');
27
- return true;
30
+ const results = fs.readFileSync('/proc/self/mountinfo', 'utf8').match(MOUNTINFO_REGEX);
31
+
32
+ if (results) return results[1];
28
33
  } catch (err) {
29
- // if no docker env, check /proc/self/cgroup
34
+ //
30
35
  }
31
36
 
32
37
  try {
33
- return fs.readFileSync('/proc/self/cgroup', 'utf8').includes('docker');
38
+ const results = fs.readFileSync('/proc/self/cgroup', 'utf8').match(CGROUP_REGEX);
39
+
40
+ if (results) return results[1];
41
+ } catch (err) {
42
+ //
43
+ }
44
+
45
+ try {
46
+ fs.statSync('/.dockerenv');
47
+ return `_${uuid()}`;
34
48
  } catch (err) {
35
- // if file not present,
36
- return false;
49
+ return null;
37
50
  }
38
51
  };
39
52
 
@@ -69,7 +82,7 @@ class AppInfo {
69
82
  type: os.type()
70
83
  };
71
84
  this.hostname = os.hostname();
72
- this.isContainer = isContainer();
85
+ this.containerId = getContainerId();
73
86
 
74
87
  logger.info('finding package.json for %s', this.indexFile);
75
88
 
@@ -555,6 +555,48 @@
555
555
  }
556
556
  ]
557
557
  }
558
+ },
559
+ "mssql/lib/base/prepared-statement.prototype.prepare": {
560
+ "type": "dataflow",
561
+ "enabled": true,
562
+ "conditions": {
563
+ "mode": "or",
564
+ "args": [
565
+ {
566
+ "index": 0,
567
+ "requiredTags": ["untrusted"],
568
+ "disallowedTags": ["sql-encoded", "limited-chars"]
569
+ }
570
+ ]
571
+ }
572
+ },
573
+ "mssql/lib/base/request.prototype.batch": {
574
+ "type": "dataflow",
575
+ "enabled": true,
576
+ "conditions": {
577
+ "mode": "or",
578
+ "args": [
579
+ {
580
+ "index": 0,
581
+ "requiredTags": ["untrusted"],
582
+ "disallowedTags": ["sql-encoded", "limited-chars"]
583
+ }
584
+ ]
585
+ }
586
+ },
587
+ "mssql/lib/base/request.prototype.query": {
588
+ "type": "dataflow",
589
+ "enabled": true,
590
+ "conditions": {
591
+ "mode": "or",
592
+ "args": [
593
+ {
594
+ "index": 0,
595
+ "requiredTags": ["untrusted"],
596
+ "disallowedTags": ["sql-encoded", "limited-chars"]
597
+ }
598
+ ]
599
+ }
558
600
  }
559
601
  }
560
602
  },
@@ -626,6 +626,24 @@
626
626
  "methodName": "Database.prototype.prepare",
627
627
  "isModule": true
628
628
  },
629
+ "mssql/lib/base/prepared-statement.prototype.prepare": {
630
+ "moduleName": "mssql",
631
+ "version": ">=6.4.0",
632
+ "methodName": "PreparedStatement.prototype.prepare",
633
+ "isModule": true
634
+ },
635
+ "mssql/lib/base/request.prototype.batch": {
636
+ "moduleName": "mssql",
637
+ "version": ">=6.4.0",
638
+ "methodName": "Request.prototype.batch",
639
+ "isModule": true
640
+ },
641
+ "mssql/lib/base/request.prototype.query": {
642
+ "moduleName": "mssql",
643
+ "version": ">=6.4.0",
644
+ "methodName": "Request.prototype.query",
645
+ "isModule": true
646
+ },
629
647
  "path.format": {
630
648
  "moduleName": "path",
631
649
  "methodName": "format",
package/lib/contrast.js CHANGED
@@ -319,27 +319,29 @@ contrastAgent.bootstrap = function(args) {
319
319
  );
320
320
  })
321
321
  .finally(async () => {
322
- let destination = process.env['CONTRAST__AGENT__DIAGNOSTICS__REPORT_PATH'];
323
- if (destination == null) {
324
- destination = agent.config._flat['agent.logger.path'].split('/');
325
- destination.pop() && destination.push('contrast_effective_config.json');
326
- destination = destination.join('/');
327
- }
328
-
329
- const args = {
330
- quiet: (process.env['CONTRAST__AGENT__DIAGNOSTICS__QUIET'] === 'false') ? false : true,
331
- output: destination,
332
- };
333
-
334
- try {
335
- outputAgentConfigFile(agent, options, args, null);
336
- } catch (err) {
337
- outputAgentConfigFile(agent, options, args, err);
338
- }
339
-
340
- if (!(process.env['CONTRAST__AGENT__SYSTEM_DIAGNOSTICS__ENABLE'] === 'false')) {
341
- const info = fetchSystemInfo();
342
- outputSystemInfo({ skip: false, quiet: true, output: 'contrast_system_info.json' }, info);
322
+ if (!(process.env['CONTRAST__AGENT__DIAGNOSTICS__ENABLE'] === 'false')) {
323
+ let destination = process.env['CONTRAST__AGENT__DIAGNOSTICS__REPORT_PATH'];
324
+ if (destination == null) {
325
+ destination = agent.config._flat['agent.logger.path'].split('/');
326
+ destination.pop() && destination.push('contrast_effective_config.json');
327
+ destination = destination.join('/');
328
+ }
329
+
330
+ const args = {
331
+ quiet: (process.env['CONTRAST__AGENT__DIAGNOSTICS__QUIET'] === 'false') ? false : true,
332
+ output: destination,
333
+ };
334
+
335
+ try {
336
+ outputAgentConfigFile(agent, options, args, null);
337
+ } catch (err) {
338
+ outputAgentConfigFile(agent, options, args, err);
339
+ }
340
+
341
+ if (!(process.env['CONTRAST__AGENT__SYSTEM_DIAGNOSTICS__ENABLE'] === 'false')) {
342
+ const info = fetchSystemInfo();
343
+ outputSystemInfo({ skip: false, quiet: true, output: 'contrast_system_info.json' }, info);
344
+ }
343
345
  }
344
346
  });
345
347
  };
package/lib/telemetry.js CHANGED
@@ -74,12 +74,18 @@ module.exports = class Telemetry {
74
74
  const mac = getMac();
75
75
 
76
76
  const hash = createHash('sha256').update(mac);
77
+ if (appInfo.containerId) {
78
+ hash.update(appInfo.containerId);
79
+ }
77
80
  this.instanceId = hash.copy().digest('hex');
78
81
  this.applicationId = hash.update(appInfo.name).digest('hex');
79
82
  } catch (err) {
80
83
  // If getMac fails we fall back to generating a UUID. "Unstable"
81
84
  // identifiers such as these are prefixed with an underscore.
82
- const id = uuid();
85
+ let id = uuid();
86
+ if (appInfo.containerId) {
87
+ id += `_${appInfo.containerId}`;
88
+ }
83
89
 
84
90
  this.instanceId = `_${id}`;
85
91
  this.applicationId = this.instanceId;
@@ -92,7 +98,7 @@ module.exports = class Telemetry {
92
98
  osArch: appInfo.os.architecture,
93
99
  osPlatform: appInfo.os.platform,
94
100
  osRelease: appInfo.os.release,
95
- isContainer: appInfo.isContainer,
101
+ isContainer: !!appInfo.containerId,
96
102
  agent: AGENT_INFO.NAME,
97
103
  agentVersion: AGENT_INFO.VERSION,
98
104
  isAssess: agent.isInAssessMode(),
@@ -29,25 +29,25 @@ function getLoggerValues(option, config, tsData) {
29
29
  tsValue = tsData.logFile;
30
30
  break;
31
31
  case 'agent.security_logger.syslog.enable':
32
- tsValue = tsData.defend.syslog && tsData.defend.syslog.enabled;
32
+ tsValue = tsData.defend.syslog && tsData.defend.syslog.syslogEnabled;
33
33
  break;
34
34
  case 'agent.security_logger.syslog.ip':
35
- tsValue = tsData.defend.syslog && tsData.defend.syslog.ipAddress;
35
+ tsValue = tsData.defend.syslog && tsData.defend.syslog.syslogIpAddress;
36
36
  break;
37
37
  case 'agent.security_logger.syslog.port':
38
- tsValue = tsData.defend.syslog && tsData.defend.syslog.port;
38
+ tsValue = tsData.defend.syslog && tsData.defend.syslog.syslogPortNumber;
39
39
  break;
40
- case 'agent.security_logger.syslog.fascility':
41
- tsValue = tsData.defend.syslog && tsData.defend.syslog.fascilityCode;
40
+ case 'agent.security_logger.syslog.facility':
41
+ tsValue = tsData.defend.syslog && tsData.defend.syslog.syslogFacilityCode;
42
42
  break;
43
43
  case 'agent.security_logger.syslog.severity_exploited':
44
- tsValue = tsData.defend.syslog && tsData.defend.syslog.severityExploited;
44
+ tsValue = tsData.defend.syslog && tsData.defend.syslog.syslogSeverityExploited;
45
45
  break;
46
46
  case 'agent.security_logger.syslog.severity_blocked':
47
- tsValue = tsData.defend.syslog && tsData.defend.syslog.severityBlocked;
47
+ tsValue = tsData.defend.syslog && tsData.defend.syslog.syslogSeverityBlocked;
48
48
  break;
49
49
  case 'agent.security_logger.syslog.severity_probed':
50
- tsValue = tsData.defend.syslog && tsData.defend.syslog.severityProbed;
50
+ tsValue = tsData.defend.syslog && tsData.defend.syslog.syslogSeverityProbed;
51
51
  break;
52
52
  default:
53
53
  break;
@@ -59,14 +59,12 @@ const init = function init(config) {
59
59
  let count = 0;
60
60
 
61
61
  const interval = setInterval(() => {
62
- if (count >= config.count) {
63
- clearInterval(interval);
64
- return;
65
- }
66
-
67
62
  writeHeapSnapshot(config.path);
68
-
69
63
  count++;
64
+
65
+ if (count === config.count) {
66
+ clearInterval(interval);
67
+ }
70
68
  }, config.window_ms);
71
69
  }, config.delay_ms).unref();
72
70
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrast/agent",
3
- "version": "4.28.1",
3
+ "version": "4.29.1",
4
4
  "description": "Node.js security instrumentation by Contrast Security",
5
5
  "keywords": [
6
6
  "security",
@@ -40,14 +40,22 @@ function isContainer() {
40
40
  fs.statSync('/.dockerenv');
41
41
  return true;
42
42
  } catch (err) {
43
- // if no docker env, check /proc/self/cgroup
43
+ // if no docker env, check /proc/self/mountinfo
44
+ }
45
+
46
+ try {
47
+ return fs.readFileSync('proc/self/mountinfo', 'utf8').includes('docker/containers/');
48
+ } catch (err) {
49
+ // else check /proc/self/cgroup
44
50
  }
45
51
 
46
52
  try {
47
53
  return fs.readFileSync('/proc/self/cgroup', 'utf8').includes('docker');
48
54
  } catch (err) {
49
- return false;
55
+ // if there's not such file we can conclude it's not docker env
50
56
  }
57
+
58
+ return false;
51
59
  }
52
60
 
53
61
  function isUsingPM2() {
@@ -55,11 +63,11 @@ function isUsingPM2() {
55
63
  let version = null;
56
64
 
57
65
  for (const pathVar of ['npm_package_json', 'PWD']) {
58
- let packagePath;
59
- if (packagePath = process.env[pathVar]) {
66
+ const packagePath = process.env[pathVar];
67
+ if (packagePath) {
60
68
  try {
61
- version = require(path.join(packagePath, 'package.json'));
62
- } catch(err) {
69
+ version = require(path.join(packagePath, 'package.json')).dependencies['pm2'];
70
+ } catch (err) {
63
71
  //
64
72
  }
65
73
  }
@@ -124,6 +132,7 @@ const diagnostics = {
124
132
 
125
133
  fetchSystemInfo() {
126
134
  const yaml = setup({}, logger);
135
+ const appPath = process.cwd();
127
136
 
128
137
  const info = {
129
138
  ReportDate: new Date(),
@@ -142,7 +151,6 @@ const diagnostics = {
142
151
  Node: {
143
152
  Version: process.version
144
153
  },
145
- PM2: isUsingPM2(),
146
154
  OperatingSystem: {
147
155
  Architecture: os.arch(),
148
156
  Name: os.type(),
@@ -155,12 +163,14 @@ const diagnostics = {
155
163
  },
156
164
  Host: {
157
165
  isDocker: isContainer(),
166
+ PM2: isUsingPM2(),
158
167
  Memory: {
159
168
  Total: (os.totalmem() / 1e6).toFixed(0).concat(' MB'),
160
169
  Free: (os.freemem() / 1e6).toFixed(0).concat(' MB'),
161
170
  Used: ((os.totalmem() - os.freemem()) / 1e6).toFixed(0).concat(' MB'),
162
171
  }
163
172
  },
173
+ Application: appPath ? require(path.join(appPath, 'package.json')) : null,
164
174
  };
165
175
 
166
176
  return info;