@contrast/contrast 1.0.19 → 1.0.21

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 (66) hide show
  1. package/dist/audit/report/commonReportingFunctions.js +3 -4
  2. package/dist/audit/report/models/reportListModel.js +2 -1
  3. package/dist/audit/report/reportingFeature.js +1 -1
  4. package/dist/audit/report/utils/reportUtils.js +30 -11
  5. package/dist/cliConstants.js +13 -6
  6. package/dist/commands/audit/auditConfig.js +1 -2
  7. package/dist/commands/audit/help.js +2 -1
  8. package/dist/commands/audit/processAudit.js +1 -1
  9. package/dist/commands/fingerprint/fingerprintConfig.js +12 -0
  10. package/dist/commands/fingerprint/processFingerprint.js +14 -0
  11. package/dist/commands/learn/learn.js +9 -0
  12. package/dist/commands/learn/processLearn.js +10 -0
  13. package/dist/common/commonHelp.js +8 -1
  14. package/dist/constants/constants.js +1 -1
  15. package/dist/constants/locales.js +14 -3
  16. package/dist/index.js +8 -0
  17. package/dist/lambda/help.js +2 -1
  18. package/dist/scaAnalysis/common/auditReport.js +16 -60
  19. package/dist/scaAnalysis/common/commonReportingFunctionsSca.js +154 -0
  20. package/dist/scaAnalysis/common/models/ScaReportModel.js +45 -0
  21. package/dist/scaAnalysis/common/scaServicesUpload.js +4 -3
  22. package/dist/scaAnalysis/common/utils/reportUtilsSca.js +76 -0
  23. package/dist/scaAnalysis/java/analysis.js +1 -28
  24. package/dist/scaAnalysis/java/index.js +1 -13
  25. package/dist/scaAnalysis/scaAnalysis.js +155 -0
  26. package/dist/scan/autoDetection.js +2 -2
  27. package/dist/scan/fileUtils.js +2 -2
  28. package/dist/scan/formatScanOutput.js +19 -13
  29. package/dist/scan/help.js +2 -1
  30. package/dist/utils/paramsUtil/configStoreParams.js +1 -12
  31. package/dist/utils/paramsUtil/paramHandler.js +1 -7
  32. package/package.json +5 -1
  33. package/src/audit/report/commonReportingFunctions.js +7 -5
  34. package/src/audit/report/models/reportListModel.ts +12 -2
  35. package/src/audit/report/reportingFeature.ts +1 -1
  36. package/src/audit/report/utils/reportUtils.ts +4 -4
  37. package/src/cliConstants.js +15 -6
  38. package/src/commands/audit/auditConfig.js +1 -2
  39. package/src/commands/audit/help.js +2 -1
  40. package/src/commands/audit/processAudit.js +1 -1
  41. package/src/commands/fingerprint/fingerprintConfig.js +19 -0
  42. package/src/commands/fingerprint/processFingerprint.js +21 -0
  43. package/src/commands/learn/learn.js +10 -0
  44. package/src/commands/learn/processLearn.js +13 -0
  45. package/src/common/commonHelp.js +11 -1
  46. package/src/constants/constants.js +1 -1
  47. package/src/constants/locales.js +22 -3
  48. package/src/index.ts +11 -0
  49. package/src/lambda/help.ts +2 -1
  50. package/src/scaAnalysis/common/auditReport.js +25 -80
  51. package/src/scaAnalysis/common/commonReportingFunctionsSca.js +276 -0
  52. package/src/scaAnalysis/common/models/ScaReportModel.ts +81 -0
  53. package/src/scaAnalysis/common/scaServicesUpload.js +5 -3
  54. package/src/scaAnalysis/common/utils/reportUtilsSca.ts +123 -0
  55. package/src/scaAnalysis/java/analysis.js +1 -28
  56. package/src/scaAnalysis/java/index.js +1 -18
  57. package/src/scaAnalysis/scaAnalysis.js +206 -0
  58. package/src/scan/autoDetection.js +2 -2
  59. package/src/scan/fileUtils.js +2 -2
  60. package/src/scan/formatScanOutput.ts +28 -17
  61. package/src/scan/help.js +2 -1
  62. package/src/utils/getConfig.ts +0 -1
  63. package/src/utils/paramsUtil/configStoreParams.js +1 -14
  64. package/src/utils/paramsUtil/paramHandler.js +1 -9
  65. package/dist/commands/scan/sca/scaAnalysis.js +0 -155
  66. package/src/commands/scan/sca/scaAnalysis.js +0 -206
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ScaReportRemediationAdviceModel = exports.ScaReportVulnerabilityModel = exports.ScaReportModel = void 0;
4
+ class ScaReportModel {
5
+ constructor(library) {
6
+ this.uuid = library.uuid;
7
+ this.groupName = library.groupName;
8
+ this.artifactName = library.artifactName;
9
+ this.version = library.version;
10
+ this.hash = library.hash;
11
+ this.fileName = library.fileName;
12
+ this.libraryLanguage = library.libraryLanguage;
13
+ this.vulnerable = library.vulnerable;
14
+ this.privateLibrary = library.privateLibrary;
15
+ this.severity = library.severity;
16
+ this.releaseDate = library.releaseDate;
17
+ this.latestVersionReleaseDate = library.latestVersionReleaseDate;
18
+ this.latestVersion = library.latestVersion;
19
+ this.versionsBehind = library.versionsBehind;
20
+ this.vulnerabilities = library.vulnerabilities;
21
+ this.remediationAdvice = library.remediationAdvice;
22
+ }
23
+ }
24
+ exports.ScaReportModel = ScaReportModel;
25
+ class ScaReportVulnerabilityModel {
26
+ constructor(name, description, cvss2Vector, severityValue, severity, cvss3Vector, cvss3SeverityValue, cvss3Severity, hasCvss3) {
27
+ this.name = name;
28
+ this.description = description;
29
+ this.cvss2Vector = cvss2Vector;
30
+ this.severityValue = severityValue;
31
+ this.severity = severity;
32
+ this.cvss3Vector = cvss3Vector;
33
+ this.cvss3SeverityValue = cvss3SeverityValue;
34
+ this.cvss3Severity = cvss3Severity;
35
+ this.hasCvss3 = hasCvss3;
36
+ }
37
+ }
38
+ exports.ScaReportVulnerabilityModel = ScaReportVulnerabilityModel;
39
+ class ScaReportRemediationAdviceModel {
40
+ constructor(closestStableVersion, latestStableVersion) {
41
+ this.closestStableVersion = closestStableVersion;
42
+ this.latestStableVersion = latestStableVersion;
43
+ }
44
+ }
45
+ exports.ScaReportRemediationAdviceModel = ScaReportRemediationAdviceModel;
@@ -44,16 +44,17 @@ const scaTreeUpload = async (analysis, config) => {
44
44
  if (res.body.status === 'COMPLETED') {
45
45
  keepChecking = false;
46
46
  return client.scaServiceReport(config, reportID).then(res => {
47
- return [res.body, reportID];
47
+ const reportBody = res.body;
48
+ return { reportBody, reportID };
48
49
  });
49
50
  }
50
51
  });
