@contrast/contrast 1.0.10 → 1.0.13

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 (112) hide show
  1. package/README.md +1 -1
  2. package/dist/audit/{languageAnalysisEngine/report → report}/commonReportingFunctions.js +56 -35
  3. package/dist/audit/report/models/reportGuidanceModel.js +6 -0
  4. package/dist/audit/{languageAnalysisEngine/report → report}/models/reportLibraryModel.js +0 -0
  5. package/dist/audit/{languageAnalysisEngine/report → report}/models/reportListModel.js +0 -0
  6. package/dist/audit/{languageAnalysisEngine/report → report}/models/reportOutputModel.js +1 -2
  7. package/dist/audit/{languageAnalysisEngine/report → report}/models/reportSeverityModel.js +0 -0
  8. package/dist/audit/{languageAnalysisEngine/report → report}/models/severityCountModel.js +1 -0
  9. package/dist/audit/{languageAnalysisEngine/report → report}/reportingFeature.js +12 -8
  10. package/dist/audit/{languageAnalysisEngine/report → report}/utils/reportUtils.js +3 -4
  11. package/dist/commands/audit/auditConfig.js +3 -3
  12. package/dist/commands/audit/help.js +3 -1
  13. package/dist/commands/audit/processAudit.js +14 -2
  14. package/dist/commands/auth/auth.js +1 -1
  15. package/dist/commands/config/config.js +2 -2
  16. package/dist/commands/scan/processScan.js +20 -4
  17. package/dist/commands/scan/sca/scaAnalysis.js +15 -5
  18. package/dist/common/HTTPClient.js +39 -2
  19. package/dist/common/commonHelp.js +19 -0
  20. package/dist/common/fail.js +70 -0
  21. package/dist/common/versionChecker.js +14 -6
  22. package/dist/constants/constants.js +2 -2
  23. package/dist/constants/locales.js +15 -5
  24. package/dist/constants.js +42 -5
  25. package/dist/index.js +6 -3
  26. package/dist/lambda/help.js +2 -3
  27. package/dist/lambda/lambda.js +7 -0
  28. package/dist/scaAnalysis/common/scaParserForGoAndJava.js +32 -0
  29. package/dist/scaAnalysis/common/scaServicesUpload.js +52 -0
  30. package/dist/scaAnalysis/common/treeUpload.js +20 -5
  31. package/dist/scaAnalysis/dotnet/analysis.js +15 -3
  32. package/dist/scaAnalysis/go/goAnalysis.js +8 -2
  33. package/dist/scaAnalysis/java/analysis.js +10 -6
  34. package/dist/scaAnalysis/java/index.js +7 -1
  35. package/dist/scaAnalysis/java/javaBuildDepsParser.js +19 -3
  36. package/dist/scaAnalysis/javascript/index.js +4 -0
  37. package/dist/scaAnalysis/javascript/scaServiceParser.js +109 -0
  38. package/dist/scaAnalysis/php/analysis.js +1 -1
  39. package/dist/scaAnalysis/php/index.js +12 -6
  40. package/dist/scaAnalysis/php/phpNewServicesMapper.js +62 -0
  41. package/dist/scaAnalysis/python/analysis.js +43 -5
  42. package/dist/scaAnalysis/python/index.js +7 -2
  43. package/dist/scaAnalysis/ruby/analysis.js +116 -9
  44. package/dist/scaAnalysis/ruby/index.js +6 -1
  45. package/dist/scan/formatScanOutput.js +6 -5
  46. package/dist/scan/help.js +2 -3
  47. package/dist/scan/populateProjectIdAndProjectName.js +5 -0
  48. package/dist/scan/scan.js +4 -0
  49. package/dist/scan/scanConfig.js +4 -4
  50. package/dist/scan/scanResults.js +46 -3
  51. package/dist/telemetry/telemetry.js +137 -0
  52. package/dist/{audit/languageAnalysisEngine/util → utils}/capabilities.js +0 -0
  53. package/dist/{audit/languageAnalysisEngine/util → utils}/generalAPI.js +14 -5
  54. package/dist/utils/getConfig.js +2 -4
  55. package/dist/utils/parsedCLIOptions.js +3 -1
  56. package/dist/utils/requestUtils.js +7 -1
  57. package/package.json +4 -2
  58. package/src/audit/{languageAnalysisEngine/report → report}/commonReportingFunctions.ts +80 -44
  59. package/src/audit/report/models/reportGuidanceModel.ts +5 -0
  60. package/src/audit/{languageAnalysisEngine/report → report}/models/reportLibraryModel.ts +0 -0
  61. package/src/audit/{languageAnalysisEngine/report → report}/models/reportListModel.ts +0 -0
  62. package/src/audit/{languageAnalysisEngine/report → report}/models/reportOutputModel.ts +1 -7
  63. package/src/audit/{languageAnalysisEngine/report → report}/models/reportSeverityModel.ts +0 -0
  64. package/src/audit/{languageAnalysisEngine/report → report}/models/severityCountModel.ts +2 -0
  65. package/src/audit/{languageAnalysisEngine/report → report}/reportingFeature.ts +16 -9
  66. package/src/audit/{languageAnalysisEngine/report → report}/utils/reportUtils.ts +4 -4
  67. package/src/commands/audit/auditConfig.ts +10 -3
  68. package/src/commands/audit/help.ts +3 -1
  69. package/src/commands/audit/processAudit.ts +24 -2
  70. package/src/commands/auth/auth.js +3 -1
  71. package/src/commands/config/config.js +4 -2
  72. package/src/commands/scan/processScan.js +32 -4
  73. package/src/commands/scan/sca/scaAnalysis.js +23 -5
  74. package/src/common/HTTPClient.js +59 -2
  75. package/src/common/commonHelp.ts +13 -0
  76. package/src/common/fail.js +79 -0
  77. package/src/common/versionChecker.ts +18 -8
  78. package/src/constants/constants.js +2 -2
  79. package/src/constants/locales.js +19 -7
  80. package/src/constants.js +46 -6
  81. package/src/index.ts +18 -4
  82. package/src/lambda/help.ts +2 -3
  83. package/src/lambda/lambda.ts +12 -0
  84. package/src/scaAnalysis/common/scaParserForGoAndJava.js +41 -0
  85. package/src/scaAnalysis/common/scaServicesUpload.js +54 -0
  86. package/src/scaAnalysis/common/treeUpload.js +21 -5
  87. package/src/scaAnalysis/dotnet/analysis.js +21 -3
  88. package/src/scaAnalysis/go/goAnalysis.js +9 -2
  89. package/src/scaAnalysis/java/analysis.js +11 -6
  90. package/src/scaAnalysis/java/index.js +9 -1
  91. package/src/scaAnalysis/java/javaBuildDepsParser.js +25 -6
  92. package/src/scaAnalysis/javascript/index.js +4 -0
  93. package/src/scaAnalysis/javascript/scaServiceParser.js +145 -0
  94. package/src/scaAnalysis/php/analysis.js +1 -1
  95. package/src/scaAnalysis/php/index.js +12 -6
  96. package/src/scaAnalysis/php/phpNewServicesMapper.js +77 -0
  97. package/src/scaAnalysis/python/analysis.js +49 -5
  98. package/src/scaAnalysis/python/index.js +7 -2
  99. package/src/scaAnalysis/ruby/analysis.js +149 -9
  100. package/src/scaAnalysis/ruby/index.js +6 -1
  101. package/src/scan/formatScanOutput.ts +7 -5
  102. package/src/scan/help.js +2 -3
  103. package/src/scan/populateProjectIdAndProjectName.js +5 -1
  104. package/src/scan/scan.ts +4 -0
  105. package/src/scan/scanConfig.js +6 -4
  106. package/src/scan/scanResults.js +52 -3
  107. package/src/telemetry/telemetry.ts +154 -0
  108. package/src/{audit/languageAnalysisEngine/util → utils}/capabilities.js +0 -0
  109. package/src/{audit/languageAnalysisEngine/util → utils}/generalAPI.js +16 -6
  110. package/src/utils/getConfig.ts +2 -11
  111. package/src/utils/parsedCLIOptions.js +14 -1
  112. package/src/utils/requestUtils.js +8 -1
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.sha1Base64Value = exports.findParamValueFromArgs = exports.paramExists = exports.obfuscateParams = exports.sendTelemetryRequest = exports.sendTelemetryConfigAsObject = exports.sendTelemetryConfigAsConfObj = exports.TELEMETRY_CLI_TIME_TO_AUTH_EVENT = exports.TELEMETRY_CLI_COMMANDS_EVENT = void 0;
27
+ const commonApi_1 = require("../utils/commonApi");
28
+ const crypto = __importStar(require("crypto"));
29
+ exports.TELEMETRY_CLI_COMMANDS_EVENT = 'CLI_COMMANDS';
30
+ exports.TELEMETRY_CLI_TIME_TO_AUTH_EVENT = 'CLI_TIME_TO_AUTH';
31
+ const sendTelemetryConfigAsConfObj = async (config, command, argv, result, language) => {
32
+ const hostParam = '--host';
33
+ const hostParamAlias = '-h';
34
+ const orgIdParam = '--organization-id';
35
+ const orgIdParamAlias = '-o';
36
+ const authParam = '--authorization';
37
+ const apiKeyParam = '--api-key';
38
+ let configToUse;
39
+ if ((0, exports.paramExists)(argv, hostParam, hostParamAlias) &&
40
+ (0, exports.paramExists)(argv, orgIdParam, orgIdParamAlias) &&
41
+ (0, exports.paramExists)(argv, authParam, null) &&
42
+ (0, exports.paramExists)(argv, apiKeyParam, null)) {
43
+ configToUse = {
44
+ host: (0, exports.findParamValueFromArgs)(argv, hostParam, hostParamAlias),
45
+ organizationId: (0, exports.findParamValueFromArgs)(argv, orgIdParam, orgIdParamAlias),
46
+ authorization: (0, exports.findParamValueFromArgs)(argv, authParam, null),
47
+ apiKey: (0, exports.findParamValueFromArgs)(argv, apiKeyParam, null)
48
+ };
49
+ }
50
+ else if (config &&
51
+ config.get('host') &&
52
+ config.get('organizationId') &&
53
+ config.get('authorization') &&
54
+ config.get('apiKey')) {
55
+ configToUse = {
56
+ host: config.get('host')?.slice(0, -1),
57
+ organizationId: config.get('organizationId'),
58
+ authorization: config.get('authorization'),
59
+ apiKey: config.get('apiKey')
60
+ };
61
+ }
62
+ else {
63
+ return;
64
+ }
65
+ return await (0, exports.sendTelemetryConfigAsObject)(configToUse, command, argv, result, language);
66
+ };
67
+ exports.sendTelemetryConfigAsConfObj = sendTelemetryConfigAsConfObj;
68
+ const sendTelemetryConfigAsObject = async (config, command, argv, result, language) => {
69
+ const obfuscatedParams = (0, exports.obfuscateParams)(argv);
70
+ const requestBody = {
71
+ event: exports.TELEMETRY_CLI_COMMANDS_EVENT,
72
+ details: {
73
+ ip_address: '',
74
+ account_name: '',
75
+ account_host: '',
76
+ company_domain: '',
77
+ command: `contrast ${command} ${obfuscatedParams}`,
78
+ app_id: config && config.applicationId
79
+ ? (0, exports.sha1Base64Value)(config.applicationId)
80
+ : 'undefined',
81
+ project_id: config && config.projectId
82
+ ? (0, exports.sha1Base64Value)(config.projectId)
83
+ : 'undefined',
84
+ language: language,
85
+ result: result,
86
+ additional_info: '',
87
+ timestamp: new Date().toUTCString()
88
+ }
89
+ };
90
+ return await (0, exports.sendTelemetryRequest)(config, requestBody);
91
+ };
92
+ exports.sendTelemetryConfigAsObject = sendTelemetryConfigAsObject;
93
+ const sendTelemetryRequest = async (config, requestBody) => {
94
+ const client = (0, commonApi_1.getHttpClient)(config);
95
+ return client
96
+ .postTelemetry(config, requestBody)
97
+ .then((res) => {
98
+ if (res.statusCode !== 200 && config.debug === true) {
99
+ console.log('Telemetry failed to send with status', res.statusCode);
100
+ }
101
+ return { statusCode: res.statusCode, statusMessage: res.statusMessage };
102
+ })
103
+ .catch((err) => {
104
+ return;
105
+ });
106
+ };
107
+ exports.sendTelemetryRequest = sendTelemetryRequest;
108
+ const obfuscateParams = (argv) => {
109
+ return argv
110
+ .join(' ')
111
+ .replace(/--(authorization [A-Z0-9]+)/gi, '--authorization *****')
112
+ .replace(/-(o [A-Z0-9-]+)/gi, '-o *****')
113
+ .replace(/--(organization-id [A-Z0-9-]+)/gi, '--organization-id *****')
114
+ .replace(/--(api-key [A-Z0-9]+)/gi, '--api-key *****');
115
+ };
116
+ exports.obfuscateParams = obfuscateParams;
117
+ const paramExists = (argv, param, paramAlias) => {
118
+ return argv.find((arg) => arg === param || arg === paramAlias);
119
+ };
120
+ exports.paramExists = paramExists;
121
+ const findParamValueFromArgs = (argv, param, paramAlias) => {
122
+ let paramAsValue;
123
+ argv.forEach((arg, index) => {
124
+ if (arg === param ||
125
+ (arg === paramAlias &&
126
+ argv[index + 1] !== undefined &&
127
+ argv[index + 1] !== null)) {
128
+ paramAsValue = argv[index + 1];
129
+ }
130
+ });
131
+ return paramAsValue;
132
+ };
133
+ exports.findParamValueFromArgs = findParamValueFromArgs;
134
+ const sha1Base64Value = (value) => {
135
+ return crypto.createHash('sha1').update(value).digest('base64');
136
+ };
137
+ exports.sha1Base64Value = sha1Base64Value;
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  const { featuresTeamServer } = require('./capabilities');
3
3
  const semver = require('semver');
