@contrast/contrast 1.0.7 → 1.0.8

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 (79) hide show
  1. package/dist/audit/autodetection/autoDetectLanguage.js +3 -3
  2. package/dist/audit/catalogueApplication/catalogueApplication.js +23 -5
  3. package/dist/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +5 -5
  4. package/dist/audit/languageAnalysisEngine/getProjectRootFilenames.js +9 -9
  5. package/dist/audit/languageAnalysisEngine/index.js +2 -2
  6. package/dist/audit/languageAnalysisEngine/languageAnalysisFactory.js +5 -28
  7. package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +11 -4
  8. package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +39 -13
  9. package/dist/audit/languageAnalysisEngine/report/models/reportListModel.js +2 -1
  10. package/dist/audit/languageAnalysisEngine/report/models/severityCountModel.js +3 -0
  11. package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +35 -14
  12. package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +3 -3
  13. package/dist/audit/save.js +29 -0
  14. package/dist/commands/audit/auditController.js +21 -5
  15. package/dist/commands/audit/help.js +24 -1
  16. package/dist/commands/audit/processAudit.js +7 -1
  17. package/dist/commands/audit/saveFile.js +7 -3
  18. package/dist/commands/scan/sca/scaAnalysis.js +31 -10
  19. package/dist/common/HTTPClient.js +6 -0
  20. package/dist/common/versionChecker.js +19 -4
  21. package/dist/constants/constants.js +1 -1
  22. package/dist/constants/locales.js +12 -11
  23. package/dist/constants.js +9 -4
  24. package/dist/index.js +4 -3
  25. package/dist/sbom/generateSbom.js +4 -3
  26. package/dist/scaAnalysis/common/formatMessage.js +26 -5
  27. package/dist/scaAnalysis/common/treeUpload.js +0 -1
  28. package/dist/scaAnalysis/go/goReadDepFile.js +1 -3
  29. package/dist/scaAnalysis/java/analysis.js +5 -5
  30. package/dist/scaAnalysis/javascript/analysis.js +110 -0
  31. package/dist/scaAnalysis/javascript/index.js +41 -0
  32. package/dist/scaAnalysis/php/analysis.js +89 -0
  33. package/dist/scaAnalysis/php/index.js +10 -0
  34. package/dist/scaAnalysis/python/analysis.js +8 -7
  35. package/dist/scaAnalysis/ruby/analysis.js +8 -8
  36. package/dist/scaAnalysis/ruby/index.js +2 -2
  37. package/dist/scan/autoDetection.js +4 -4
  38. package/dist/scan/fileUtils.js +13 -2
  39. package/dist/utils/filterProjectPath.js +7 -2
  40. package/package.json +3 -3
  41. package/src/audit/autodetection/autoDetectLanguage.ts +3 -3
  42. package/src/audit/catalogueApplication/catalogueApplication.js +28 -6
  43. package/src/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +5 -5
  44. package/src/audit/languageAnalysisEngine/getProjectRootFilenames.js +11 -11
  45. package/src/audit/languageAnalysisEngine/index.js +2 -2
  46. package/src/audit/languageAnalysisEngine/languageAnalysisFactory.js +4 -32
  47. package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +20 -19
  48. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +67 -17
  49. package/src/audit/languageAnalysisEngine/report/models/reportListModel.ts +4 -1
  50. package/src/audit/languageAnalysisEngine/report/models/severityCountModel.ts +4 -0
  51. package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +49 -17
  52. package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +1 -1
  53. package/src/audit/save.js +32 -0
  54. package/src/commands/audit/auditController.ts +22 -13
  55. package/src/commands/audit/help.ts +24 -1
  56. package/src/commands/audit/processAudit.ts +6 -3
  57. package/src/commands/audit/saveFile.ts +5 -1
  58. package/src/commands/scan/sca/scaAnalysis.js +53 -22
  59. package/src/common/HTTPClient.js +7 -0
  60. package/src/common/versionChecker.ts +23 -4
  61. package/src/constants/constants.js +1 -1
  62. package/src/constants/locales.js +12 -11
  63. package/src/constants.js +9 -4
  64. package/src/index.ts +5 -3
  65. package/src/sbom/generateSbom.ts +1 -1
  66. package/src/scaAnalysis/common/formatMessage.js +27 -5
  67. package/src/scaAnalysis/common/treeUpload.js +0 -1
  68. package/src/scaAnalysis/go/goReadDepFile.js +1 -3
  69. package/src/scaAnalysis/java/analysis.js +5 -5
  70. package/src/scaAnalysis/javascript/analysis.js +127 -0
  71. package/src/scaAnalysis/javascript/index.js +56 -0
  72. package/src/scaAnalysis/php/analysis.js +98 -0
  73. package/src/scaAnalysis/php/index.js +11 -0
  74. package/src/scaAnalysis/python/analysis.js +8 -7
  75. package/src/scaAnalysis/ruby/analysis.js +8 -8
  76. package/src/scaAnalysis/ruby/index.js +2 -2
  77. package/src/scan/autoDetection.js +4 -4
  78. package/src/scan/fileUtils.js +13 -2
  79. package/src/utils/filterProjectPath.js +6 -2