51
52
  if (!keepChecking) {
52
- return [res, reportID];
53
+ return { reportArray: res.reportBody, reportID };
53
54
  }
54
55
  await requestUtils.sleep(5000);
55
56
  }
56
- return [res, reportID];
57
+ return { reportArray: res, reportID };
57
58
  };
58
59
  module.exports = {
59
60
  scaTreeUpload
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.severityCountSingleCVESca = exports.severityCountAllCVEsSca = exports.severityCountAllLibrariesSca = exports.convertGenericToTypedReportModelSca = exports.findCVESeveritySca = exports.orderByHighestPrioritySca = exports.findHighestSeverityCVESca = void 0;
4
+ const lodash_1 = require("lodash");
5
+ const constants_1 = require("../../../constants/constants");
6
+ const reportSeverityModel_1 = require("../../../audit/report/models/reportSeverityModel");
7
+ const ScaReportModel_1 = require("../models/ScaReportModel");
8
+ function findHighestSeverityCVESca(cveArray) {
9
+ const mappedToReportSeverityModels = cveArray.map(cve => findCVESeveritySca(cve));
10
+ return (0, lodash_1.orderBy)(mappedToReportSeverityModels, cve => cve?.priority)[0];
11
+ }
12
+ exports.findHighestSeverityCVESca = findHighestSeverityCVESca;
13
+ function orderByHighestPrioritySca(reportSeverityModel) {
14
+ return (0, lodash_1.orderBy)(reportSeverityModel, ['priority'], ['asc']);
15
+ }
16
+ exports.orderByHighestPrioritySca = orderByHighestPrioritySca;
17
+ function findCVESeveritySca(vulnerabilityModel) {
18
+ const { name } = vulnerabilityModel;
19
+ if (vulnerabilityModel.cvss3Severity === 'CRITICAL' ||
20
+ vulnerabilityModel.severity === 'CRITICAL') {
21
+ return new reportSeverityModel_1.ReportSeverityModel('CRITICAL', constants_1.CRITICAL_PRIORITY, constants_1.CRITICAL_COLOUR, name);
22
+ }
23
+ else if (vulnerabilityModel.cvss3Severity === 'HIGH' ||
24
+ vulnerabilityModel.severity === 'HIGH') {
25
+ return new reportSeverityModel_1.ReportSeverityModel('HIGH', constants_1.HIGH_PRIORITY, constants_1.HIGH_COLOUR, name);
26
+ }
27
+ else if (vulnerabilityModel.cvss3Severity === 'MEDIUM' ||
28
+ vulnerabilityModel.severity === 'MEDIUM') {
29
+ return new reportSeverityModel_1.ReportSeverityModel('MEDIUM', constants_1.MEDIUM_PRIORITY, constants_1.MEDIUM_COLOUR, name);
30
+ }
31
+ else if (vulnerabilityModel.cvss3Severity === 'LOW' ||
32
+ vulnerabilityModel.severity === 'LOW') {
33
+ return new reportSeverityModel_1.ReportSeverityModel('LOW', constants_1.LOW_PRIORITY, constants_1.LOW_COLOUR, name);
34
+ }
35
+ else if (vulnerabilityModel.cvss3Severity === 'NOTE' ||
36
+ vulnerabilityModel.severity === 'NOTE') {
37
+ return new reportSeverityModel_1.ReportSeverityModel('NOTE', constants_1.NOTE_PRIORITY, constants_1.NOTE_COLOUR, name);
38
+ }
39
+ }
40
+ exports.findCVESeveritySca = findCVESeveritySca;
41
+ function convertGenericToTypedReportModelSca(reportArray) {
42
+ return reportArray.map((library) => {
43
+ return new ScaReportModel_1.ScaReportModel(library);
44
+ });
45
+ }
46
+ exports.convertGenericToTypedReportModelSca = convertGenericToTypedReportModelSca;
47
+ function severityCountAllLibrariesSca(vulnerableLibraries, severityCount) {
48
+ vulnerableLibraries.forEach(lib => severityCountAllCVEsSca(lib.vulnerabilities, severityCount));
49
+ return severityCount;
50
+ }
51
+ exports.severityCountAllLibrariesSca = severityCountAllLibrariesSca;
52
+ function severityCountAllCVEsSca(cveArray, severityCount) {
53
+ const severityCountInner = severityCount;
54
+ cveArray.forEach(cve => severityCountSingleCVESca(cve, severityCountInner));
55
+ return severityCountInner;
56
+ }
57
+ exports.severityCountAllCVEsSca = severityCountAllCVEsSca;
58
+ function severityCountSingleCVESca(cve, severityCount) {
59
+ if (cve.cvss3Severity === 'CRITICAL' || cve.severity === 'CRITICAL') {
60
+ severityCount.critical += 1;
61
+ }
62
+ else if (cve.cvss3Severity === 'HIGH' || cve.severity === 'HIGH') {
63
+ severityCount.high += 1;
64
+ }
65
+ else if (cve.cvss3Severity === 'MEDIUM' || cve.severity === 'MEDIUM') {
66
+ severityCount.medium += 1;
67
+ }
68
+ else if (cve.cvss3Severity === 'LOW' || cve.severity === 'LOW') {
69
+ severityCount.low += 1;
70
+ }
71
+ else if (cve.cvss3Severity === 'NOTE' || cve.severity === 'NOTE') {
72
+ severityCount.note += 1;
73
+ }
74
+ return severityCount;
75
+ }
76
+ exports.severityCountSingleCVESca = severityCountSingleCVESca;
@@ -111,34 +111,7 @@ const getJavaBuildDeps = (config, files) => {
111
111
  console.log(err.message.toString());
112
112
  }
113
113
  };