4
- const { handleResponseErrors } = require('../../../common/errorHandling');
5
- const { getHttpClient } = require('../../../utils/commonApi');
4
+ const { handleResponseErrors } = require('../common/errorHandling');
5
+ const commonApi = require('./commonApi');
6
+ const { isNil } = require('lodash');
6
7
  const getGlobalProperties = async (config) => {
7
- const client = getHttpClient(config);
8
+ const client = commonApi.getHttpClient(config);
8
9
  return client
9
- .getGlobalProperties(config)
10
+ .getGlobalProperties(config.host)
10
11
  .then(res => {
11
12
  if (res.statusCode === 200) {
12
13
  return res.body;
@@ -19,6 +20,13 @@ const getGlobalProperties = async (config) => {
19
20
  console.log(err);
20
21
  });
21
22
  };
23
+ const getMode = async (config) => {
24
+ const features = await getGlobalProperties(config);
25
+ if (!isNil(features?.mode)) {
26
+ return features.mode;
27
+ }
28
+ return '';
29
+ };
22
30
  const getFeatures = version => {
23
31
  const featuresEnabled = [];
24
32
  featuresTeamServer.forEach(feature => {
@@ -35,5 +43,6 @@ const isFeatureEnabled = (features, featureName) => {
35
43
  module.exports = {
36
44
  getGlobalProperties,
37
45
  getFeatures,
38
- isFeatureEnabled
46
+ isFeatureEnabled,
47
+ getMode
39
48
  };
@@ -5,16 +5,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.setConfigValues = exports.localConfig = void 0;
7
7
  const conf_1 = __importDefault(require("conf"));
8
+ const constants_1 = require("../constants/constants");
8
9
  const localConfig = (name, version) => {
9
10
  const config = new conf_1.default({
10
11
  configName: name
11
12
  });
12
13
  config.set('version', version);
13
- if (process.env.CONTRAST_CODSEC_DISABLE_UPDATE_MESSAGE) {
14
- config.set('updateMessageHidden', JSON.parse(process.env.CONTRAST_CODSEC_DISABLE_UPDATE_MESSAGE.toLowerCase()));
15
- }
16
14
  if (!config.has('host')) {
17
- config.set('host', 'https://ce.contrastsecurity.com/');
15
+ config.set('host', constants_1.CE_URL);
18
16
  }
19
17
  return config;
20
18
  };
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  const commandLineArgs = require('command-line-args');
3
- const getCommandLineArgsCustom = (parameterList, optionDefinitions) => {
3
+ const { sendTelemetryConfigAsConfObj } = require('../telemetry/telemetry');
4
+ const getCommandLineArgsCustom = async (contrastConf, command, parameterList, optionDefinitions) => {
4
5
  try {
5
6
  return commandLineArgs(optionDefinitions, {
6
7
  argv: parameterList,
@@ -10,6 +11,7 @@ const getCommandLineArgsCustom = (parameterList, optionDefinitions) => {
10
11
  });
11
12
  }
12
13
  catch (e) {
14
+ await sendTelemetryConfigAsConfObj(contrastConf, command, parameterList, 'FAILURE', 'undefined');
13
15
  console.log(e.message.toString());
14
16
  process.exit(1);
15
17
  }
@@ -11,8 +11,14 @@ const millisToSeconds = millis => {
11
11
  const sleep = ms => {
12
12
  return new Promise(resolve => setTimeout(resolve, ms));
13
13
  };
14
+ const timeOutError = (ms, reject) => {
15
+ return setTimeout(() => {
16
+ reject(new Error(`No input detected after 30s`));
17
+ }, ms);
18
+ };
14
19
  module.exports = {
15
20
  sendRequest: sendRequest,
16
21
  sleep: sleep,
17
- millisToSeconds: millisToSeconds
22
+ millisToSeconds: millisToSeconds,
23
+ timeOutError: timeOutError
18
24
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrast/contrast",
3
- "version": "1.0.10",
3
+ "version": "1.0.13",
4
4
  "description": "Contrast Security's command line tool",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -23,7 +23,9 @@
23
23
  "test": "jest --testPathIgnorePatterns=./test-integration/",
24
24
  "test-int": "jest ./test-integration/",
25
25
  "test-int-scan": "jest ./test-integration/scan",
26
- "test-int-audit": "jest test-integration/audit/audit-int.spec.js",
26
+ "test-int-audit": "jest test-integration/audit",
27
+ "test-int-audit-reports": "jest test-integration/audit/audit-language-reports.spec.js",
28
+ "test-int-audit-features": "jest test-integration/audit/auditFeatures/",
27
29
  "format": "prettier --write \"**/*.{ts,tsx,js,json,md,yml}\" .eslintrc.*",
28
30
  "check-format": "prettier --check \"**/*.{ts,tsx,js,json,md,yml}\" .eslintrc.*",
29
31
  "coverage-local": "nyc --reporter=text mocha './test/**/*.spec.js'",
@@ -1,4 +1,4 @@
1
- import { getHttpClient, handleResponseErrors } from '../../../utils/commonApi'
1
+ import { getHttpClient, handleResponseErrors } from '../../utils/commonApi'
2
2
  import {
3
3
  ReportCompositeKey,
4
4
  ReportList,
@@ -22,15 +22,17 @@ import {
22
22
  ReportOutputModel
23
23
  } from './models/reportOutputModel'
24
24
  import {
25
+ CE_URL,
25
26
  CRITICAL_COLOUR,
26
27
  HIGH_COLOUR,
27
28
  LOW_COLOUR,
28
29
  MEDIUM_COLOUR,
29
30
  NOTE_COLOUR
30
- } from '../../../constants/constants'
31
+ } from '../../constants/constants'
31
32
  import Table from 'cli-table3'
33
+ import { ReportGuidanceModel } from './models/reportGuidanceModel'
32
34
 
33
- export const createSummaryMessage = (
35
+ export const createSummaryMessageTop = (
34
36
  numberOfVulnerableLibraries: number,
35
37
  numberOfCves: number
36
38
  ) => {
@@ -41,6 +43,14 @@ export const createSummaryMessage = (
41
43
  )
42
44
  }
43
45
 
46
+ export const createSummaryMessageBottom = (
47
+ numberOfVulnerableLibraries: number
48
+ ) => {
49
+ numberOfVulnerableLibraries === 1
50
+ ? console.log(`Found 1 vulnerable library`)
51
+ : console.log(`Found ${numberOfVulnerableLibraries} vulnerable libraries`)
52
+ }
53
+
44
54
  export const getReport = async (config: any, reportId: string) => {
45
55
  const client = getHttpClient(config)
46
56
  return client
@@ -86,7 +96,7 @@ export const printFormattedOutput = (
86
96
  numberOfCves: number,
87
97
  guidance: any
88
98
  ) => {
89
- createSummaryMessage(numberOfVulnerableLibraries, numberOfCves)
99
+ createSummaryMessageTop(numberOfVulnerableLibraries, numberOfCves)
90
100
  console.log()
91
101
  const report = new ReportList()
92
102
 
@@ -160,7 +170,11 @@ export const printFormattedOutput = (
160
170
  numOfCVEs
161
171
  )
162
172
 
163
- const advice = gatherRemediationAdvice(guidance, reportModel)
173
+ const advice = gatherRemediationAdvice(
174
+ guidance,
175
+ libraryName,
176
+ libraryVersion
177
+ )
164
178
 
165
179
  const body = buildBody(reportModel.cveArray, advice)
166
180
 
@@ -168,7 +182,6 @@ export const printFormattedOutput = (
168
182
 
169
183
  table.push(
170
184
  reportOutputModel.body.issueMessage,
171
- reportOutputModel.body.issueMessageCves,
172
185
  reportOutputModel.body.adviceMessage
173
186
  )
174
187
 
@@ -179,7 +192,7 @@ export const printFormattedOutput = (
179
192
  console.log(table.toString() + '\n')
180
193
  }
181
194
 
182
- createSummaryMessage(numberOfVulnerableLibraries, numberOfCves)
195
+ createSummaryMessageBottom(numberOfVulnerableLibraries)
183
196
  const {
184
197
  criticalMessage,
185
198
  highMessage,
@@ -190,6 +203,15 @@ export const printFormattedOutput = (
190
203
  console.log(
191
204
  `${criticalMessage} | ${highMessage} | ${mediumMessage} | ${lowMessage} | ${noteMessage}`
192
205
  )
206
+
207
+ if (config.host !== CE_URL) {
208
+ console.log(
209
+ '\n' + chalk.bold('View your full dependency tree in Contrast:')
210
+ )
211
+ console.log(
212
+ `${config.host}/Contrast/static/ng/index.html#/${config.organizationId}/applications/${config.applicationId}/libs/dependency-tree`
213
+ )
214
+ }
193
215
  }
194
216
 
195
217
  export function buildHeader(
@@ -203,18 +225,22 @@ export function buildHeader(
203
225
  numOfCVEs > 1 ? 'vulnerabilities' : 'vulnerability'
204
226
  const formattedHeaderNum = buildFormattedHeaderNum(contrastHeaderNum)
205
227
 
206
- const vulnMessage = chalk
207
- .hex(highestSeverity.outputColour)
208
- .bold(
209
- `${formattedHeaderNum} - [${highestSeverity.severity}] ${libraryName}-${version}`
210
- )
228
+ const headerColour = chalk.hex(highestSeverity.outputColour)
229
+ const headerNumAndSeverity = headerColour(
230
+ `${formattedHeaderNum} - [${highestSeverity.severity}]`
231
+ )
232
+ const libraryNameAndVersion = headerColour.bold(`${libraryName}-${version}`)
233
+ const vulnMessage = `${headerNumAndSeverity} ${libraryNameAndVersion}`
211
234
 
212
235
  const introducesMessage = `introduces ${numOfCVEs} ${vulnerabilityPluralised}`
213
236
 
214
237
  return new ReportOutputHeaderModel(vulnMessage, introducesMessage)
215
238
  }
216
239
 
217
- export function buildBody(cveArray: ReportCVEModel[], advice: any) {
240
+ export function buildBody(
241
+ cveArray: ReportCVEModel[],
242
+ advice: ReportGuidanceModel
243
+ ) {
218
244
  const cveMessages: string[] = []
219
245
 
220
246
  findCVESeveritiesAndOrderByHighestPriority(cveArray).forEach(
@@ -233,46 +259,40 @@ export function buildBody(cveArray: ReportCVEModel[], advice: any) {
233
259
 
234
260
  const numAndSeverityType = getNumOfAndSeverityType(cveArray)
235
261
 
236
- const issueMessage = [chalk.bold('Issue'), ':', `${numAndSeverityType}`]
237
-
238
- const issueMessageCves = ['', '', cveMessages.join(', ')]
262
+ const issueMessage = [
263
+ chalk.bold('Issue'),
264
+ ':',
265
+ `${numAndSeverityType} ${cveMessages.join(', ')}`
266
+ ]
239
267
 
240
268
  //todo different advice based on remediationGuidance being available or now
241
269
  // console.log(advice)
242
270
 
243
- const displayAdvice = advice?.minimum
244
- ? `Update to version ${chalk.bold(advice.minimum)}`
245
- : `Update to latest version`
271
+ const minOrMax = advice.maximum ? advice.maximum : advice.minimum
272
+ const displayAdvice = minOrMax
273
+ ? `Change to version ${chalk.bold(minOrMax)}`
274
+ : 'No recommendation is available according to our data. Upgrade to the latest stable is the best advice we can give.'
246
275
 
247
276
  const adviceMessage = [chalk.bold('Advice'), ':', displayAdvice]
248
277
 
249
- return new ReportOutputBodyModel(
250
- issueMessage,
251
- issueMessageCves,
252
- adviceMessage
253
- )
278
+ return new ReportOutputBodyModel(issueMessage, adviceMessage)
254
279
  }
255
280
 
256
- export function gatherRemediationAdvice(guidance: any, reportModel: any) {
257
- const guidanceData = {
258
- minimum: undefined,
259
- maximum: undefined,
260
- latest: undefined
261
- }
281
+ export function gatherRemediationAdvice(
282
+ guidance: any,
283
+ libraryName: string,
284
+ libraryVersion: string
285
+ ) {
286
+ const guidanceModel = new ReportGuidanceModel()
262
287
 
263
- const data =
264
- guidance[
265
- reportModel.compositeKey.libraryName +
266
- '@' +
267
- reportModel.compositeKey.libraryVersion
268
- ]
288
+ const data = guidance[libraryName + '@' + libraryVersion]
269
289
 
270
290
  if (data) {
271
- guidanceData.minimum = data.minUpgradeVersion
272
- guidanceData.maximum = data.maxUpgradeVersion
291
+ guidanceModel.minimum = data.minUpgradeVersion
292
+ guidanceModel.maximum = data.maxUpgradeVersion
273
293
  }
274
294
 
275
- return guidanceData
295
+ return guidanceModel
276
296
  }
277
297
 
278
298
  export function buildFormattedHeaderNum(contrastHeaderNum: number) {
@@ -285,11 +305,27 @@ export function getNumOfAndSeverityType(cveArray: ReportCVEModel[]) {
285
305
  new SeverityCountModel()
286
306
  )
287
307
 
288
- const criticalMessage = critical > 0 ? `${critical} Critical` : ''
289
- const highMessage = high > 0 ? `${high} High` : ''
290
- const mediumMessage = medium > 0 ? `${medium} Medium` : ''
291
- const lowMessage = low > 0 ? `${low} Low` : ''
292
- const noteMessage = note > 0 ? `${note} Note` : ''
308
+ const criticalNumCheck = critical > 0
309
+
310
+ const highNumCheck = high > 0
311
+ const highDivider = highNumCheck ? '|' : ''
312
+
313
+ const mediumNumCheck = medium > 0
314
+ const mediumDivider = mediumNumCheck ? '|' : ''
315
+
316
+ const lowNumCheck = low > 0
317
+ const lowDivider = lowNumCheck ? '|' : ''
318
+
319
+ const noteNumCheck = low > 0
320
+ const noteDivider = noteNumCheck ? '|' : ''
321
+
322
+ const criticalMessage = criticalNumCheck
323
+ ? `${critical} Critical ${highDivider}`
324
+ : ''
325
+ const highMessage = highNumCheck ? `${high} High ${mediumDivider}` : ''
326
+ const mediumMessage = mediumNumCheck ? `${medium} Medium ${lowDivider}` : ''
327
+ const lowMessage = lowNumCheck ? `${low} Low ${noteDivider}` : ''
328
+ const noteMessage = noteNumCheck ? `${note} Note` : ''
293
329
 
294
330
  //removes/trims whitespace to single spaces
295
331
  return `${criticalMessage} ${highMessage} ${mediumMessage} ${lowMessage} ${noteMessage}`
@@ -0,0 +1,5 @@
1
+ export class ReportGuidanceModel {
2
+ minimum?: string
3
+ maximum?: string
4
+ latest?: string
5
+ }
@@ -20,16 +20,10 @@ export class ReportOutputHeaderModel {
20
20
 
21
21
  export class ReportOutputBodyModel {
22
22
  issueMessage: string[]
23
- issueMessageCves: string[]
24
23
  adviceMessage: string[]
25
24
 
26
- constructor(
27
- issueMessage: string[],
28
- issueMessageCves: string[],
29
- adviceMessage: string[]
30
- ) {
25
+ constructor(issueMessage: string[], adviceMessage: string[]) {
31
26
  this.issueMessage = issueMessage
32
- this.issueMessageCves = issueMessageCves
33
27
  this.adviceMessage = adviceMessage
34
28
  }
35
29
  }
@@ -4,6 +4,7 @@ export class SeverityCountModel {
4
4
  medium!: number
5
5
  low!: number
6
6
  note!: number
7
+ total!: number
7
8
 
8
9
  //needed as default to stop NaN when new object constructed
9
10
  constructor() {
@@ -12,6 +13,7 @@ export class SeverityCountModel {
12
13
  this.medium = 0
13
14
  this.low = 0
14
15
  this.note = 0
16
+ this.total = 0
15
17
  }
16
18
 
17
19
  get getTotal(): number {
@@ -8,7 +8,9 @@ import {
8
8
  } from './utils/reportUtils'
9
9
  import i18n from 'i18n'
10
10
  import chalk from 'chalk'
11
- import * as constants from '../../../constants/constants'
11
+ import * as constants from '../../constants/constants'
12
+ import { SeverityCountModel } from './models/severityCountModel'
13
+ import * as common from '../../common/fail'
12
14
 
13
15
  export function convertKeysToStandardFormat(config: any, guidance: any) {
14
16
  let convertedGuidance = guidance
@@ -72,6 +74,7 @@ export function formatVulnerabilityOutput(
72
74
  String(0)
73
75
  )
74
76
  )
77
+ return [false, 0, [new SeverityCountModel()]]
75
78
  } else {
76
79
  let numberOfCves = 0
77
80
  vulnerableLibraries.forEach(lib => (numberOfCves += lib.cveArray.length))
@@ -83,12 +86,13 @@ export function formatVulnerabilityOutput(
83
86
  numberOfCves,
84
87
  guidance
85
88
  )
86
-
87
- return [
88
- hasSomeVulnerabilitiesReported,
89
- numberOfCves,
90
- severityCountAllLibraries(vulnerableLibraries)
91
- ]
89
+ let severityCount = new SeverityCountModel()
90
+ severityCount = severityCountAllLibraries(
91
+ vulnerableLibraries,
92
+ severityCount
93
+ )
94
+ severityCount.total = severityCount.getTotal
95
+ return [hasSomeVulnerabilitiesReported, numberOfCves, severityCount]
92
96
  }
93
97
  }
94
98
 
@@ -97,8 +101,7 @@ export async function vulnerabilityReportV2(config: any, reportId: string) {
97
101
  const reportResponse = await getReport(config, reportId)
98
102
 
99
103
  if (reportResponse !== undefined) {
100
- const name = config.applicationName
101
- formatVulnerabilityOutput(
104
+ let output = formatVulnerabilityOutput(
102
105
  reportResponse.vulnerabilities,
103
106
  config.applicationId,
104
107
  config,
@@ -106,5 +109,9 @@ export async function vulnerabilityReportV2(config: any, reportId: string) {
106
109
  ? reportResponse.remediationGuidance
107
110
  : {}
108
111
  )
112
+
113
+ if (config.fail) {
114
+ common.processFail(config, output[2])
115
+ }
109
116
  }
110
117
  }
@@ -3,7 +3,7 @@ import {
3
3
  ReportLibraryModel
4
4
  } from '../models/reportLibraryModel'
5
5
  import { ReportSeverityModel } from '../models/reportSeverityModel'
6
- import languageAnalysisEngine from './../../../../constants/constants'
6
+ import languageAnalysisEngine from '../../../constants/constants'
7
7
  import {
8
8
  CRITICAL_COLOUR,
9
9
  CRITICAL_PRIORITY,
@@ -15,7 +15,7 @@ import {
15
15
  MEDIUM_PRIORITY,
16
16
  NOTE_COLOUR,
17
17
  NOTE_PRIORITY
18
- } from '../../../../constants/constants'
18
+ } from '../../../constants/constants'
19
19
  import { orderBy } from 'lodash'
20
20
  import { SeverityCountModel } from '../models/severityCountModel'
21
21
  import { ReportModelStructure } from '../models/reportListModel'
@@ -75,9 +75,9 @@ export function convertGenericToTypedLibraryVulns(libraries: any) {
75
75
  }
76
76
 
77
77
  export function severityCountAllLibraries(
78
- vulnerableLibraries: ReportLibraryModel[]
78
+ vulnerableLibraries: ReportLibraryModel[],
79
+ severityCount: SeverityCountModel
79
80
  ) {
80
- const severityCount = new SeverityCountModel()
81
81
  vulnerableLibraries.forEach(lib =>
82
82
  severityCountAllCVEs(lib.cveArray, severityCount)
83
83
  )
@@ -1,9 +1,16 @@
1
1
  import paramHandler from '../../utils/paramsUtil/paramHandler'
2
2
  import constants from '../../constants'
3
- import cliOptions from '../../utils/parsedCLIOptions'
3
+ import { getCommandLineArgsCustom } from '../../utils/parsedCLIOptions'
4
+ import { ContrastConf } from '../../utils/getConfig'
4
5
 
5
- export const getAuditConfig = (argv: string[]): { [key: string]: string } => {
6
- const auditParameters = cliOptions.getCommandLineArgsCustom(
6
+ export const getAuditConfig = async (
7
+ contrastConf: ContrastConf,
8
+ command: string,
9
+ argv: string[]
10
+ ): Promise<{ [key: string]: string }> => {
11
+ const auditParameters = await getCommandLineArgsCustom(
12
+ contrastConf,
13
+ command,
7
14
  argv,
8
15
  constants.commandLineDefinitions.auditOptionDefinitions
9
16
  )
@@ -1,6 +1,7 @@
1
1
  import commandLineUsage from 'command-line-usage'
2
2
  import i18n from 'i18n'
3
3
  import constants from '../../constants'
4
+ import { commonHelpLinks } from '../../common/commonHelp'
4
5
 
5
6
  const auditUsageGuide = commandLineUsage([
6
7
  {
@@ -48,7 +49,8 @@ const auditUsageGuide = commandLineUsage([
48
49
  'app-groups',
49
50
  'metadata'
50
51
  ]
51
- }
52
+ },
53
+ commonHelpLinks()
52
54
  ])
53
55
 
54
56
  export { auditUsageGuide }