@@ -8,14 +8,14 @@ const i18n_1 = __importDefault(require("i18n"));
8
8
  const reduceIdentifiedLanguages_1 = require("../languageAnalysisEngine/reduceIdentifiedLanguages");
9
9
  const getProjectRootFilenames_1 = require("../languageAnalysisEngine/getProjectRootFilenames");
10
10
  function identifyLanguages(config) {
11
- const { projectPath } = config;
12
- const projectRootFilenames = (0, getProjectRootFilenames_1.getProjectRootFilenames)(projectPath);
11
+ const { file } = config;
12
+ const projectRootFilenames = (0, getProjectRootFilenames_1.getProjectRootFilenames)(file);
13
13
  const identifiedLanguages = projectRootFilenames.reduce((accumulator, filename) => {
14
14
  const deducedLanguages = (0, reduceIdentifiedLanguages_1.deduceLanguage)(filename);
15
15
  return [...accumulator, ...deducedLanguages];
16
16
  }, []);
17
17
  if (Object.keys(identifiedLanguages).length === 0) {
18
- throw new Error(i18n_1.default.__('languageAnalysisNoLanguage', projectPath));
18
+ throw new Error(i18n_1.default.__('languageAnalysisNoLanguage', file));
19
19
  }
20
20
  return (0, reduceIdentifiedLanguages_1.reduceIdentifiedLanguages)(identifiedLanguages);
21
21
  }
@@ -1,9 +1,5 @@
1
1
  "use strict";
2
- const i18n = require('i18n');
3
2
  const { getHttpClient, handleResponseErrors } = require('../../utils/commonApi');
4
- const displaySuccessMessage = () => {
5
- console.log(i18n.__('catalogueSuccessCommand'));
6
- };
7
3
  const catalogueApplication = async (config) => {
8
4
  const client = getHttpClient(config);
9
5
  let appId;
@@ -13,6 +9,9 @@ const catalogueApplication = async (config) => {
13
9
  if (res.statusCode === 201) {
14
10
  appId = res.body.application.app_id;
15
11
  }
12
+ else if (doesMessagesContainAppId(res)) {
13
+ appId = tryRetrieveAppIdFromMessages(res.body.messages);
14
+ }
16
15
  else {
17
16
  handleResponseErrors(res, 'catalogue');
18
17
  }
@@ -22,6 +21,25 @@ const catalogueApplication = async (config) => {
22
21
  });
23
22
  return appId;
24
23
  };
24
+ const doesMessagesContainAppId = res => {
25
+ const regex = /(Application ID =)/;
26
+ if (res.statusCode === 400 &&
27
+ res.body.messages.filter(message => regex.exec(message))[0]) {
28
+ return true;
29
+ }
30
+ return false;
31
+ };
32
+ const tryRetrieveAppIdFromMessages = messages => {
33
+ let appId;
34
+ messages.forEach(message => {
35
+ if (message.includes('Application ID')) {
36
+ appId = message.split('=')[1].replace(/\s+/g, '');
37
+ }
38
+ });
39
+ return appId;
40
+ };
25
41
  module.exports = {
26
- catalogueApplication: catalogueApplication
42
+ catalogueApplication: catalogueApplication,
43
+ doesMessagesContainAppId,
44
+ tryRetrieveAppIdFromMessages
27
45
  };
@@ -1,23 +1,23 @@
1
1
  "use strict";
2
2
  const path = require('path');
3
3
  module.exports = exports = (analysis, next) => {
4
- const { projectPath, languageAnalysis } = analysis;
5
- languageAnalysis.identifiedLanguageInfo = getIdentifiedLanguageInfo(projectPath, languageAnalysis.identifiedLanguages);
4
+ const { file, languageAnalysis } = analysis;
5
+ languageAnalysis.identifiedLanguageInfo = getIdentifiedLanguageInfo(file, languageAnalysis.identifiedLanguages);
6
6
  next();
7
7
  };