114
- const agreementPrompt = async (config) => {
115
- const rl = readLine.createInterface({
116
- input: process.stdin,
117
- output: process.stdout
118
- });
119
- return new Promise((resolve, reject) => {
120
- rl.question('❔ Do you want to continue? Type Y or N', async (input) => {
121
- if (input.toLowerCase() === 'yes' || input.toLowerCase() === 'y') {
122
- config.javaAgreement = paramHandler.setAgreement(true);
123
- rl.close();
124
- resolve(config);
125
- }
126
- else if (input.toLowerCase() === 'no' || input.toLowerCase() === 'n') {
127
- rl.close();
128
- resolve(process.exit(1));
129
- }
130
- else {
131
- rl.close();
132
- console.log('Invalid Input: Exiting');
133
- resolve(process.exit(1));
134
- }
135
- });
136
- }).catch(e => {
137
- throw e;
138
- });
139
- };
140
114
  module.exports = {
141
115
  getJavaBuildDeps,
142
- determineProjectTypeAndCwd,
143
- agreementPrompt
116
+ determineProjectTypeAndCwd
144
117
  };
@@ -3,13 +3,10 @@ const analysis = require('./analysis');
3
3
  const { parseBuildDeps } = require('./javaBuildDepsParser');
4
4
  const { createJavaTSMessage } = require('../common/formatMessage');
