@contrast/contrast 1.0.4 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierignore +0 -3
- package/dist/audit/autodetection/autoDetectLanguage.js +32 -0
- package/dist/audit/catalogueApplication/catalogueApplication.js +2 -11
- package/dist/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +4 -2
- package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +2 -1
- package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +2 -1
- package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +2 -1
- package/dist/audit/languageAnalysisEngine/languageAnalysisFactory.js +6 -2
- package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +39 -1
- package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +69 -30
- package/dist/audit/languageAnalysisEngine/report/models/reportOutputModel.js +24 -0
- package/dist/audit/languageAnalysisEngine/report/models/reportSeverityModel.js +3 -1
- package/dist/audit/languageAnalysisEngine/report/models/severityCountModel.js +13 -0
- package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +2 -2
- package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +56 -45
- package/dist/audit/languageAnalysisEngine/sendSnapshot.js +65 -17
- package/dist/commands/audit/auditConfig.js +8 -2
- package/dist/commands/audit/auditController.js +9 -3
- package/dist/commands/audit/processAudit.js +1 -1
- package/dist/commands/scan/processScan.js +7 -4
- package/dist/commands/scan/sca/scaAnalysis.js +60 -0
- package/dist/common/HTTPClient.js +50 -16
- package/dist/common/errorHandling.js +11 -16
- package/dist/common/versionChecker.js +1 -1
- package/dist/constants/constants.js +24 -2
- package/dist/constants/locales.js +31 -36
- package/dist/constants.js +20 -0
- package/dist/lambda/analytics.js +11 -0
- package/dist/lambda/lambda.js +35 -4
- package/dist/lambda/types.js +13 -0
- package/dist/scaAnalysis/common/formatMessage.js +35 -0
- package/dist/scaAnalysis/common/treeUpload.js +29 -0
- package/dist/scaAnalysis/go/goAnalysis.js +17 -0
- package/dist/scaAnalysis/go/goParseDeps.js +158 -0
- package/dist/scaAnalysis/go/goReadDepFile.js +23 -0
- package/dist/scaAnalysis/java/analysis.js +105 -0
- package/dist/scaAnalysis/java/index.js +18 -0
- package/dist/scaAnalysis/java/javaBuildDepsParser.js +339 -0
- package/dist/scaAnalysis/python/analysis.js +41 -0
- package/dist/scaAnalysis/python/index.js +10 -0
- package/dist/scaAnalysis/ruby/analysis.js +226 -0
- package/dist/scaAnalysis/ruby/index.js +10 -0
- package/dist/scan/autoDetection.js +50 -1
- package/dist/scan/fileUtils.js +80 -1
- package/dist/scan/formatScanOutput.js +213 -0
- package/dist/scan/help.js +3 -1
- package/dist/scan/models/groupedResultsModel.js +2 -1
- package/dist/scan/models/scanResultsModel.js +3 -1
- package/dist/scan/populateProjectIdAndProjectName.js +2 -1
- package/dist/scan/scan.js +6 -99
- package/dist/scan/scanConfig.js +6 -1
- package/dist/scan/scanController.js +26 -7
- package/dist/scan/scanResults.js +20 -20
- package/dist/utils/commonApi.js +4 -1
- package/dist/utils/oraWrapper.js +5 -1
- package/package.json +12 -7
- package/src/audit/autodetection/autoDetectLanguage.ts +40 -0
- package/src/audit/catalogueApplication/catalogueApplication.js +3 -16
- package/src/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +11 -8
- package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +2 -1
- package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +2 -1
- package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +2 -1
- package/src/audit/languageAnalysisEngine/languageAnalysisFactory.js +17 -5
- package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +76 -3
- package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +122 -40
- package/src/audit/languageAnalysisEngine/report/models/reportLibraryModel.ts +3 -3
- package/src/audit/languageAnalysisEngine/report/models/reportListModel.ts +15 -11
- package/src/audit/languageAnalysisEngine/report/models/reportOutputModel.ts +29 -0
- package/src/audit/languageAnalysisEngine/report/models/reportSeverityModel.ts +12 -3
- package/src/audit/languageAnalysisEngine/report/models/severityCountModel.ts +16 -0
- package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +3 -3
- package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +87 -65
- package/src/audit/languageAnalysisEngine/sendSnapshot.js +78 -25
- package/src/commands/audit/auditConfig.ts +12 -3
- package/src/commands/audit/auditController.ts +9 -3
- package/src/commands/audit/processAudit.ts +4 -1
- package/src/commands/scan/processScan.js +10 -4
- package/src/commands/scan/sca/scaAnalysis.js +83 -0
- package/src/common/HTTPClient.js +65 -25
- package/src/common/errorHandling.ts +14 -22
- package/src/common/versionChecker.ts +1 -1
- package/src/constants/constants.js +24 -2
- package/src/constants/locales.js +33 -50
- package/src/constants.js +22 -0
- package/src/lambda/analytics.ts +9 -0
- package/src/lambda/arn.ts +2 -1
- package/src/lambda/lambda.ts +37 -17
- package/src/lambda/types.ts +35 -0
- package/src/lambda/utils.ts +2 -7
- package/src/scaAnalysis/common/formatMessage.js +38 -0
- package/src/scaAnalysis/common/treeUpload.js +30 -0
- package/src/scaAnalysis/go/goAnalysis.js +19 -0
- package/src/scaAnalysis/go/goParseDeps.js +203 -0
- package/src/scaAnalysis/go/goReadDepFile.js +32 -0
- package/src/scaAnalysis/java/analysis.js +142 -0
- package/src/scaAnalysis/java/index.js +21 -0
- package/src/scaAnalysis/java/javaBuildDepsParser.js +404 -0
- package/src/scaAnalysis/python/analysis.js +48 -0
- package/src/scaAnalysis/python/index.js +11 -0
- package/src/scaAnalysis/ruby/analysis.js +282 -0
- package/src/scaAnalysis/ruby/index.js +11 -0
- package/src/scan/autoDetection.js +58 -1
- package/src/scan/fileUtils.js +99 -1
- package/src/scan/formatScanOutput.ts +249 -0
- package/src/scan/help.js +3 -1
- package/src/scan/models/groupedResultsModel.ts +7 -5
- package/src/scan/models/resultContentModel.ts +2 -2
- package/src/scan/models/scanResultsModel.ts +5 -2
- package/src/scan/populateProjectIdAndProjectName.js +3 -1
- package/src/scan/scan.ts +8 -136
- package/src/scan/scanConfig.js +5 -1
- package/src/scan/scanController.js +30 -10
- package/src/scan/scanResults.js +31 -18
- package/src/utils/commonApi.js +4 -1
- package/src/utils/oraWrapper.js +6 -1
package/.prettierignore
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.determineProjectLanguage = exports.identifyLanguages = void 0;
|
|
7
|
+
const i18n_1 = __importDefault(require("i18n"));
|
|
8
|
+
const reduceIdentifiedLanguages_1 = require("../languageAnalysisEngine/reduceIdentifiedLanguages");
|
|
9
|
+
const getProjectRootFilenames_1 = require("../languageAnalysisEngine/getProjectRootFilenames");
|
|
10
|
+
function identifyLanguages(config) {
|
|
11
|
+
const { projectPath } = config;
|
|
12
|
+
const projectRootFilenames = (0, getProjectRootFilenames_1.getProjectRootFilenames)(projectPath);
|
|
13
|
+
const identifiedLanguages = projectRootFilenames.reduce((accumulator, filename) => {
|
|
14
|
+
const deducedLanguages = (0, reduceIdentifiedLanguages_1.deduceLanguage)(filename);
|
|
15
|
+
return [...accumulator, ...deducedLanguages];
|
|
16
|
+
}, []);
|
|
17
|
+
if (Object.keys(identifiedLanguages).length === 0) {
|
|
18
|
+
throw new Error(i18n_1.default.__('languageAnalysisNoLanguage', projectPath));
|
|
19
|
+
}
|
|
20
|
+
return (0, reduceIdentifiedLanguages_1.reduceIdentifiedLanguages)(identifiedLanguages);
|
|
21
|
+
}
|
|
22
|
+
exports.identifyLanguages = identifyLanguages;
|
|
23
|
+
function determineProjectLanguage(reducedLanguages) {
|
|
24
|
+
const reducedLanguagesKeys = Object.keys(reducedLanguages);
|
|
25
|
+
if (reducedLanguagesKeys.length === 1) {
|
|
26
|
+
return reducedLanguagesKeys[0];
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
throw new Error('Detected multiple languages. Please specify a single language using --language');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.determineProjectLanguage = determineProjectLanguage;
|
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const i18n = require('i18n');
|
|
3
3
|
const { getHttpClient, handleResponseErrors } = require('../../utils/commonApi');
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
};
|
|
7
|
-
const displaySuccessMessage = (config, appId) => {
|
|
8
|
-
console.log('\n **************************' +
|
|
9
|
-
i18n.__('successHeader') +
|
|
10
|
-
'************************** \n');
|
|
11
|
-
console.log('\n' + i18n.__('catalogueSuccessCommand') + appId + '\n');
|
|
12
|
-
console.log(locationOfApp(config, appId));
|
|
13
|
-
console.log('\n *********************************************************** \n');
|
|
4
|
+
const displaySuccessMessage = () => {
|
|
5
|
+
console.log(i18n.__('catalogueSuccessCommand'));
|
|
14
6
|
};
|
|
15
7
|
const catalogueApplication = async (config) => {
|
|
16
8
|
const client = getHttpClient(config);
|
|
@@ -19,7 +11,6 @@ const catalogueApplication = async (config) => {
|
|
|
19
11
|
.catalogueCommand(config)
|
|
20
12
|
.then(res => {
|
|
21
13
|
if (res.statusCode === 201) {
|
|
22
|
-
displaySuccessMessage(config, res.body.application.app_id);
|
|
23
14
|
appId = res.body.application.app_id;
|
|
24
15
|
}
|
|
25
16
|
else {
|
|
@@ -142,10 +142,12 @@ const parseMvn = mvnDependancyTreeOutput => {
|
|
|
142
142
|
});
|
|
143
143
|
return parsedDepObj;
|
|
144
144
|
};
|
|
145
|
-
exports.shaveConsoleOutputUntilItFindsFirsDigraphMention =
|
|
145
|
+
exports.shaveConsoleOutputUntilItFindsFirsDigraphMention =
|
|
146
|
+
shaveConsoleOutputUntilItFindsFirsDigraphMention;
|
|
146
147
|
exports.getDigraphObjInfo = getDigraphObjInfo;
|
|
147
148
|
exports.createDigraphObjKey = createDigraphObjKey;
|
|
148
|
-
exports.turnDigraphDependanciesIntoArrOfInnerDep =
|
|
149
|
+
exports.turnDigraphDependanciesIntoArrOfInnerDep =
|
|
150
|
+
turnDigraphDependanciesIntoArrOfInnerDep;
|
|
149
151
|
exports.hasVersion = hasVersion;
|
|
150
152
|
exports.formatKeyName = formatKeyName;
|
|
151
153
|
exports.createOuterDependanciesAndType = createOuterDependanciesAndType;
|
|
@@ -21,4 +21,5 @@ const checkForMultipleIdentifiedLanguages = identifiedLanguages => {
|
|
|
21
21
|
throw new Error(errMsg);
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
|
-
exports.checkForMultipleIdentifiedLanguages =
|
|
24
|
+
exports.checkForMultipleIdentifiedLanguages =
|
|
25
|
+
checkForMultipleIdentifiedLanguages;
|
|
@@ -21,4 +21,5 @@ const checkForMultipleIdentifiedProjectFiles = identifiedLanguages => {
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
|
-
exports.checkForMultipleIdentifiedProjectFiles =
|
|
24
|
+
exports.checkForMultipleIdentifiedProjectFiles =
|
|
25
|
+
checkForMultipleIdentifiedProjectFiles;
|
|
@@ -20,4 +20,5 @@ const checkIdentifiedLanguageHasProjectFile = identifiedLanguages => {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
|
-
exports.checkIdentifiedLanguageHasProjectFile =
|
|
23
|
+
exports.checkIdentifiedLanguageHasProjectFile =
|
|
24
|
+
checkIdentifiedLanguageHasProjectFile;
|
|
@@ -14,6 +14,8 @@ const fs = require('fs');
|
|
|
14
14
|
const chalk = require('chalk');
|
|
15
15
|
const saveFile = require('../../commands/audit/saveFile').default;
|
|
16
16
|
const generateSbom = require('../../sbom/generateSbom').default;
|
|
17
|
+
const { failSpinner, returnOra, startSpinner, succeedSpinner } = require('../../utils/oraWrapper');
|
|
18
|
+
const { pollForSnapshotCompletition } = require('./sendSnapshot');
|
|
17
19
|
module.exports = exports = (err, analysis) => {
|
|
18
20
|
const { identifiedLanguageInfo } = analysis.languageAnalysis;
|
|
19
21
|
const catalogueAppId = analysis.languageAnalysis.appId;
|
|
@@ -35,11 +37,13 @@ module.exports = exports = (err, analysis) => {
|
|
|
35
37
|
err);
|
|
36
38
|
return process.exit(5);
|
|
37
39
|
}
|
|
38
|
-
|
|
40
|
+
const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'));
|
|
41
|
+
startSpinner(reportSpinner);
|
|
39
42
|
const snapshotResponse = await newSendSnapShot(analysis, catalogueAppId);
|
|
43
|
+
const pollResult = await pollForSnapshotCompletition(analysis.config, snapshotResponse.id, reportSpinner);
|
|
44
|
+
succeedSpinner(reportSpinner, 'Contrast SCA analysis complete');
|
|
40
45
|
await vulnerabilityReport(analysis, catalogueAppId, snapshotResponse.id);
|
|
41
46
|
await auditSave(config);
|
|
42
|
-
console.log('\n ***************CONTRAST OSS ANALYSIS COMPLETE************** \n');
|
|
43
47
|
};
|
|
44
48
|
if (identifiedLanguageInfo.language === DOTNET) {
|
|
45
49
|
dotnetAE(identifiedLanguageInfo, analysis.config, langCallback);
|
|
@@ -22,6 +22,42 @@ function isNodeLockFilename(filename) {
|
|
|
22
22
|
const isRubyLockFilename = filename => filename === 'Gemfile.lock';
|
|
23
23
|
const isPipfileLockLockFilename = filename => filename === 'Pipfile.lock';
|
|
24
24
|
const isGoProjectFilename = filename => filename === 'go.mod';
|
|
25
|
+
const deduceLanguageScaAnalysis = filenames => {
|
|
26
|
+
const deducedLanguages = [];
|
|
27
|
+
let language = '';
|
|
28
|
+
filenames.forEach(filename => {
|
|
29
|
+
if (isJavaMavenProjectFilename(filename)) {
|
|
30
|
+
deducedLanguages.push(filename);
|
|
31
|
+
language = JAVA;
|
|
32
|
+
}
|
|
33
|
+
if (isJavaGradleProjectFilename(filename)) {
|
|
34
|
+
deducedLanguages.push(filename);
|
|
35
|
+
language = JAVA;
|
|
36
|
+
}
|
|
37
|
+
if (isNodeProjectFilename(filename)) {
|
|
38
|
+
deducedLanguages.push(filename);
|
|
39
|
+
language = NODE;
|
|
40
|
+
}
|
|
41
|
+
if (isRubyProjectFilename(filename)) {
|
|
42
|
+
deducedLanguages.push(filename);
|
|
43
|
+
language = RUBY;
|
|
44
|
+
}
|
|
45
|
+
if (isPythonProjectFilename(filename)) {
|
|
46
|
+
deducedLanguages.push(filename);
|
|
47
|
+
language = PYTHON;
|
|
48
|
+
}
|
|
49
|
+
if (isNodeLockFilename(filename)) {
|
|
50
|
+
deducedLanguages.push(filename);
|
|
51
|
+
language = NODE;
|
|
52
|
+
}
|
|
53
|
+
if (isGoProjectFilename(filename)) {
|
|
54
|
+
deducedLanguages.push({ language: GO, projectFilename: filename });
|
|
55
|
+
language = GO;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
let identifiedLanguages = { [language]: deducedLanguages };
|
|
59
|
+
return identifiedLanguages;
|
|
60
|
+
};
|
|
25
61
|
const deduceLanguage = filename => {
|
|
26
62
|
const deducedLanguages = [];
|
|
27
63
|
if (isJavaMavenProjectFilename(filename)) {
|
|
@@ -90,7 +126,8 @@ module.exports = exports = (analysis, next) => {
|
|
|
90
126
|
}
|
|
91
127
|
let language = config.language;
|
|
92
128
|
if (language === undefined) {
|
|
93
|
-
languageAnalysis.identifiedLanguages =
|
|
129
|
+
languageAnalysis.identifiedLanguages =
|
|
130
|
+
reduceIdentifiedLanguages(identifiedLanguages);
|
|
94
131
|
}
|
|
95
132
|
else {
|
|
96
133
|
let refinedIdentifiedLanguages = [];
|
|
@@ -119,3 +156,4 @@ exports.isPhpProjectFilename = isPhpProjectFilename;
|
|
|
119
156
|
exports.isPhpLockFilename = isPhpLockFilename;
|
|
120
157
|
exports.deduceLanguage = deduceLanguage;
|
|
121
158
|
exports.reduceIdentifiedLanguages = reduceIdentifiedLanguages;
|
|
159
|
+
exports.deduceLanguageScaAnalysis = deduceLanguageScaAnalysis;
|
|
@@ -3,41 +3,29 @@ 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.printFormattedOutput = exports.printVulnerabilityResponse = exports.getReport = exports.createLibraryHeader = void 0;
|
|
7
|
-
const i18n_1 = __importDefault(require("i18n"));
|
|
6
|
+
exports.getNumOfAndSeverityType = exports.buildFormattedHeaderNum = exports.buildBody = exports.buildHeader = exports.printFormattedOutput = exports.printVulnerabilityResponse = exports.getReport = exports.createLibraryHeader = void 0;
|
|
8
7
|
const commonApi_1 = require("../../../utils/commonApi");
|
|
9
8
|
const reportListModel_1 = require("./models/reportListModel");
|
|
10
9
|
const lodash_1 = require("lodash");
|
|
11
10
|
const chalk_1 = __importDefault(require("chalk"));
|
|
12
11
|
const reportUtils_1 = require("./utils/reportUtils");
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
? console.log(`\n Application Name: ${name} | Application ID: ${id}`)
|
|
17
|
-
: console.log(` Application ID: ${id}`);
|
|
12
|
+
const severityCountModel_1 = require("./models/severityCountModel");
|
|
13
|
+
const reportOutputModel_1 = require("./models/reportOutputModel");
|
|
14
|
+
const createLibraryHeader = (id, numberOfVulnerableLibraries, numberOfCves) => {
|
|
18
15
|
numberOfVulnerableLibraries === 1
|
|
19
|
-
? console.log(
|
|
20
|
-
|
|
21
|
-
'************************** ')
|
|
22
|
-
: console.log('\n **************************' +
|
|
23
|
-
` Found ${numberOfVulnerableLibraries} vulnerable libraries containing ${numberOfCves} CVE's ` +
|
|
24
|
-
'************************** ');
|
|
16
|
+
? console.log(` Found 1 vulnerable library containing ${numberOfCves} CVE's`)
|
|
17
|
+
: console.log(` Found ${numberOfVulnerableLibraries} vulnerable libraries containing ${numberOfCves} CVE's `);
|
|
25
18
|
};
|
|
26
19
|
exports.createLibraryHeader = createLibraryHeader;
|
|
27
20
|
const getReport = async (config, reportId) => {
|
|
28
21
|
const client = (0, commonApi_1.getHttpClient)(config);
|
|
29
|
-
const reportSpinner = (0, oraWrapper_1.returnOra)(i18n_1.default.__('auditReportWaiting'));
|
|
30
|
-
reportSpinner.indent = 1;
|
|
31
|
-
(0, oraWrapper_1.startSpinner)(reportSpinner);
|
|
32
22
|
return client
|
|
33
23
|
.getReportById(config, reportId)
|
|
34
24
|
.then((res) => {
|
|
35
25
|
if (res.statusCode === 200) {
|
|
36
|
-
(0, oraWrapper_1.succeedSpinner)(reportSpinner, i18n_1.default.__('auditReportSuccessMessage'));
|
|
37
26
|
return res.body;
|
|
38
27
|
}
|
|
39
28
|
else {
|
|
40
|
-
(0, oraWrapper_1.failSpinner)(reportSpinner, i18n_1.default.__('auditReportFail'));
|
|
41
29
|
console.log('config-------------------');
|
|
42
30
|
console.log(config);
|
|
43
31
|
console.log('reportId----------------');
|
|
@@ -67,19 +55,70 @@ const printFormattedOutput = (libraries, config) => {
|
|
|
67
55
|
const newOutputModel = new reportListModel_1.ReportModelStructure(new reportListModel_1.ReportCompositeKey(name, version, (0, reportUtils_1.findHighestSeverityCVE)(library.cveArray)), library.cveArray);
|
|
68
56
|
report.reportOutputList.push(newOutputModel);
|
|
69
57
|
}
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const highestSeverity = reportModel.compositeKey
|
|
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++;
|
|
62
|
+
const { libraryName, libraryVersion, highestSeverity } = reportModel.compositeKey;
|
|
75
63
|
const numOfCVEs = reportModel.cveArray.length;
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
console.log(
|
|
81
|
-
console.log(
|
|
82
|
-
console.log(chalk_1.default.bold(' How to fix: Update to latest version'));
|
|
64
|
+
const header = buildHeader(highestSeverity, contrastHeaderNumCounter, libraryName, libraryVersion, numOfCVEs);
|
|
65
|
+
const body = buildBody(reportModel.cveArray);
|
|
66
|
+
const reportOutputModel = new reportOutputModel_1.ReportOutputModel(header, body);
|
|
67
|
+
console.log(reportOutputModel.header.vulnMessage, reportOutputModel.header.introducesMessage);
|
|
68
|
+
console.log(reportOutputModel.body.issueMessage);
|
|
69
|
+
console.log(reportOutputModel.body.adviceMessage);
|
|
83
70
|
}
|
|
84
71
|
};
|
|
85
72
|
exports.printFormattedOutput = printFormattedOutput;
|
|
73
|
+
function buildHeader(highestSeverity, contrastHeaderNum, libraryName, version, numOfCVEs) {
|
|
74
|
+
const vulnerabilityPluralised = numOfCVEs > 1 ? 'Vulnerabilities' : 'Vulnerability';
|
|
75
|
+
const formattedHeaderNum = buildFormattedHeaderNum(contrastHeaderNum);
|
|
76
|
+
const vulnMessage = chalk_1.default
|
|
77
|
+
.hex(highestSeverity.outputColour)
|
|
78
|
+
.bold(`${formattedHeaderNum} - [${highestSeverity.severity}] ${libraryName}-${version}`);
|
|
79
|
+
const introducesMessage = chalk_1.default.bold(`introduces ${numOfCVEs} ${vulnerabilityPluralised}`);
|
|
80
|
+
return new reportOutputModel_1.ReportOutputHeaderModel(vulnMessage, introducesMessage);
|
|
81
|
+
}
|
|
82
|
+
exports.buildHeader = buildHeader;
|
|
83
|
+
function buildBody(cveArray) {
|
|
84
|
+
const cveMessages = [];
|
|
85
|
+
(0, reportUtils_1.findCVESeveritiesAndOrderByHighestPriority)(cveArray).forEach(reportSeverityModel => {
|
|
86
|
+
const { outputColour, severity, cveName } = reportSeverityModel;
|
|
87
|
+
const severityShorthand = chalk_1.default
|
|
88
|
+
.hex(outputColour)
|
|
89
|
+
.bold(`[${severity.charAt(0).toUpperCase()}]`);
|
|
90
|
+
const builtMessage = `${severityShorthand} ${cveName}`;
|
|
91
|
+
cveMessages.push(builtMessage);
|
|
92
|
+
});
|
|
93
|
+
const numAndSeverityType = getNumOfAndSeverityType(cveArray);
|
|
94
|
+
const issueMessage = ` ${chalk_1.default.bold('Issue')} : ${numAndSeverityType} ${cveMessages.join(', ')}.`;
|
|
95
|
+
const adviceMessage = ` ${chalk_1.default.bold('Advice')} : ${chalk_1.default.bold('Update to latest version')}.`;
|
|
96
|
+
return new reportOutputModel_1.ReportOutputBodyModel(issueMessage, adviceMessage);
|
|
97
|
+
}
|
|
98
|
+
exports.buildBody = buildBody;
|
|
99
|
+
function buildFormattedHeaderNum(contrastHeaderNum) {
|
|
100
|
+
let formattedHeaderNum;
|
|
101
|
+
if (contrastHeaderNum < 10) {
|
|
102
|
+
formattedHeaderNum = `00${contrastHeaderNum}`;
|
|
103
|
+
}
|
|
104
|
+
else if (contrastHeaderNum >= 10 && contrastHeaderNum < 100) {
|
|
105
|
+
formattedHeaderNum = `0${contrastHeaderNum}`;
|
|
106
|
+
}
|
|
107
|
+
else if (contrastHeaderNum >= 100) {
|
|
108
|
+
formattedHeaderNum = contrastHeaderNum;
|
|
109
|
+
}
|
|
110
|
+
return `CONTRAST-${formattedHeaderNum}`;
|
|
111
|
+
}
|
|
112
|
+
exports.buildFormattedHeaderNum = buildFormattedHeaderNum;
|
|
113
|
+
function getNumOfAndSeverityType(cveArray) {
|
|
114
|
+
const { critical, high, medium, low, note } = (0, reportUtils_1.severityCountAllCVEs)(cveArray, new severityCountModel_1.SeverityCountModel());
|
|
115
|
+
const criticalMessage = critical > 0 ? `${critical} Critical` : '';
|
|
116
|
+
const highMessage = high > 0 ? `${high} High` : '';
|
|
117
|
+
const mediumMessage = medium > 0 ? `${medium} Medium` : '';
|
|
118
|
+
const lowMessage = low > 0 ? `${low} Low` : '';
|
|
119
|
+
const noteMessage = note > 0 ? `${note} Note` : '';
|
|
120
|
+
return `${criticalMessage} ${highMessage} ${mediumMessage} ${lowMessage} ${noteMessage}`
|
|
121
|
+
.replace(/\s+/g, ' ')
|
|
122
|
+
.trim();
|
|
123
|
+
}
|
|
124
|
+
exports.getNumOfAndSeverityType = getNumOfAndSeverityType;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReportOutputBodyModel = exports.ReportOutputHeaderModel = exports.ReportOutputModel = void 0;
|
|
4
|
+
class ReportOutputModel {
|
|
5
|
+
constructor(header, body) {
|
|
6
|
+
this.header = header;
|
|
7
|
+
this.body = body;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.ReportOutputModel = ReportOutputModel;
|
|
11
|
+
class ReportOutputHeaderModel {
|
|
12
|
+
constructor(vulnMessage, introducesMessage) {
|
|
13
|
+
this.vulnMessage = vulnMessage;
|
|
14
|
+
this.introducesMessage = introducesMessage;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.ReportOutputHeaderModel = ReportOutputHeaderModel;
|
|
18
|
+
class ReportOutputBodyModel {
|
|
19
|
+
constructor(bodyIssueMessage, bodyAdviceMessage) {
|
|
20
|
+
this.issueMessage = bodyIssueMessage;
|
|
21
|
+
this.adviceMessage = bodyAdviceMessage;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.ReportOutputBodyModel = ReportOutputBodyModel;
|
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ReportSeverityModel = void 0;
|
|
4
4
|
class ReportSeverityModel {
|
|
5
|
-
constructor(severity, priority) {
|
|
5
|
+
constructor(severity, priority, outputColour, cveName) {
|
|
6
6
|
this.severity = severity;
|
|
7
7
|
this.priority = priority;
|
|
8
|
+
this.outputColour = outputColour;
|
|
9
|
+
this.cveName = cveName;
|
|
8
10
|
}
|
|
9
11
|
}
|
|
10
12
|
exports.ReportSeverityModel = ReportSeverityModel;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SeverityCountModel = void 0;
|
|
4
|
+
class SeverityCountModel {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.critical = 0;
|
|
7
|
+
this.high = 0;
|
|
8
|
+
this.medium = 0;
|
|
9
|
+
this.low = 0;
|
|
10
|
+
this.note = 0;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.SeverityCountModel = SeverityCountModel;
|
|
@@ -17,12 +17,12 @@ function formatVulnerabilityOutput(libraryVulnerabilityResponse, id, name, confi
|
|
|
17
17
|
const numberOfVulnerableLibraries = vulnerableLibraries.length;
|
|
18
18
|
let numberOfCves = 0;
|
|
19
19
|
vulnerableLibraries.forEach(lib => (numberOfCves += lib.cveArray.length));
|
|
20
|
-
(0, commonReportingFunctions_1.createLibraryHeader)(id, numberOfVulnerableLibraries, numberOfCves
|
|
20
|
+
(0, commonReportingFunctions_1.createLibraryHeader)(id, numberOfVulnerableLibraries, numberOfCves);
|
|
21
21
|
const hasSomeVulnerabilitiesReported = (0, commonReportingFunctions_1.printVulnerabilityResponse)(vulnerableLibraries, config);
|
|
22
22
|
return [
|
|
23
23
|
hasSomeVulnerabilitiesReported,
|
|
24
24
|
numberOfCves,
|
|
25
|
-
(0, reportUtils_1.
|
|
25
|
+
(0, reportUtils_1.severityCountAllLibraries)(vulnerableLibraries)
|
|
26
26
|
];
|
|
27
27
|
}
|
|
28
28
|
exports.formatVulnerabilityOutput = formatVulnerabilityOutput;
|
|
@@ -3,70 +3,81 @@ 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.
|
|
6
|
+
exports.findNameAndVersion = exports.severityCountSingleCVE = exports.severityCountAllCVEs = exports.severityCountAllLibraries = exports.convertGenericToTypedLibraries = 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"));
|
|
10
|
+
const constants_2 = require("../../../../constants/constants");
|
|
11
|
+
const lodash_1 = require("lodash");
|
|
12
|
+
const severityCountModel_1 = require("../models/severityCountModel");
|
|
10
13
|
const { supportedLanguages: { GO } } = constants_1.default;
|
|
11
14
|
function findHighestSeverityCVE(cveArray) {
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
const mappedToReportSeverityModels = cveArray.map(cve => findCVESeverity(cve));
|
|
16
|
+
return (0, lodash_1.orderBy)(mappedToReportSeverityModels, cve => cve?.priority)[0];
|
|
17
|
+
}
|
|
18
|
+
exports.findHighestSeverityCVE = findHighestSeverityCVE;
|
|
19
|
+
function findCVESeveritiesAndOrderByHighestPriority(cves) {
|
|
20
|
+
return (0, lodash_1.orderBy)(cves.map(cve => findCVESeverity(cve)), ['priority'], ['asc']);
|
|
21
|
+
}
|
|
22
|
+
exports.findCVESeveritiesAndOrderByHighestPriority = findCVESeveritiesAndOrderByHighestPriority;
|
|
23
|
+
function findCVESeverity(cve) {
|
|
24
|
+
const cveName = cve.name;
|
|
25
|
+
if (cve.cvss3SeverityCode === 'CRITICAL' || cve.severityCode === 'CRITICAL') {
|
|
26
|
+
return new reportSeverityModel_1.ReportSeverityModel('CRITICAL', constants_2.CRITICAL_PRIORITY, constants_2.CRITICAL_COLOUR, cveName);
|
|
14
27
|
}
|
|
15
|
-
else if (
|
|
16
|
-
return new reportSeverityModel_1.ReportSeverityModel('HIGH',
|
|
28
|
+
else if (cve.cvss3SeverityCode === 'HIGH' || cve.severityCode === 'HIGH') {
|
|
29
|
+
return new reportSeverityModel_1.ReportSeverityModel('HIGH', constants_2.HIGH_PRIORITY, constants_2.HIGH_COLOUR, cveName);
|
|
17
30
|
}
|
|
18
|
-
else if (
|
|
19
|
-
|
|
31
|
+
else if (cve.cvss3SeverityCode === 'MEDIUM' ||
|
|
32
|
+
cve.severityCode === 'MEDIUM') {
|
|
33
|
+
return new reportSeverityModel_1.ReportSeverityModel('MEDIUM', constants_2.MEDIUM_PRIORITY, constants_2.MEDIUM_COLOUR, cveName);
|
|
20
34
|
}
|
|
21
|
-
else if (
|
|
22
|
-
return new reportSeverityModel_1.ReportSeverityModel('LOW',
|
|
35
|
+
else if (cve.cvss3SeverityCode === 'LOW' || cve.severityCode === 'LOW') {
|
|
36
|
+
return new reportSeverityModel_1.ReportSeverityModel('LOW', constants_2.LOW_PRIORITY, constants_2.LOW_COLOUR, cveName);
|
|
23
37
|
}
|
|
24
|
-
else if (
|
|
25
|
-
return new reportSeverityModel_1.ReportSeverityModel('NOTE',
|
|
38
|
+
else if (cve.cvss3SeverityCode === 'NOTE' || cve.severityCode === 'NOTE') {
|
|
39
|
+
return new reportSeverityModel_1.ReportSeverityModel('NOTE', constants_2.NOTE_PRIORITY, constants_2.NOTE_COLOUR, cveName);
|
|
26
40
|
}
|
|
27
41
|
}
|
|
28
|
-
exports.
|
|
42
|
+
exports.findCVESeverity = findCVESeverity;
|
|
29
43
|
function convertGenericToTypedLibraries(libraries) {
|
|
30
44
|
return Object.entries(libraries).map(([name, cveArray]) => {
|
|
31
45
|
return new reportLibraryModel_1.ReportLibraryModel(name, cveArray);
|
|
32
46
|
});
|
|
33
47
|
}
|
|
34
48
|
exports.convertGenericToTypedLibraries = convertGenericToTypedLibraries;
|
|
35
|
-
function
|
|
36
|
-
const severityCount =
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
});
|
|
49
|
+
function severityCountAllLibraries(vulnerableLibraries) {
|
|
50
|
+
const severityCount = new severityCountModel_1.SeverityCountModel();
|
|
51
|
+
vulnerableLibraries.forEach(lib => severityCountAllCVEs(lib.cveArray, severityCount));
|
|
52
|
+
return severityCount;
|
|
53
|
+
}
|
|
54
|
+
exports.severityCountAllLibraries = severityCountAllLibraries;
|
|
55
|
+
function severityCountAllCVEs(cveArray, severityCount) {
|
|
56
|
+
const severityCountInner = severityCount;
|
|
57
|
+
cveArray.forEach(cve => severityCountSingleCVE(cve, severityCountInner));
|
|
58
|
+
return severityCountInner;
|
|
59
|
+
}
|
|
60
|
+
exports.severityCountAllCVEs = severityCountAllCVEs;
|
|
61
|
+
function severityCountSingleCVE(cve, severityCount) {
|
|
62
|
+
if (cve.cvss3SeverityCode === 'CRITICAL' || cve.severityCode === 'CRITICAL') {
|
|
63
|
+
severityCount.critical += 1;
|
|
64
|
+
}
|
|
65
|
+
else if (cve.cvss3SeverityCode === 'HIGH' || cve.severityCode === 'HIGH') {
|
|
66
|
+
severityCount.high += 1;
|
|
67
|
+
}
|
|
68
|
+
else if (cve.cvss3SeverityCode === 'MEDIUM' ||
|
|
69
|
+
cve.severityCode === 'MEDIUM') {
|
|
70
|
+
severityCount.medium += 1;
|
|
71
|
+
}
|
|
72
|
+
else if (cve.cvss3SeverityCode === 'LOW' || cve.severityCode === 'LOW') {
|
|
73
|
+
severityCount.low += 1;
|
|
74
|
+
}
|
|
75
|
+
else if (cve.cvss3SeverityCode === 'NOTE' || cve.severityCode === 'NOTE') {
|
|
76
|
+
severityCount.note += 1;
|
|
77
|
+
}
|
|
67
78
|
return severityCount;
|
|
68
79
|
}
|
|
69
|
-
exports.
|
|
80
|
+
exports.severityCountSingleCVE = severityCountSingleCVE;
|
|
70
81
|
function findNameAndVersion(library, config) {
|
|
71
82
|
if (config.language.toUpperCase() === GO) {
|
|
72
83
|
const nameVersion = library.name.split('@');
|
|
@@ -1,32 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const prettyjson = require('prettyjson');
|
|
3
|
-
const i18n = require('i18n');
|
|
4
|
-
const { getHttpClient } = require('../../utils/commonApi');
|
|
5
2
|
const { handleResponseErrors } = require('../../common/errorHandling');
|
|
6
3
|
const { APP_VERSION } = require('../../constants/constants');
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const newSendSnapShot = async (analysis, applicationId) => {
|
|
4
|
+
const commonApi = require('../../utils/commonApi');
|
|
5
|
+
const _ = require('lodash');
|
|
6
|
+
const oraFunctions = require('../../utils/oraWrapper');
|
|
7
|
+
const i18n = require('i18n');
|
|
8
|
+
const oraWrapper = require('../../utils/oraWrapper');
|
|
9
|
+
const requestUtils = require('../../utils/requestUtils');
|
|
10
|
+
const { performance } = require('perf_hooks');
|
|
11
|
+
const newSendSnapShot = async (analysis) => {
|
|
16
12
|
const analysisLanguage = analysis.config.language.toLowerCase();
|
|
17
13
|
const requestBody = {
|
|
18
14
|
appID: analysis.config.applicationId,
|
|
19
15
|
cliVersion: APP_VERSION,
|
|
20
16
|
snapshot: { [analysisLanguage]: analysis[analysisLanguage] }
|
|
21
17
|
};
|
|
22
|
-
const client = getHttpClient(analysis.config);
|
|
18
|
+
const client = commonApi.getHttpClient(analysis.config);
|
|
23
19
|
return client
|
|
24
20
|
.sendSnapshot(requestBody, analysis.config)
|
|
25
21
|
.then(res => {
|
|
26
22
|
if (res.statusCode === 201) {
|
|
27
|
-
if (analysis.config.host !== 'https://ce.contrastsecurity.com/') {
|
|
28
|
-
displaySnapshotSuccessMessage(analysis.config);
|
|
29
|
-
}
|
|
30
23
|
return res.body;
|
|
31
24
|
}
|
|
32
25
|
else {
|
|
@@ -37,7 +30,62 @@ const newSendSnapShot = async (analysis, applicationId) => {
|
|
|
37
30
|
console.log(err);
|
|
38
31
|
});
|
|
39
32
|
};
|
|
33
|
+
const pollSnapshotResults = async (config, snapshotId, client) => {
|
|
34
|
+
await requestUtils.sleep(5000);
|
|
35
|
+
return client
|
|
36
|
+
.getReportStatusById(config, snapshotId)
|
|
37
|
+
.then(res => {
|
|
38
|
+
return res;
|
|
39
|
+
})
|
|
40
|
+
.catch(err => {
|
|
41
|
+
console.log(err);
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
const getTimeout = config => {
|
|
45
|
+
if (config.timeout) {
|
|
46
|
+
return config.timeout;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
if (config.verbose) {
|
|
50
|
+
console.log('Timeout set to 2 minutes');
|
|
51
|
+
}
|
|
52
|
+
return 120;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const pollForSnapshotCompletition = async (config, snapshotId, reportSpinner) => {
|
|
56
|
+
const client = commonApi.getHttpClient(config);
|
|
57
|
+
const startTime = performance.now();
|
|
58
|
+
const timeout = getTimeout(config);
|
|
59
|
+
let complete = false;
|
|
60
|
+
if (!_.isNil(snapshotId)) {
|
|
61
|
+
while (!complete) {
|
|
62
|
+
let result = await pollSnapshotResults(config, snapshotId, client);
|
|
63
|
+
if (result.statusCode === 200) {
|
|
64
|
+
if (result.body.status === 'PROCESSED') {
|
|
65
|
+
complete = true;
|
|
66
|
+
return result.body;
|
|
67
|
+
}
|
|
68
|
+
if (result.body.status === 'FAILED') {
|
|
69
|
+
complete = true;
|
|
70
|
+
if (config.debug) {
|
|
71
|
+
oraFunctions.failSpinner(reportSpinner, i18n.__('auditNotCompleted'));
|
|
72
|
+
}
|
|
73
|
+
console.log(result.body.errorMessage);
|
|
74
|
+
oraWrapper.stopSpinner(reportSpinner);
|
|
75
|
+
console.log('Contrast audit finished');
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const endTime = performance.now() - startTime;
|
|
80
|
+
if (requestUtils.millisToSeconds(endTime) > timeout) {
|
|
81
|
+
oraFunctions.failSpinner(reportSpinner, 'Contrast audit timed out at the specified ' + timeout + ' seconds.');
|
|
82
|
+
console.log('Please try again, allowing more time.');
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
40
88
|
module.exports = {
|
|
41
89
|
newSendSnapShot: newSendSnapShot,
|
|
42
|
-
|
|
90
|
+
pollForSnapshotCompletition: pollForSnapshotCompletition
|
|
43
91
|
};
|