8
- const getIdentifiedLanguageInfo = (projectPath, identifiedLanguages) => {
8
+ const getIdentifiedLanguageInfo = (file, identifiedLanguages) => {
9
9
  const [language] = Object.keys(identifiedLanguages);
10
10
  const { projectFilenames: [projectFilename], lockFilenames: [lockFilename] } = Object.values(identifiedLanguages)[0];
11
11
  let identifiedLanguageInfo = {
12
12
  language,
13
13
  projectFilename,
14
- projectFilePath: path.join(projectPath, projectFilename)
14
+ projectFilePath: path.join(file, projectFilename)
15
15
  };
16
16
  if (lockFilename) {
17
17
  identifiedLanguageInfo = {
18
18
  ...identifiedLanguageInfo,
19
19
  lockFilename,
20
- lockFilePath: path.join(projectPath, lockFilename)
20
+ lockFilePath: path.join(file, lockFilename)
21
21
  };
22
22
  }
23
23
  return identifiedLanguageInfo;
@@ -3,9 +3,9 @@ const fs = require('fs');
3
3
  const path = require('path');
4
4
  const i18n = require('i18n');
5
5
  module.exports = exports = (analysis, next) => {
6
- const { projectPath, languageAnalysis } = analysis;
6
+ const { file, languageAnalysis } = analysis;
7
7
  try {
8
- languageAnalysis.projectRootFilenames = getProjectRootFilenames(projectPath);
8
+ languageAnalysis.projectRootFilenames = getProjectRootFilenames(file);
9
9
  }
10
10
  catch (err) {
11
11
  next(err);
@@ -13,27 +13,27 @@ module.exports = exports = (analysis, next) => {
13
13
  }
14
14
  next();
15
15
  };
16
- const getProjectRootFilenames = projectPath => {
16
+ const getProjectRootFilenames = file => {
17
17
  let projectStats = null;
18
18
  try {
19
- projectStats = fs.statSync(projectPath);
19
+ projectStats = fs.statSync(file);
20
20
  }
21
21
  catch (err) {
22
- throw new Error(i18n.__('languageAnalysisProjectRootFileNameFailure', projectPath) +
22
+ throw new Error(i18n.__('languageAnalysisProjectRootFileNameFailure', file) +
23
23
  `${err.message}`);
24
24
  }
25
25
  if (projectStats.isDirectory()) {
26
26
  try {
27
- return fs.readdirSync(projectPath);
27
+ return fs.readdirSync(file);
28
28
  }
29
29
  catch (err) {
30
- throw new Error(i18n.__('languageAnalysisProjectRootFileNameReadError', projectPath) +
30
+ throw new Error(i18n.__('languageAnalysisProjectRootFileNameReadError', file) +
31
31
  `${err.message}`);
32
32
  }
33
33
  }
34
34
  if (projectStats.isFile()) {
35
- return [path.basename(projectPath)];
35
+ return [path.basename(file)];
36
36
  }
37
- throw new Error(i18n.__('languageAnalysisProjectRootFileNameMissingError'), projectPath);
37
+ throw new Error(i18n.__('languageAnalysisProjectRootFileNameMissingError'), file);
38
38
  };
39
39
  exports.getProjectRootFilenames = getProjectRootFilenames;
@@ -9,9 +9,9 @@ const checkIdentifiedLanguageHasProjectFile = require('./checkIdentifiedLanguage
9
9
  const checkIdentifiedLanguageHasLockFile = require('./checkIdentifiedLanguageHasLockFile');
10
10
  const getIdentifiedLanguageInfo = require('./getIdentifiedLanguageInfo');
11
11
  const { libraryAnalysisError } = require('../../common/errorHandling');
12
- module.exports = exports = (projectPath, callback, appId, config) => {
12
+ module.exports = exports = (file, callback, appId, config) => {
13
13
  const ae = new AnalysisEngine({
14
- projectPath,
14
+ file,
15
15
  appId,
16
16
  languageAnalysis: { appId: appId },
17
17
  config
@@ -10,12 +10,9 @@ const phpAE = require('../phpAnalysisEngine');
10
10
  const goAE = require('../goAnalysisEngine');
11
11
  const { vulnerabilityReport } = require('./report/reportingFeature');
12
12
  const { newSendSnapShot } = require('../languageAnalysisEngine/sendSnapshot');
13
- const fs = require('fs');
14
- const chalk = require('chalk');
15
- const saveFile = require('../../commands/audit/saveFile').default;
16
- const generateSbom = require('../../sbom/generateSbom').default;
17
- const { failSpinner, returnOra, startSpinner, succeedSpinner } = require('../../utils/oraWrapper');
13
+ const { returnOra, startSpinner, succeedSpinner } = require('../../utils/oraWrapper');
18
14
  const { pollForSnapshotCompletition } = require('./sendSnapshot');
15
+ const auditSave = require('../save');
19
16
  module.exports = exports = (err, analysis) => {
20
17
  const { identifiedLanguageInfo } = analysis.languageAnalysis;
21
18
  const catalogueAppId = analysis.languageAnalysis.appId;
@@ -40,10 +37,10 @@ module.exports = exports = (err, analysis) => {
40
37
  const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'));
41
38
  startSpinner(reportSpinner);
42
39
  const snapshotResponse = await newSendSnapShot(analysis, catalogueAppId);
43
- const pollResult = await pollForSnapshotCompletition(analysis.config, snapshotResponse.id, reportSpinner);
44
- succeedSpinner(reportSpinner, 'Contrast SCA analysis complete');
40
+ await pollForSnapshotCompletition(analysis.config, snapshotResponse.id, reportSpinner);
41
+ succeedSpinner(reportSpinner, i18n.__('auditSCAAnalysisComplete'));
45
42
  await vulnerabilityReport(analysis, catalogueAppId, snapshotResponse.id);
46
- await auditSave(config);
43
+ await auditSave.auditSave(config);
47
44
  };
48
45
  if (identifiedLanguageInfo.language === DOTNET) {
49
46
  dotnetAE(identifiedLanguageInfo, analysis.config, langCallback);
@@ -67,23 +64,3 @@ module.exports = exports = (err, analysis) => {
67
64
  goAE(identifiedLanguageInfo, analysis.config, langCallback);
68
65
  }
69
66
  };
70
- async function auditSave(config) {
71
- if (config.save) {
72
- if (config.save.toLowerCase() === 'sbom') {
73
- saveFile(config, await generateSbom(config));
74
- const filename = `${config.applicationId}-sbom-cyclonedx.json`;
75
- if (fs.existsSync(filename)) {
76
- console.log(i18n.__('auditSBOMSaveSuccess') + ` - ${filename}`);
77
- }
78
- else {
79
- console.log(chalk.yellow.bold(`\n Unable to save ${filename} Software Bill of Materials (SBOM)`));
80
- }
81
- }
82
- else {
83
- console.log(i18n.__('auditBadFiletypeSpecifiedForSave'));
84
- }
85
- }
86
- else if (config.save === null) {
87
- console.log(i18n.__('auditNoFiletypeSpecifiedForSave'));
88
- }
89
- }
@@ -36,7 +36,7 @@ const deduceLanguageScaAnalysis = filenames => {
36
36
  }
37
37
  if (isNodeProjectFilename(filename)) {
38
38
  deducedLanguages.push(filename);
39
- language = NODE;
39
+ language = JAVASCRIPT;
40
40
  }
41
41
  if (isRubyProjectFilename(filename)) {
42
42
  deducedLanguages.push(filename);
@@ -46,9 +46,16 @@ const deduceLanguageScaAnalysis = filenames => {
46
46
  deducedLanguages.push(filename);
47
47
  language = PYTHON;
48
48
  }
49
+ if (isPhpProjectFilename(filename)) {
50
+ deducedLanguages.push({ language: PHP, projectFilename: filename });
51
+ language = PHP;
52
+ }
49
53
  if (isNodeLockFilename(filename)) {
50
54
  deducedLanguages.push(filename);
51
- language = NODE;
55
+ language = JAVASCRIPT;
56
+ }
57
+ if (isPhpLockFilename(filename)) {
58
+ deducedLanguages.push({ language: PHP, lockFilename: filename });
52
59
  }
53
60
  if (isGoProjectFilename(filename)) {
54
61
  deducedLanguages.push({ language: GO, projectFilename: filename });
@@ -115,13 +122,13 @@ const reduceIdentifiedLanguages = identifiedLanguages => identifiedLanguages.red
115
122
  return accumulator;
116
123
  }, {});
117
124
  module.exports = exports = (analysis, next) => {
118
- const { projectPath, languageAnalysis, config } = analysis;
125
+ const { file, languageAnalysis, config } = analysis;
119
126
  let identifiedLanguages = languageAnalysis.projectRootFilenames.reduce((accumulator, filename) => {
120
127
  const deducedLanguages = deduceLanguage(filename);
121
128
  return [...accumulator, ...deducedLanguages];
122
129
  }, []);
123
130
  if (Object.keys(identifiedLanguages).length === 0) {
124
- next(new Error(i18n.__('languageAnalysisNoLanguage', projectPath)));
131
+ next(new Error(i18n.__('languageAnalysisNoLanguage', file)));
125
132
  return;
126
133
  }
127
134
  let language = config.language;
@@ -11,10 +11,11 @@ const chalk_1 = __importDefault(require("chalk"));
11
11
  const reportUtils_1 = require("./utils/reportUtils");
12
12
  const severityCountModel_1 = require("./models/severityCountModel");
13
13
  const reportOutputModel_1 = require("./models/reportOutputModel");
14
+ const constants_1 = require("../../../constants/constants");
14
15
  const createLibraryHeader = (id, numberOfVulnerableLibraries, numberOfCves) => {
15
16
  numberOfVulnerableLibraries === 1
16
- ? console.log(` Found 1 vulnerable library containing ${numberOfCves} CVE's`)
17
- : console.log(` Found ${numberOfVulnerableLibraries} vulnerable libraries containing ${numberOfCves} CVE's `);
17
+ ? console.log(`Found 1 vulnerable library containing ${numberOfCves} CVEs`)
18
+ : console.log(`Found ${numberOfVulnerableLibraries} vulnerable libraries containing ${numberOfCves} CVEs `);
18
19
  };
19
20
  exports.createLibraryHeader = createLibraryHeader;
20
21
  const getReport = async (config, reportId) => {
@@ -26,10 +27,6 @@ const getReport = async (config, reportId) => {
26
27
  return res.body;
27
28
  }
28
29
  else {
29
- console.log('config-------------------');
30
- console.log(config);
31
- console.log('reportId----------------');
32
- console.log(reportId);
33
30
  console.log(JSON.stringify(res));
34
31
  (0, commonApi_1.handleResponseErrors)(res, 'report');
35
32
  }
@@ -52,13 +49,20 @@ const printFormattedOutput = (libraries, config) => {
52
49
  const report = new reportListModel_1.ReportList();
53
50
  for (const library of libraries) {
54
51
  const { name, version } = (0, reportUtils_1.findNameAndVersion)(library, config);
55
- const newOutputModel = new reportListModel_1.ReportModelStructure(new reportListModel_1.ReportCompositeKey(name, version, (0, reportUtils_1.findHighestSeverityCVE)(library.cveArray)), library.cveArray);
52
+ const newOutputModel = new reportListModel_1.ReportModelStructure(new reportListModel_1.ReportCompositeKey(name, version, (0, reportUtils_1.findHighestSeverityCVE)(library.cveArray), (0, reportUtils_1.severityCountAllCVEs)(library.cveArray, new severityCountModel_1.SeverityCountModel()).getTotal), library.cveArray);
56
53
  report.reportOutputList.push(newOutputModel);
57
54
  }
58
- const orderedOutputListLowestFirst = (0, lodash_1.orderBy)(report.reportOutputList, reportListItem => reportListItem.compositeKey.highestSeverity.priority, ['desc']);
59
- let contrastHeaderNumCounter = 0;
60
- for (const reportModel of orderedOutputListLowestFirst) {
61
- contrastHeaderNumCounter++;
55
+ const outputOrderedByLowestSeverityAndLowestNumOfCvesFirst = (0, lodash_1.orderBy)(report.reportOutputList, [
56
+ (reportListItem) => {
57
+ return reportListItem.compositeKey.highestSeverity.priority;
58
+ },
59
+ (reportListItem) => {
60
+ return reportListItem.compositeKey.numberOfSeverities;
61
+ }
62
+ ], ['desc']);
63
+ let contrastHeaderNumCounter = outputOrderedByLowestSeverityAndLowestNumOfCvesFirst.length + 1;
64
+ for (const reportModel of outputOrderedByLowestSeverityAndLowestNumOfCvesFirst) {
65
+ contrastHeaderNumCounter--;
62
66
  const { libraryName, libraryVersion, highestSeverity } = reportModel.compositeKey;
63
67
  const numOfCVEs = reportModel.cveArray.length;
64
68
  const header = buildHeader(highestSeverity, contrastHeaderNumCounter, libraryName, libraryVersion, numOfCVEs);
@@ -66,12 +70,16 @@ const printFormattedOutput = (libraries, config) => {
66
70
  const reportOutputModel = new reportOutputModel_1.ReportOutputModel(header, body);
67
71
  console.log(reportOutputModel.header.vulnMessage, reportOutputModel.header.introducesMessage);
68
72
  console.log(reportOutputModel.body.issueMessage);
69
- console.log(reportOutputModel.body.adviceMessage);
73
+ console.log(reportOutputModel.body.adviceMessage + '\n');
74
+ }
75
+ const { criticalMessage, highMessage, mediumMessage, lowMessage, noteMessage, total } = buildFooter(libraries);
76
+ if (total > 1) {
77
+ console.log(`${criticalMessage} | ${highMessage} | ${mediumMessage} | ${lowMessage} | ${noteMessage}`);
70
78
  }
71
79
  };
72
80
  exports.printFormattedOutput = printFormattedOutput;
73
81
  function buildHeader(highestSeverity, contrastHeaderNum, libraryName, version, numOfCVEs) {
74
- const vulnerabilityPluralised = numOfCVEs > 1 ? 'Vulnerabilities' : 'Vulnerability';
82
+ const vulnerabilityPluralised = numOfCVEs > 1 ? 'vulnerabilities' : 'vulnerability';
75
83
  const formattedHeaderNum = buildFormattedHeaderNum(contrastHeaderNum);
76
84
  const vulnMessage = chalk_1.default
77
85
  .hex(highestSeverity.outputColour)
@@ -96,6 +104,24 @@ function buildBody(cveArray) {
96
104
  return new reportOutputModel_1.ReportOutputBodyModel(issueMessage, adviceMessage);
97
105
  }
98
106
  exports.buildBody = buildBody;
107
+ const buildFooter = (libraries) => {
108
+ const { critical, high, medium, low, note, getTotal } = (0, reportUtils_1.severityCountAllLibraries)(libraries);
109
+ const criticalMessage = chalk_1.default
110
+ .hex(constants_1.CRITICAL_COLOUR)
111
+ .bold(`${critical} Critical`);
112
+ const highMessage = chalk_1.default.hex(constants_1.HIGH_COLOUR).bold(`${high} High`);
113
+ const mediumMessage = chalk_1.default.hex(constants_1.MEDIUM_COLOUR).bold(`${medium} Medium`);
114
+ const lowMessage = chalk_1.default.hex(constants_1.LOW_COLOUR).bold(`${low} Low`);
115
+ const noteMessage = chalk_1.default.hex(constants_1.NOTE_COLOUR).bold(`${note} Note`);
116
+ return {
117
+ criticalMessage,
118
+ highMessage,
119
+ mediumMessage,
120
+ lowMessage,
121
+ noteMessage,
122
+ total: getTotal
123
+ };
124
+ };
99
125
  function buildFormattedHeaderNum(contrastHeaderNum) {
100
126
  let formattedHeaderNum;
101
127
  if (contrastHeaderNum < 10) {
@@ -15,10 +15,11 @@ class ReportModelStructure {
15
15
  }
16
16
  exports.ReportModelStructure = ReportModelStructure;
17
17
  class ReportCompositeKey {
18
- constructor(libraryName, libraryVersion, highestSeverity) {
18
+ constructor(libraryName, libraryVersion, highestSeverity, numberOfSeverities) {
19
19
  this.libraryName = libraryName;
20
20
  this.libraryVersion = libraryVersion;
21
21
  this.highestSeverity = highestSeverity;
22
+ this.numberOfSeverities = numberOfSeverities;
22
23
  }
23
24
  }
24
25
  exports.ReportCompositeKey = ReportCompositeKey;
@@ -9,5 +9,8 @@ class SeverityCountModel {
9
9
  this.low = 0;
10
10
  this.note = 0;
11
11
  }
12
+ get getTotal() {
13
+ return this.critical + this.high + this.medium + this.low + this.note;
14
+ }
12
15
  }
13
16
  exports.SeverityCountModel = SeverityCountModel;
@@ -1,28 +1,49 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.formatVulnerabilityOutput = exports.vulnerabilityReport = void 0;
6
+ exports.vulnerabilityReportV2 = exports.formatVulnerabilityOutput = exports.vulnerabilityReport = void 0;
4
7
  const commonReportingFunctions_1 = require("./commonReportingFunctions");
5
8
  const reportUtils_1 = require("./utils/reportUtils");
9
+ const i18n_1 = __importDefault(require("i18n"));
10
+ const chalk_1 = __importDefault(require("chalk"));
6
11
  async function vulnerabilityReport(analysis, applicationId, reportId) {
7
12
  const reportResponse = await (0, commonReportingFunctions_1.getReport)(analysis.config, reportId);
8
13
  if (reportResponse !== undefined) {
9
14
  const id = applicationId;
10
- const name = analysis.config.applicationName;
11
- formatVulnerabilityOutput(reportResponse.vulnerabilities, id, name, analysis.config);
15
+ formatVulnerabilityOutput(reportResponse.vulnerabilities, id, analysis.config);
12
16
  }
13
17
  }
14
18
  exports.vulnerabilityReport = vulnerabilityReport;
15
- function formatVulnerabilityOutput(libraryVulnerabilityResponse, id, name, config) {
16
- const vulnerableLibraries = (0, reportUtils_1.convertGenericToTypedLibraries)(libraryVulnerabilityResponse);
19
+ function formatVulnerabilityOutput(libraryVulnerabilityResponse, id, config) {
20
+ const vulnerableLibraries = (0, reportUtils_1.convertGenericToTypedLibraryVulns)(libraryVulnerabilityResponse);
17
21
  const numberOfVulnerableLibraries = vulnerableLibraries.length;
18
- let numberOfCves = 0;
19
- vulnerableLibraries.forEach(lib => (numberOfCves += lib.cveArray.length));
20
- (0, commonReportingFunctions_1.createLibraryHeader)(id, numberOfVulnerableLibraries, numberOfCves);
21
- const hasSomeVulnerabilitiesReported = (0, commonReportingFunctions_1.printVulnerabilityResponse)(vulnerableLibraries, config);
22
- return [
23
- hasSomeVulnerabilitiesReported,
24
- numberOfCves,
25
- (0, reportUtils_1.severityCountAllLibraries)(vulnerableLibraries)
26
- ];
22
+ if (numberOfVulnerableLibraries === 0) {
23
+ console.log(i18n_1.default.__('scanNoVulnerabilitiesFound'));
24
+ console.log(i18n_1.default.__('scanNoVulnerabilitiesFoundSecureCode'));
25
+ console.log(i18n_1.default.__('scanNoVulnerabilitiesFoundGoodWork'));
26
+ console.log(chalk_1.default.bold(`Found ${numberOfVulnerableLibraries} vulnerabilities`));
27
+ console.log(i18n_1.default.__('foundDetailedVulnerabilities', String(0), String(0), String(0), String(0), String(0)));
28
+ }
29
+ else {
30
+ let numberOfCves = 0;
31
+ vulnerableLibraries.forEach(lib => (numberOfCves += lib.cveArray.length));
32
+ (0, commonReportingFunctions_1.createLibraryHeader)(id, numberOfVulnerableLibraries, numberOfCves);
33
+ const hasSomeVulnerabilitiesReported = (0, commonReportingFunctions_1.printVulnerabilityResponse)(vulnerableLibraries, config);
34
+ return [
35
+ hasSomeVulnerabilitiesReported,
36
+ numberOfCves,
37
+ (0, reportUtils_1.severityCountAllLibraries)(vulnerableLibraries)
38
+ ];
39
+ }
27
40
  }
28
41
  exports.formatVulnerabilityOutput = formatVulnerabilityOutput;
42
+ async function vulnerabilityReportV2(config, reportId) {
43
+ const reportResponse = await (0, commonReportingFunctions_1.getReport)(config, reportId);
44
+ if (reportResponse !== undefined) {
45
+ const name = config.applicationName;
46
+ formatVulnerabilityOutput(reportResponse.vulnerabilities, config.applicationId, config);
47
+ }
48
+ }
49
+ exports.vulnerabilityReportV2 = vulnerabilityReportV2;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.findNameAndVersion = exports.severityCountSingleCVE = exports.severityCountAllCVEs = exports.severityCountAllLibraries = exports.convertGenericToTypedLibraries = exports.findCVESeverity = exports.findCVESeveritiesAndOrderByHighestPriority = exports.findHighestSeverityCVE = void 0;
6
+ exports.findNameAndVersion = exports.severityCountSingleCVE = exports.severityCountAllCVEs = exports.severityCountAllLibraries = exports.convertGenericToTypedLibraryVulns = exports.findCVESeverity = exports.findCVESeveritiesAndOrderByHighestPriority = exports.findHighestSeverityCVE = void 0;
7
7
  const reportLibraryModel_1 = require("../models/reportLibraryModel");
8
8
  const reportSeverityModel_1 = require("../models/reportSeverityModel");
9
9
  const constants_1 = __importDefault(require("../../../languageAnalysisEngine/constants"));
@@ -40,12 +40,12 @@ function findCVESeverity(cve) {
40
40
  }
41
41
  }
42
42
  exports.findCVESeverity = findCVESeverity;
43
- function convertGenericToTypedLibraries(libraries) {
43
+ function convertGenericToTypedLibraryVulns(libraries) {
44
44
  return Object.entries(libraries).map(([name, cveArray]) => {
45
45
  return new reportLibraryModel_1.ReportLibraryModel(name, cveArray);
46
46
  });
47
47
  }
48
- exports.convertGenericToTypedLibraries = convertGenericToTypedLibraries;
48
+ exports.convertGenericToTypedLibraryVulns = convertGenericToTypedLibraryVulns;
49
49
  function severityCountAllLibraries(vulnerableLibraries) {
50
50
  const severityCount = new severityCountModel_1.SeverityCountModel();
51
51
  vulnerableLibraries.forEach(lib => severityCountAllCVEs(lib.cveArray, severityCount));
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ const fs = require('fs');
3
+ const i18n = require('i18n');
4
+ const chalk = require('chalk');
5
+ const save = require('../commands/audit/saveFile');
6
+ const sbom = require('../sbom/generateSbom');
7
+ async function auditSave(config) {
8
+ if (config.save) {
9
+ if (config.save.toLowerCase() === 'sbom') {
10
+ save.saveFile(config, await sbom.generateSbom(config));
11
+ const filename = `${config.applicationId}-sbom-cyclonedx.json`;
12
+ if (fs.existsSync(filename)) {
13
+ console.log(i18n.__('auditSBOMSaveSuccess') + ` - ${filename}`);
14
+ }
15
+ else {
16
+ console.log(chalk.yellow.bold(`\n Unable to save ${filename} Software Bill of Materials (SBOM)`));
17
+ }
18
+ }
19
+ else {
20
+ console.log(i18n.__('auditBadFiletypeSpecifiedForSave'));
21
+ }
22
+ }
23
+ else if (config.save === null) {
24
+ console.log(i18n.__('auditNoFiletypeSpecifiedForSave'));
25
+ }
26
+ }
27
+ module.exports = {
28
+ auditSave
29
+ };
@@ -3,12 +3,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.startAudit = exports.dealWithNoAppId = void 0;
6
+ exports.getAppName = exports.startAudit = exports.dealWithNoAppId = void 0;
7
7
  const catalogueApplication_1 = require("../../audit/catalogueApplication/catalogueApplication");
8
8
  const commonApi_1 = __importDefault(require("../../audit/languageAnalysisEngine/commonApi"));
9
9
  const identifyLanguageAE = require('./../../audit/languageAnalysisEngine');
10
10
  const languageFactory = require('../../audit/languageAnalysisEngine/languageAnalysisFactory');
11
- const { v4: uuidv4 } = require('uuid');
12
11
  const dealWithNoAppId = async (config) => {
13
12
  let appID;
14
13
  try {
@@ -17,8 +16,11 @@ const dealWithNoAppId = async (config) => {
17
16
  return await (0, catalogueApplication_1.catalogueApplication)(config);
18
17
  }
19
18
  if (!appID && !config.applicationName) {
20
- config.applicationName = uuidv4();
21
- return await (0, catalogueApplication_1.catalogueApplication)(config);
19
+ config.applicationName = (0, exports.getAppName)(config.file);
20
+ appID = await commonApi_1.default.returnAppId(config);
21
+ if (!appID) {
22
+ return await (0, catalogueApplication_1.catalogueApplication)(config);
23
+ }
22
24
  }
23
25
  }
24
26
  catch (e) {
@@ -35,6 +37,20 @@ const startAudit = async (config) => {
35
37
  if (!config.applicationId) {
36
38
  config.applicationId = await (0, exports.dealWithNoAppId)(config);
37
39
  }
38
- identifyLanguageAE(config.projectPath, languageFactory, config.applicationId, config);
40
+ identifyLanguageAE(config.file, languageFactory, config.applicationId, config);
39
41
  };
40
42
  exports.startAudit = startAudit;
43
+ const getAppName = (file) => {
44
+ const last = file.charAt(file.length - 1);
45
+ if (last !== '/') {
46
+ return file.split('/').pop();
47
+ }
48
+ else {
49
+ const str = removeLastChar(file);
50
+ return str.split('/').pop();
51
+ }
52
+ };
53
+ exports.getAppName = getAppName;
54
+ const removeLastChar = (str) => {
55
+ return str.substring(0, str.length - 1);
56
+ };
@@ -46,7 +46,30 @@ const auditUsageGuide = (0, command_line_usage_1.default)([
46
46
  },
47
47
  {
48
48
  header: i18n_1.default.__('constantsAuditOptions'),
49
- optionList: constants_1.default.commandLineDefinitions.auditOptionDefinitions
49
+ optionList: constants_1.default.commandLineDefinitions.auditOptionDefinitions,
50
+ hide: [
51
+ 'application-id',
52
+ 'application-name',
53
+ 'organization-id',
54
+ 'api-key',
55
+ 'authorization',
56
+ 'host',
57
+ 'proxy',
58
+ 'help',
59
+ 'ff',
60
+ 'ignore-cert-errors',
61
+ 'verbose',
62
+ 'debug',
63
+ 'experimental',
64
+ 'tags',
65
+ 'sub-project',
66
+ 'code',
67
+ 'maven-settings-path',
68
+ 'language',
69
+ 'experimental',
70
+ 'app-groups',
71
+ 'metadata'
72
+ ]
50
73
  }
51
74
  ]);
52
75
  exports.auditUsageGuide = auditUsageGuide;
@@ -4,13 +4,19 @@ exports.processAudit = void 0;
4
4
  const auditController_1 = require("./auditController");
5
5
  const auditConfig_1 = require("./auditConfig");
6
6
  const help_1 = require("./help");
7
+ const scaAnalysis_1 = require("../scan/sca/scaAnalysis");
7
8
  const processAudit = async (argv) => {
8
9
  if (argv.indexOf('--help') != -1) {
9
10
  printHelpMessage();
10
11
  process.exit(0);
11
12
  }
12
13
  const config = (0, auditConfig_1.getAuditConfig)(argv);
13
- const auditResults = await (0, auditController_1.startAudit)(config);
14
+ if (config.experimental) {
15
+ await (0, scaAnalysis_1.processSca)(config);
16
+ }
17
+ else {
18
+ await (0, auditController_1.startAudit)(config);
19
+ }
14
20
  };
15
21
  exports.processAudit = processAudit;
16
22
  const printHelpMessage = () => {
@@ -3,9 +3,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.saveFile = void 0;
6
7
  const fs_1 = __importDefault(require("fs"));
7
- function saveFile(config, rawResults) {
8
+ const saveFile = (config, rawResults) => {
8
9
  const fileName = `${config.applicationId}-sbom-cyclonedx.json`;
9
10
  fs_1.default.writeFileSync(fileName, JSON.stringify(rawResults));
10
- }
11
- exports.default = saveFile;
11
+ };
12
+ exports.saveFile = saveFile;
13
+ module.exports = {
14
+ saveFile: exports.saveFile
15
+ };