5
5
  const { parseDependenciesForSCAServices } = require('../common/scaParserForGoAndJava');
6
- const chalk = require('chalk');
7
- const _ = require('lodash');
8
6
  const javaAnalysis = async (config, languageFiles) => {
9
7
  languageFiles.JAVA.forEach(file => {
10
8
  file.replace('build.gradle.kts', 'build.gradle');
11
9
  });
12
- await getAgreement(config);
13
10
  const javaDeps = buildJavaTree(config, languageFiles.JAVA);
14
11
  if (config.experimental) {
15
12
  return parseDependenciesForSCAServices(javaDeps);
@@ -18,19 +15,10 @@ const javaAnalysis = async (config, languageFiles) => {
18
15
  return createJavaTSMessage(javaDeps);
19
16
  }
20
17
  };
21
- const getAgreement = async (config) => {
22
- console.log(chalk.bold('Java project detected'));
23
- console.log('Java analysis uses maven / gradle which are potentially susceptible to command injection. Be sure that the code you are running Contrast CLI on is trusted before continuing.');
24
- if (!process.env.CI && !config?.javaAgreement) {
25
- return await analysis.agreementPrompt(config);
26
- }
27
- return config;
28
- };
29
18
  const buildJavaTree = (config, files) => {
30
19
  const javaBuildDeps = analysis.getJavaBuildDeps(config, files);
31
20
  return parseBuildDeps(config, javaBuildDeps);
32
21
  };
33
22
  module.exports = {
34
- javaAnalysis,
35
- getAgreement
23
+ javaAnalysis
36
24
  };
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ const { supportedLanguages: { JAVA, GO, PYTHON, RUBY, JAVASCRIPT, NODE, PHP, DOTNET } } = require('../constants/constants');
3
+ const { pollForSnapshotCompletion } = require('../audit/languageAnalysisEngine/sendSnapshot');
4
+ const { returnOra, startSpinner, succeedSpinner } = require('../utils/oraWrapper');
5
+ const { vulnerabilityReportV2 } = require('../audit/report/reportingFeature');
6
+ const autoDetection = require('../scan/autoDetection');
7
+ const treeUpload = require('./common/treeUpload');
8
+ const auditController = require('../commands/audit/auditController');
9
+ const rootFile = require('../audit/languageAnalysisEngine/getProjectRootFilenames');
10
+ const path = require('path');
11
+ const i18n = require('i18n');
12
+ const auditSave = require('../audit/save');
13
+ const { auditUsageGuide } = require('../commands/audit/help');
14
+ const repoMode = require('./repoMode');
15
+ const { dotNetAnalysis } = require('./dotnet');
16
+ const { goAnalysis } = require('./go/goAnalysis');
17
+ const { phpAnalysis } = require('./php');
18
+ const { rubyAnalysis } = require('./ruby');
19
+ const { pythonAnalysis } = require('./python');
20
+ const javaAnalysis = require('./java');
21
+ const jsAnalysis = require('./javascript');
22
+ const auditReport = require('./common/auditReport');
23
+ const scaUpload = require('./common/scaServicesUpload');
24
+ const settingsHelper = require('../utils/settingsHelper');
25
+ const chalk = require('chalk');
26
+ const saveResults = require('../scan/saveResults');
27
+ const { convertGenericToTypedReportModelSca } = require('./common/utils/reportUtilsSca');
28
+ const processSca = async (config) => {
29
+ config = await settingsHelper.getSettings(config);
30
+ const startTime = performance.now();
31
+ let filesFound;
32
+ if (config.help) {
33
+ console.log(auditUsageGuide);
34
+ process.exit(0);
35
+ }
36
+ const projectStats = await rootFile.getProjectStats(config.file);
37
+ let pathWithFile = projectStats.isFile();
38
+ config.fileName = config.file;
39
+ config.file = pathWithFile
40
+ ? rootFile.getDirectoryFromPathGiven(config.file).concat('/')
41
+ : config.file;
42
+ filesFound = await autoDetection.autoDetectAuditFilesAndLanguages(config.file);
43
+ autoDetection.dealWithMultiJava(filesFound);
44
+ if (filesFound.length > 1 && pathWithFile) {
45
+ filesFound = filesFound.filter(i => Object.values(i)[0].includes(path.basename(config.fileName)));
46
+ }
47
+ let messageToSend = undefined;
48
+ if (filesFound.length === 1) {
49
+ switch (Object.keys(filesFound[0])[0]) {
50
+ case JAVA:
51
+ config.language = JAVA;
52
+ if (config.mode === 'repo') {
53
+ try {
54
+ return repoMode.buildRepo(config, filesFound[0]);
55
+ }
56
+ catch (e) {
57
+ throw new Error('Unable to build in repository mode. Check your project file');
58
+ }
59
+ }
60
+ else {
61
+ messageToSend = await javaAnalysis.javaAnalysis(config, filesFound[0]);
62
+ }
63
+ break;
64
+ case JAVASCRIPT:
65
+ messageToSend = await jsAnalysis.jsAnalysis(config, filesFound[0]);
66
+ config.language = NODE;
67
+ break;
68
+ case PYTHON:
69
+ messageToSend = pythonAnalysis(config, filesFound[0]);
70
+ config.language = PYTHON;
71
+ break;
72
+ case RUBY:
73
+ messageToSend = rubyAnalysis(config, filesFound[0]);
74
+ config.language = RUBY;
75
+ break;
76
+ case PHP:
77
+ messageToSend = phpAnalysis(config, filesFound[0]);
78
+ config.language = PHP;
79
+ break;
80
+ case GO:
81
+ messageToSend = goAnalysis(config, filesFound[0]);
82
+ config.language = GO;
83
+ break;
84
+ case DOTNET:
85
+ if (config.experimental) {
86
+ console.log(`${chalk.bold('\n.NET project found\n')} Language type is unsupported.`);
87
+ return;
88
+ }
89
+ else {
90
+ messageToSend = dotNetAnalysis(config, filesFound[0]);
91
+ config.language = DOTNET;
92
+ break;
93
+ }
94
+ default:
95
+ console.log('No supported language detected in project path');
96
+ return;
97
+ }
98
+ if (!config.applicationId) {
99
+ config.applicationId = await auditController.dealWithNoAppId(config);
100
+ }
101
+ if (config.experimental) {
102
+ console.log('');
103
+ const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'));
104
+ startSpinner(reportSpinner);
105
+ const { reportArray, reportId } = await scaUpload.scaTreeUpload(messageToSend, config);
106
+ const reportModelLibraryList = convertGenericToTypedReportModelSca(reportArray);
107
+ auditReport.processAuditReport(config, reportModelLibraryList);
108
+ succeedSpinner(reportSpinner, i18n.__('auditSCAAnalysisComplete'));
109
+ if (config.save !== undefined) {
110
+ await auditSave.auditSave(config, reportId);
111
+ }
112
+ else {
113
+ console.log('Use contrast audit --save to generate an SBOM');
114
+ }
115
+ const endTime = performance.now() - startTime;
116
+ const scanDurationMs = endTime - startTime;
117
+ console.log(`----- completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`);
118
+ }
119
+ else {
120
+ console.log('');
121
+ const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'));
122
+ startSpinner(reportSpinner);
123
+ const snapshotResponse = await treeUpload.commonSendSnapShot(messageToSend, config);
124
+ await pollForSnapshotCompletion(config, snapshotResponse.id, reportSpinner);
125
+ succeedSpinner(reportSpinner, i18n.__('auditSCAAnalysisComplete'));
126
+ await vulnerabilityReportV2(config, snapshotResponse.id);
127
+ if (config.save !== undefined) {
128
+ await auditSave.auditSave(config);
129
+ }
130
+ else {
131
+ console.log('\nUse contrast audit --save to generate an SBOM');
132
+ }
133
+ const endTime = performance.now() - startTime;
134
+ const scanDurationMs = endTime - startTime;
135
+ console.log(`----- completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`);
136
+ }
137
+ }
138
+ else {
139
+ if (filesFound.length === 0) {
140
+ console.log(i18n.__('languageAnalysisNoLanguage'));
141
+ console.log(i18n.__('languageAnalysisNoLanguageHelpLine'));
142
+ throw new Error();
143
+ }
144
+ else {
145
+ console.log(chalk.bold(`\nMultiple language files detected \n`));
146
+ filesFound.forEach(file => {
147
+ console.log(`${Object.keys(file)[0]} : `, Object.values(file)[0]);
148
+ });
149
+ throw new Error(`Please use --file to audit one language only. \nExample: contrast audit --file package-lock.json`);
150
+ }
151
+ }
152
+ };
153
+ module.exports = {
154
+ processSca
155
+ };
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  const i18n = require('i18n');
3
3
  const fileFinder = require('./fileUtils');
4
- const autoDetectFingerprintInfo = async (filePath) => {
5
- let complexObj = await fileFinder.findAllFiles(filePath);
4
+ const autoDetectFingerprintInfo = async (filePath, depth) => {
5
+ let complexObj = await fileFinder.findAllFiles(filePath, depth);
6
6
  let result = [];
7
7
  let count = 0;
8
8
  complexObj.forEach(i => {
@@ -10,7 +10,7 @@ const findFile = async () => {
10
10
  onlyFiles: true
11
11
  });
12
12
  };
13
- const findAllFiles = async (filePath) => {
13
+ const findAllFiles = async (filePath, depth = 2) => {
14
14
  const result = await fg([
15
15
  '**/pom.xml',
16
16
  '**/build.gradle',
@@ -22,7 +22,7 @@ const findAllFiles = async (filePath) => {
22
22
  '**/go.mod'
23
23
  ], {
24
24
  dot: false,
25
- deep: 2,
25
+ deep: depth,
26
26
  onlyFiles: true,
27
27
  absolute: true,
28
28
  cwd: filePath ? filePath : process.cwd()
@@ -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.assignBySeverity = exports.stripTags = exports.getCodeFlowInfo = exports.getSourceLineNumber = exports.getLocationsSyncInfo = exports.editVulName = exports.getDefaultView = exports.formatLinks = exports.formatScanOutput = void 0;
6
+ exports.assignBySeverity = exports.stripTags = exports.getCodeFlowInfo = exports.getSourceLineNumber = exports.getLocationsSyncInfo = exports.editVulName = exports.doAddSourceLineNumber = exports.getDefaultView = exports.formatLinks = exports.formatScanOutput = void 0;
7
7
  const i18n_1 = __importDefault(require("i18n"));
8
8
  const chalk_1 = __importDefault(require("chalk"));
9
9
  const groupedResultsModel_1 = require("./models/groupedResultsModel");
@@ -12,24 +12,25 @@ const cli_table3_1 = __importDefault(require("cli-table3"));
12
12
  const constants_1 = require("../constants/constants");
13
13
  const commonReportingFunctions_1 = require("../audit/report/commonReportingFunctions");
14
14
  function formatScanOutput(scanResults) {
15
- const { scanResultsInstances } = scanResults;
16
- const projectOverview = (0, commonReportingFunctions_1.getSeverityCounts)(scanResultsInstances.content);
17
- if (scanResultsInstances.content.length === 0) {
15
+ const { content } = scanResults.scanResultsInstances;
16
+ const { language } = scanResults.scanDetail;
17
+ const severityCounts = (0, commonReportingFunctions_1.getSeverityCounts)(content);
18
+ if (content.length === 0) {
18
19
  console.log(i18n_1.default.__('scanNoVulnerabilitiesFound'));
19
20
  console.log(i18n_1.default.__('scanNoVulnerabilitiesFoundSecureCode'));
20
21
  console.log(i18n_1.default.__('scanNoVulnerabilitiesFoundGoodWork'));
21
22
  }
22
23
  else {
23
- const message = projectOverview.critical || projectOverview.high
24
+ const message = severityCounts.critical || severityCounts.high
24
25
  ? 'Here are your top priorities to fix'
25
26
  : "No major issues, here's what we found";
26
27
  console.log(chalk_1.default.bold(message));
27
28
  console.log();
28
- let defaultView = getDefaultView(scanResultsInstances.content);
29
+ const defaultView = getDefaultView(content, language);
29
30
  let count = 0;
30
31
  defaultView.forEach(entry => {
31
32
  count++;
32
- let table = new cli_table3_1.default({
33
+ const table = new cli_table3_1.default({
33
34
  chars: {
34
35
  top: '',
35
36
  'top-mid': '',
@@ -90,8 +91,8 @@ function formatScanOutput(scanResults) {
90
91
  console.log();
91
92
  });
92
93
  }
93
- (0, commonReportingFunctions_1.printVulnInfo)(projectOverview);
94
- return projectOverview;
94
+ (0, commonReportingFunctions_1.printVulnInfo)(severityCounts);
95
+ return severityCounts;
95
96
  }
96
97
  exports.formatScanOutput = formatScanOutput;
97
98
  function formatLinks(objName, entry) {
@@ -107,7 +108,7 @@ function formatLinks(objName, entry) {
107
108
  }
108
109
  }
109
110
  exports.formatLinks = formatLinks;
110
- function getDefaultView(content) {
111
+ function getDefaultView(content, language) {
111
112
  const groupTypeResults = [];
112
113
  content.forEach(resultEntry => {
113
114
  const groupResultsObj = new groupedResultsModel_1.GroupedResultsModel(resultEntry.ruleId);
@@ -118,8 +119,7 @@ function getDefaultView(content) {
118
119
  groupResultsObj.learn = resultEntry.learn;
119
120
  groupResultsObj.message = resultEntry.message?.text
120
121
  ? editVulName(resultEntry.message.text) +
121
- ':' +
122
- getSourceLineNumber(resultEntry)
122
+ doAddSourceLineNumber(resultEntry, language)
123
123
  : '';
124
124
  groupResultsObj.codePath = getLocationsSyncInfo(resultEntry);
125
125
  groupTypeResults.push(groupResultsObj);
@@ -128,6 +128,12 @@ function getDefaultView(content) {
128
128
  return (0, lodash_1.sortBy)(groupTypeResults, ['priority']);
129
129
  }
130
130
  exports.getDefaultView = getDefaultView;
131
+ function doAddSourceLineNumber(resultEntry, language) {
132
+ return language !== constants_1.supportedLanguagesScan.JAVASCRIPT
133
+ ? ':' + getSourceLineNumber(resultEntry)
134
+ : '';
135
+ }
136
+ exports.doAddSourceLineNumber = doAddSourceLineNumber;
131
137
  function editVulName(message) {
132
138
  return message.substring(message.indexOf(' in '));
133
139
  }
@@ -143,7 +149,7 @@ function getLocationsSyncInfo(resultEntry) {
143
149
  exports.getLocationsSyncInfo = getLocationsSyncInfo;
144
150
  function getSourceLineNumber(resultEntry) {
145
151
  const locationsLineNumber = resultEntry.locations[0]?.physicalLocation?.region?.startLine || '';
146
- let codeFlowLineNumber = getCodeFlowInfo(resultEntry);
152
+ const codeFlowLineNumber = getCodeFlowInfo(resultEntry);
147
153
  return codeFlowLineNumber ? codeFlowLineNumber : locationsLineNumber;
148
154
  }
149
155
  exports.getSourceLineNumber = getSourceLineNumber;
package/dist/scan/help.js CHANGED
@@ -43,7 +43,8 @@ const scanUsageGuide = commandLineUsage([
43
43
  optionList: constants.commandLineDefinitions.scanAdvancedOptionDefinitionsForHelp
44
44
  },
45
45
  commonHelpLinks()[0],
46
- commonHelpLinks()[1]
46
+ commonHelpLinks()[1],
47
+ commonHelpLinks()[2]
47
48
  ]);
48
49
  module.exports = {
49
50
  scanUsageGuide
@@ -15,15 +15,4 @@ const getAuth = () => {
15
15
  }
16
16
  return ContrastConfToUse;
17
17
  };
18
- const getAgreement = () => {
19
- const ContrastConf = config.localConfig(APP_NAME, APP_VERSION);
20
- let ContrastConfToUse = {};
21
- ContrastConfToUse.javaAgreement = ContrastConf.get('javaAgreement');
22
- return ContrastConfToUse;
23
- };
24
- const setAgreement = agreement => {
25
- const ContrastConf = config.localConfig(APP_NAME, APP_VERSION);
26
- ContrastConf.set('javaAgreement', agreement);
27
- return agreement;
28
- };
29
- module.exports = { getAuth, getAgreement, setAgreement };
18
+ module.exports = { getAuth };
@@ -22,10 +22,4 @@ const getAuth = params => {
22
22
  process.exit(1);
23
23
  }
24
24
  };
25
- const getAgreement = () => {
26
- return configStoreParams.getAgreement();
27
- };
28
- const setAgreement = answer => {
29
- return configStoreParams.setAgreement(answer);
30
- };
31
- module.exports = { getAuth, getAgreement, setAgreement };
25
+ module.exports = { getAuth };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrast/contrast",
3
- "version": "1.0.19",
3
+ "version": "1.0.21",
4
4
  "description": "Contrast Security's command line tool",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -15,6 +15,10 @@
15
15
  {
16
16
  "name": "Andrew Shanks",
17
17
  "email": "andrew.shanks@contrastsecurity.com"
18
+ },
19
+ {
20
+ "name": "Oisín Cassidy",
21
+ "email": "oisin.cassidy@contrastsecurity.com"
18
22
  }
19
23
  ],
20
24
  "license": "ISC",
@@ -108,7 +108,8 @@ const printFormattedOutput = (
108
108
  new SeverityCountModel()
109
109
  ).getTotal
110
110
  ),
111
- library.cveArray
111
+ library.cveArray,
112
+ null
112
113
  )
113
114
  report.reportOutputList.push(newOutputModel)
114
115
  }
@@ -131,6 +132,7 @@ const printFormattedOutput = (
131
132
  contrastHeaderNumCounter++
132
133
  const { libraryName, libraryVersion, highestSeverity } =
133
134
  reportModel.compositeKey
135
+
134
136
  const numOfCVEs = reportModel.cveArray.length
135
137
 
136
138
  const table = getReportTable()
@@ -236,9 +238,11 @@ function buildHeader(
236
238
  }
237
239
 
238
240
  function buildBody(cveArray, advice) {
239
- let assignPriorityToVulns = cveArray.map(result => findCVESeverity(result))
241
+ const orderedCvesWithSeverityAssigned = orderByHighestPriority(
242
+ cveArray.map(cve => findCVESeverity(cve))
243
+ )
240
244
 
241
- const issueMessage = getIssueRow(assignPriorityToVulns)
245
+ const issueMessage = getIssueRow(orderedCvesWithSeverityAssigned)
242
246
 
243
247
  //todo different advice based on remediationGuidance being available or now
244
248
  // console.log(advice)
@@ -254,7 +258,6 @@ function buildBody(cveArray, advice) {
254
258
  }
255
259
 
256
260
  function getIssueRow(cveArray) {
257
- orderByHighestPriority(cveArray)
258
261
  const cveMessagesList = getIssueCveMsgList(cveArray)
259
262
  return [chalk.bold('Issue'), ':', `${cveMessagesList.join(', ')}`]
260
263
  }
@@ -301,7 +304,6 @@ const getIssueCveMsgList = results => {
301
304
  const cveMessages = []
302
305
 
303
306
  results.forEach(reportSeverityModel => {
304
- // @ts-ignore
305
307
  const { colour, severity, name } = reportSeverityModel
306
308
 
307
309
  const severityShorthand = chalk
@@ -1,5 +1,9 @@
1
1
  import { ReportSeverityModel } from './reportSeverityModel'
2
2
  import { ReportCVEModel } from './reportLibraryModel'
3
+ import {
4
+ ScaReportRemediationAdviceModel,
5
+ ScaReportVulnerabilityModel
6
+ } from '../../../scaAnalysis/common/models/ScaReportModel'
3
7
 
4
8
  export class ReportList {
5
9
  reportOutputList: ReportModelStructure[]
@@ -11,11 +15,17 @@ export class ReportList {
11
15
 
12
16
  export class ReportModelStructure {
13
17
  compositeKey: ReportCompositeKey
14
- cveArray: ReportCVEModel[]
18
+ cveArray: ReportCVEModel[] | ScaReportVulnerabilityModel[]
19
+ remediationAdvice: ScaReportRemediationAdviceModel | null
15
20
 
16
- constructor(compositeKey: ReportCompositeKey, cveArray: ReportCVEModel[]) {
21
+ constructor(
22
+ compositeKey: ReportCompositeKey,
23
+ cveArray: ReportCVEModel[] | ScaReportVulnerabilityModel[],
24
+ remediationAdvice: ScaReportRemediationAdviceModel | null
25
+ ) {
17
26
  this.compositeKey = compositeKey
18
27
  this.cveArray = cveArray
28
+ this.remediationAdvice = remediationAdvice
19
29
  }
20
30
  }
21
31
 
@@ -87,7 +87,7 @@ export async function vulnerabilityReportV2(config: any, reportId: string) {
87
87
  const reportResponse = await getReport(config, reportId)
88
88
 
89
89
  if (reportResponse !== undefined) {
90
- let output = formatVulnerabilityOutput(
90
+ const output = formatVulnerabilityOutput(
91
91
  reportResponse.vulnerabilities,
92
92
  config.applicationId,
93
93
  config,