@contrast/contrast 1.0.5 → 1.0.6
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 +1 -0
- package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +5 -1
- package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +66 -13
- 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 +1 -1
- package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +59 -45
- package/dist/commands/audit/auditController.js +1 -1
- package/dist/commands/scan/processScan.js +1 -1
- package/dist/commands/scan/sca/scaAnalysis.js +12 -7
- package/dist/constants/constants.js +13 -3
- package/dist/scaAnalysis/common/formatMessage.js +9 -1
- package/dist/scaAnalysis/common/treeUpload.js +2 -3
- 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 +6 -14
- package/dist/scaAnalysis/java/index.js +5 -5
- package/dist/scaAnalysis/java/javaBuildDepsParser.js +14 -1
- package/dist/scan/formatScanOutput.js +10 -7
- package/dist/scan/scan.js +4 -3
- package/dist/scan/scanController.js +11 -4
- package/dist/scan/scanResults.js +15 -5
- package/dist/utils/oraWrapper.js +5 -1
- package/package.json +1 -1
- package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +6 -5
- package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +117 -18
- package/src/audit/languageAnalysisEngine/report/models/reportOutputModel.ts +29 -0
- package/src/audit/languageAnalysisEngine/report/models/reportSeverityModel.ts +7 -3
- package/src/audit/languageAnalysisEngine/report/models/severityCountModel.ts +16 -0
- package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +2 -2
- package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +74 -68
- package/src/commands/audit/auditController.ts +1 -2
- package/src/commands/scan/processScan.js +2 -1
- package/src/commands/scan/sca/scaAnalysis.js +12 -10
- package/src/constants/constants.js +13 -3
- package/src/scaAnalysis/common/formatMessage.js +11 -1
- package/src/scaAnalysis/common/treeUpload.js +2 -6
- package/src/scaAnalysis/go/goAnalysis.js +20 -0
- package/src/scaAnalysis/go/goParseDeps.js +203 -0
- package/src/scaAnalysis/go/goReadDepFile.js +32 -0
- package/src/scaAnalysis/java/analysis.js +8 -24
- package/src/scaAnalysis/java/index.js +5 -5
- package/src/scaAnalysis/java/javaBuildDepsParser.js +15 -2
- package/src/scan/formatScanOutput.ts +17 -8
- package/src/scan/scan.ts +7 -6
- package/src/scan/scanController.js +13 -6
- package/src/scan/scanResults.js +21 -10
- package/src/utils/oraWrapper.js +6 -1
package/.prettierignore
CHANGED
|
@@ -40,7 +40,11 @@ const deduceLanguageScaAnalysis = filenames => {
|
|
|
40
40
|
}
|
|
41
41
|
if (isNodeLockFilename(filename)) {
|
|
42
42
|
deducedLanguages.push(filename);
|
|
43
|
-
language =
|
|
43
|
+
language = NODE;
|
|
44
|
+
}
|
|
45
|
+
if (isGoProjectFilename(filename)) {
|
|
46
|
+
deducedLanguages.push({ language: GO, projectFilename: filename });
|
|
47
|
+
language = GO;
|
|
44
48
|
}
|
|
45
49
|
});
|
|
46
50
|
let identifiedLanguages = { [language]: deducedLanguages };
|
|
@@ -3,12 +3,14 @@ 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;
|
|
6
|
+
exports.getNumOfAndSeverityType = exports.buildFormattedHeaderNum = exports.buildBody = exports.buildHeader = exports.printFormattedOutput = exports.printVulnerabilityResponse = exports.getReport = exports.createLibraryHeader = void 0;
|
|
7
7
|
const commonApi_1 = require("../../../utils/commonApi");
|
|
8
8
|
const reportListModel_1 = require("./models/reportListModel");
|
|
9
9
|
const lodash_1 = require("lodash");
|
|
10
10
|
const chalk_1 = __importDefault(require("chalk"));
|
|
11
11
|
const reportUtils_1 = require("./utils/reportUtils");
|
|
12
|
+
const severityCountModel_1 = require("./models/severityCountModel");
|
|
13
|
+
const reportOutputModel_1 = require("./models/reportOutputModel");
|
|
12
14
|
const createLibraryHeader = (id, numberOfVulnerableLibraries, numberOfCves) => {
|
|
13
15
|
numberOfVulnerableLibraries === 1
|
|
14
16
|
? console.log(` Found 1 vulnerable library containing ${numberOfCves} CVE's`)
|
|
@@ -53,19 +55,70 @@ const printFormattedOutput = (libraries, config) => {
|
|
|
53
55
|
const newOutputModel = new reportListModel_1.ReportModelStructure(new reportListModel_1.ReportCompositeKey(name, version, (0, reportUtils_1.findHighestSeverityCVE)(library.cveArray)), library.cveArray);
|
|
54
56
|
report.reportOutputList.push(newOutputModel);
|
|
55
57
|
}
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
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;
|
|
61
63
|
const numOfCVEs = reportModel.cveArray.length;
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
console.log(
|
|
67
|
-
console.log(
|
|
68
|
-
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);
|
|
69
70
|
}
|
|
70
71
|
};
|
|
71
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;
|
|
@@ -22,7 +22,7 @@ function formatVulnerabilityOutput(libraryVulnerabilityResponse, id, name, confi
|
|
|
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,84 @@ 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
|
-
return new reportSeverityModel_1.ReportSeverityModel('MEDIUM',
|
|
31
|
+
else if (cve.cvss3SeverityCode === 'MEDIUM' || cve.severityCode === 'MEDIUM') {
|
|
32
|
+
return new reportSeverityModel_1.ReportSeverityModel('MEDIUM', constants_2.MEDIUM_PRIORITY, constants_2.MEDIUM_COLOUR, cveName);
|
|
20
33
|
}
|
|
21
|
-
else if (
|
|
22
|
-
return new reportSeverityModel_1.ReportSeverityModel('LOW',
|
|
34
|
+
else if (cve.cvss3SeverityCode === 'LOW' || cve.severityCode === 'LOW') {
|
|
35
|
+
return new reportSeverityModel_1.ReportSeverityModel('LOW', constants_2.LOW_PRIORITY, constants_2.LOW_COLOUR, cveName);
|
|
23
36
|
}
|
|
24
|
-
else if (
|
|
25
|
-
return new reportSeverityModel_1.ReportSeverityModel('NOTE',
|
|
37
|
+
else if (cve.cvss3SeverityCode === 'NOTE' || cve.severityCode === 'NOTE') {
|
|
38
|
+
return new reportSeverityModel_1.ReportSeverityModel('NOTE', constants_2.NOTE_PRIORITY, constants_2.NOTE_COLOUR, cveName);
|
|
26
39
|
}
|
|
27
40
|
}
|
|
28
|
-
exports.
|
|
41
|
+
exports.findCVESeverity = findCVESeverity;
|
|
29
42
|
function convertGenericToTypedLibraries(libraries) {
|
|
30
43
|
return Object.entries(libraries).map(([name, cveArray]) => {
|
|
31
44
|
return new reportLibraryModel_1.ReportLibraryModel(name, cveArray);
|
|
32
45
|
});
|
|
33
46
|
}
|
|
34
47
|
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
|
-
|
|
48
|
+
function severityCountAllLibraries(vulnerableLibraries) {
|
|
49
|
+
const severityCount = new severityCountModel_1.SeverityCountModel();
|
|
50
|
+
vulnerableLibraries.forEach(lib => severityCountAllCVEs(lib.cveArray, severityCount));
|
|
51
|
+
return severityCount;
|
|
52
|
+
}
|
|
53
|
+
exports.severityCountAllLibraries = severityCountAllLibraries;
|
|
54
|
+
function severityCountAllCVEs(cveArray, severityCount) {
|
|
55
|
+
const severityCountInner = severityCount;
|
|
56
|
+
cveArray.forEach(cve => severityCountSingleCVE(cve, severityCountInner));
|
|
57
|
+
return severityCountInner;
|
|
58
|
+
}
|
|
59
|
+
exports.severityCountAllCVEs = severityCountAllCVEs;
|
|
60
|
+
function severityCountSingleCVE(cve, severityCount) {
|
|
61
|
+
if (cve.cvss3SeverityCode === 'CRITICAL' ||
|
|
62
|
+
cve.severityCode === 'CRITICAL') {
|
|
63
|
+
severityCount.critical += 1;
|
|
64
|
+
}
|
|
65
|
+
else if (cve.cvss3SeverityCode === 'HIGH' ||
|
|
66
|
+
cve.severityCode === 'HIGH') {
|
|
67
|
+
severityCount.high += 1;
|
|
68
|
+
}
|
|
69
|
+
else if (cve.cvss3SeverityCode === 'MEDIUM' ||
|
|
70
|
+
cve.severityCode === 'MEDIUM') {
|
|
71
|
+
severityCount.medium += 1;
|
|
72
|
+
}
|
|
73
|
+
else if (cve.cvss3SeverityCode === 'LOW' ||
|
|
74
|
+
cve.severityCode === 'LOW') {
|
|
75
|
+
severityCount.low += 1;
|
|
76
|
+
}
|
|
77
|
+
else if (cve.cvss3SeverityCode === 'NOTE' ||
|
|
78
|
+
cve.severityCode === 'NOTE') {
|
|
79
|
+
severityCount.note += 1;
|
|
80
|
+
}
|
|
67
81
|
return severityCount;
|
|
68
82
|
}
|
|
69
|
-
exports.
|
|
83
|
+
exports.severityCountSingleCVE = severityCountSingleCVE;
|
|
70
84
|
function findNameAndVersion(library, config) {
|
|
71
85
|
if (config.language.toUpperCase() === GO) {
|
|
72
86
|
const nameVersion = library.name.split('@');
|
|
@@ -23,7 +23,7 @@ const dealWithNoAppId = async (config) => {
|
|
|
23
23
|
}
|
|
24
24
|
catch (e) {
|
|
25
25
|
if (e.toString().includes('tunneling socket could not be established')) {
|
|
26
|
-
console.log(e.message);
|
|
26
|
+
console.log(e.message.toString());
|
|
27
27
|
console.log('There seems to be an issue with your proxy, please check and try again');
|
|
28
28
|
}
|
|
29
29
|
process.exit(1);
|
|
@@ -11,7 +11,7 @@ const processScan = async (argvMain) => {
|
|
|
11
11
|
await processSca(config);
|
|
12
12
|
}
|
|
13
13
|
let scanResults = new ScanResultsModel(await startScan(config));
|
|
14
|
-
if (scanResults) {
|
|
14
|
+
if (scanResults.scanResultsInstances !== undefined) {
|
|
15
15
|
formatScanOutput(scanResults);
|
|
16
16
|
}
|
|
17
17
|
if (config.save !== undefined) {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const autoDetection = require('../../../scan/autoDetection');
|
|
3
|
-
const
|
|
4
|
-
const
|
|
3
|
+
const javaAnalysis = require('../../../scaAnalysis/java');
|
|
4
|
+
const treeUpload = require('../../../scaAnalysis/common/treeUpload');
|
|
5
5
|
const { manualDetectAuditFilesAndLanguages } = require('../../../scan/autoDetection');
|
|
6
|
-
const
|
|
7
|
-
const { supportedLanguages: { JAVA } } = require('../../../audit/languageAnalysisEngine/constants');
|
|
6
|
+
const auditController = require('../../audit/auditController');
|
|
7
|
+
const { supportedLanguages: { JAVA, GO } } = require('../../../audit/languageAnalysisEngine/constants');
|
|
8
|
+
const goAnalysis = require('../../../scaAnalysis/go/goAnalysis');
|
|
8
9
|
const processSca = async (config) => {
|
|
9
10
|
let filesFound;
|
|
10
11
|
if (config.projectPath) {
|
|
@@ -17,18 +18,22 @@ const processSca = async (config) => {
|
|
|
17
18
|
if (filesFound.length === 1) {
|
|
18
19
|
switch (Object.keys(filesFound[0])[0]) {
|
|
19
20
|
case JAVA:
|
|
20
|
-
messageToSend =
|
|
21
|
+
messageToSend = javaAnalysis.javaAnalysis(config, filesFound[0]);
|
|
21
22
|
config.language = JAVA;
|
|
22
23
|
break;
|
|
24
|
+
case GO:
|
|
25
|
+
messageToSend = goAnalysis.goAnalysis(config, filesFound[0]);
|
|
26
|
+
config.language = GO;
|
|
27
|
+
break;
|
|
23
28
|
default:
|
|
24
29
|
console.log('language detected not supported');
|
|
25
30
|
return;
|
|
26
31
|
}
|
|
27
32
|
if (!config.applicationId) {
|
|
28
|
-
config.applicationId = await dealWithNoAppId(config);
|
|
33
|
+
config.applicationId = await auditController.dealWithNoAppId(config);
|
|
29
34
|
}
|
|
30
35
|
console.log('processing dependencies');
|
|
31
|
-
const response = await commonSendSnapShot(messageToSend, config);
|
|
36
|
+
const response = await treeUpload.commonSendSnapShot(messageToSend, config);
|
|
32
37
|
}
|
|
33
38
|
else {
|
|
34
39
|
if (filesFound.length === 0) {
|
|
@@ -12,13 +12,18 @@ const MEDIUM = 'MEDIUM';
|
|
|
12
12
|
const HIGH = 'HIGH';
|
|
13
13
|
const CRITICAL = 'CRITICAL';
|
|
14
14
|
const APP_NAME = 'contrast';
|
|
15
|
-
const APP_VERSION = '1.0.
|
|
15
|
+
const APP_VERSION = '1.0.6';
|
|
16
16
|
const TIMEOUT = 120000;
|
|
17
17
|
const HIGH_COLOUR = '#ff9900';
|
|
18
18
|
const CRITICAL_COLOUR = '#e35858';
|
|
19
19
|
const MEDIUM_COLOUR = '#f1c232';
|
|
20
|
-
const LOW_COLOUR = '#
|
|
20
|
+
const LOW_COLOUR = '#b7b7b7';
|
|
21
21
|
const NOTE_COLOUR = '#999999';
|
|
22
|
+
const CRITICAL_PRIORITY = 1;
|
|
23
|
+
const HIGH_PRIORITY = 2;
|
|
24
|
+
const MEDIUM_PRIORITY = 3;
|
|
25
|
+
const LOW_PRIORITY = 4;
|
|
26
|
+
const NOTE_PRIORITY = 5;
|
|
22
27
|
const AUTH_UI_URL = 'https://cli-auth.contrastsecurity.com';
|
|
23
28
|
const AUTH_CALLBACK_URL = 'https://cli-auth-api.contrastsecurity.com';
|
|
24
29
|
const SARIF_FILE = 'SARIF';
|
|
@@ -40,5 +45,10 @@ module.exports = {
|
|
|
40
45
|
MEDIUM_COLOUR,
|
|
41
46
|
LOW_COLOUR,
|
|
42
47
|
NOTE_COLOUR,
|
|
43
|
-
CE_URL
|
|
48
|
+
CE_URL,
|
|
49
|
+
CRITICAL_PRIORITY,
|
|
50
|
+
HIGH_PRIORITY,
|
|
51
|
+
MEDIUM_PRIORITY,
|
|
52
|
+
LOW_PRIORITY,
|
|
53
|
+
NOTE_PRIORITY
|
|
44
54
|
};
|
|
@@ -6,6 +6,14 @@ const createJavaTSMessage = javaTree => {
|
|
|
6
6
|
}
|
|
7
7
|
};
|
|
8
8
|
};
|
|
9
|
+
const createGoTSMessage = goTree => {
|
|
10
|
+
return {
|
|
11
|
+
go: {
|
|
12
|
+
goDependencyTrees: goTree
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
};
|
|
9
16
|
module.exports = {
|
|
10
|
-
createJavaTSMessage
|
|
17
|
+
createJavaTSMessage,
|
|
18
|
+
createGoTSMessage
|
|
11
19
|
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const { getHttpClient } = require('../../utils/commonApi');
|
|
3
|
-
const { handleResponseErrors } = require('../../common/errorHandling');
|
|
4
3
|
const { APP_VERSION } = require('../../constants/constants');
|
|
5
4
|
const commonSendSnapShot = async (analysis, config) => {
|
|
6
5
|
const requestBody = {
|
|
@@ -13,12 +12,12 @@ const commonSendSnapShot = async (analysis, config) => {
|
|
|
13
12
|
.sendSnapshot(requestBody, config)
|
|
14
13
|
.then(res => {
|
|
15
14
|
if (res.statusCode === 201) {
|
|
16
|
-
console.log('
|
|
15
|
+
console.log('dependencies processed successfully');
|
|
17
16
|
return res.body;
|
|
18
17
|
}
|
|
19
18
|
else {
|
|
20
19
|
console.log(res.statusCode);
|
|
21
|
-
|
|
20
|
+
console.log('error processing dependencies');
|
|
22
21
|
}
|
|
23
22
|
})
|
|
24
23
|
.catch(err => {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const { createGoTSMessage } = require('../common/formatMessage');
|
|
3
|
+
const goReadDepFile = require('./goReadDepFile');
|
|
4
|
+
const goParseDeps = require('./goParseDeps');
|
|
5
|
+
const goAnalysis = (config, languageFiles) => {
|
|
6
|
+
try {
|
|
7
|
+
const rawGoDependencies = goReadDepFile.getGoDependencies(config);
|
|
8
|
+
const parsedGoDependencies = goParseDeps.parseGoDependencies(rawGoDependencies);
|
|
9
|
+
return createGoTSMessage(parsedGoDependencies);
|
|
10
|
+
}
|
|
11
|
+
catch (e) {
|
|
12
|
+
console.log(e.message.toString());
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
module.exports = {
|
|
16
|
+
goAnalysis
|
|
17
|
+
};
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const crypto = require('crypto');
|
|
3
|
+
const parseGoDependencies = goDeps => {
|
|
4
|
+
return parseGo(goDeps);
|
|
5
|
+
};
|
|
6
|
+
const parseGo = modGraphOutput => {
|
|
7
|
+
let splitLines = splitAllLinesIntoArray(modGraphOutput);
|
|
8
|
+
const directDepNames = getDirectDepNames(splitLines);
|
|
9
|
+
const uniqueTransitiveDepNames = getAllUniqueTransitiveDepNames(splitLines, directDepNames);
|
|
10
|
+
let rootNodes = createRootNodes(splitLines);
|
|
11
|
+
createTransitiveDeps(uniqueTransitiveDepNames, splitLines, rootNodes);
|
|
12
|
+
return rootNodes;
|
|
13
|
+
};
|
|
14
|
+
const splitAllLinesIntoArray = modGraphOutput => {
|
|
15
|
+
return modGraphOutput.split(/\r\n|\r|\n/);
|
|
16
|
+
};
|
|
17
|
+
const getAllDepsOfADepAsEdge = (dep, deps) => {
|
|
18
|
+
let edges = {};
|
|
19
|
+
const depRows = deps.filter(line => {
|
|
20
|
+
return line.startsWith(dep);
|
|
21
|
+
});
|
|
22
|
+
depRows.forEach(dep => {
|
|
23
|
+
const edgeName = dep.split(' ')[1];
|
|
24
|
+
edges[edgeName] = edgeName;
|
|
25
|
+
});
|
|
26
|
+
return edges;
|
|
27
|
+
};
|
|
28
|
+
const getAllDepsOfADepAsName = (dep, deps) => {
|
|
29
|
+
let edges = [];
|
|
30
|
+
const depRows = deps.filter(line => {
|
|
31
|
+
return line.startsWith(dep);
|
|
32
|
+
});
|
|
33
|
+
depRows.forEach(dep => {
|
|
34
|
+
const edgeName = dep.split(' ')[1];
|
|
35
|
+
edges.push(edgeName);
|
|
36
|
+
});
|
|
37
|
+
return edges;
|
|
38
|
+
};
|
|
39
|
+
const createRootNodes = deps => {
|
|
40
|
+
let rootDep = {};
|
|
41
|
+
const rootDeps = getRootDeps(deps);
|
|
42
|
+
const edges = rootDeps.map(dep => {
|
|
43
|
+
return dep.split(' ')[1];
|
|
44
|
+
});
|
|
45
|
+
rootDep[rootDeps[0].split(' ')[0]] = {};
|
|
46
|
+
edges.forEach(edge => {
|
|
47
|
+
const splitEdge = edge.split('@');
|
|
48
|
+
const splitGroupName = splitEdge[0].split('/');
|
|
49
|
+
const name = splitGroupName.pop();
|
|
50
|
+
const lastSlash = splitEdge[0].lastIndexOf('/');
|
|
51
|
+
let group = splitEdge[0].substring(0, lastSlash);
|
|
52
|
+
const hash = getHash(splitEdge[0]);
|
|
53
|
+
group = checkGroupExists(group, name);
|
|
54
|
+
const edgesOfDep = getAllDepsOfADepAsEdge(edge, deps);
|
|
55
|
+
rootDep[rootDeps[0].split(' ')[0]][edge] = {
|
|
56
|
+
artifactID: name,
|
|
57
|
+
group: group,
|
|
58
|
+
version: splitEdge[1],
|
|
59
|
+
scope: '"compile',
|
|
60
|
+
type: 'direct',
|
|
61
|
+
hash: hash,
|
|
62
|
+
edges: edgesOfDep
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
return rootDep;
|
|
66
|
+
};
|
|
67
|
+
const getRootDeps = deps => {
|
|
68
|
+
const rootDeps = deps.filter(dep => {
|
|
69
|
+
const parentDep = dep.split(' ')[0];
|
|
70
|
+
if (parentDep.split('@v').length === 1) {
|
|
71
|
+
return dep;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
return rootDeps;
|
|
75
|
+
};
|
|
76
|
+
const getHash = library => {
|
|
77
|
+
let shaSum = crypto.createHash('sha1');
|
|
78
|
+
shaSum.update(library);
|
|
79
|
+
return shaSum.digest('hex');
|
|
80
|
+
};
|
|
81
|
+
const getDirectDepNames = deps => {
|
|
82
|
+
const directDepNames = [];
|
|
83
|
+
deps.forEach(dep => {
|
|
84
|
+
const parentDep = dep.split(' ')[0];
|
|
85
|
+
if (parentDep.split('@v').length === 1) {
|
|
86
|
+
dep.split(' ')[1] !== undefined
|
|
87
|
+
? directDepNames.push(dep.split(' ')[1])
|
|
88
|
+
: null;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
return directDepNames;
|
|
92
|
+
};
|
|
93
|
+
const getAllUniqueTransitiveDepNames = (deps, directDepNames) => {
|
|
94
|
+
let uniqueDeps = [];
|
|
95
|
+
deps.forEach(dep => {
|
|
96
|
+
const parentDep = dep.split(' ')[0];
|
|
97
|
+
if (parentDep.split('@v').length !== 1) {
|
|
98
|
+
if (!directDepNames.includes(parentDep)) {
|
|
99
|
+
if (!uniqueDeps.includes(parentDep)) {
|
|
100
|
+
parentDep.length > 1 ? uniqueDeps.push(parentDep) : null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
return uniqueDeps;
|
|
106
|
+
};
|
|
107
|
+
const checkGroupExists = (group, name) => {
|
|
108
|
+
if (group === null || group === '') {
|
|
109
|
+
return name;
|
|
110
|
+
}
|
|
111
|
+
return group;
|
|
112
|
+
};
|
|
113
|
+
const createTransitiveDeps = (transitiveDeps, splitLines, rootNodes) => {
|
|
114
|
+
transitiveDeps.forEach(dep => {
|
|
115
|
+
const splitEdge = dep.split('@');
|
|
116
|
+
const splitGroupName = splitEdge[0].split('/');
|
|
117
|
+
const name = splitGroupName.pop();
|
|
118
|
+
const lastSlash = splitEdge[0].lastIndexOf('/');
|
|
119
|
+
let group = splitEdge[0].substring(0, lastSlash);
|
|
120
|
+
const hash = getHash(splitEdge[0]);
|
|
121
|
+
group = checkGroupExists(group, name);
|
|
122
|
+
const transitiveDep = {
|
|
123
|
+
artifactID: name,
|
|
124
|
+
group: group,
|
|
125
|
+
version: splitEdge[1],
|
|
126
|
+
scope: 'compile',
|
|
127
|
+
type: 'transitive',
|
|
128
|
+
hash: hash,
|
|
129
|
+
edges: {}
|
|
130
|
+
};
|
|
131
|
+
const edges = getAllDepsOfADepAsEdge(dep, splitLines);
|
|
132
|
+
transitiveDep.edges = edges;
|
|
133
|
+
const edgesAsName = getAllDepsOfADepAsName(dep, splitLines);
|
|
134
|
+
edgesAsName.forEach(dep => {
|
|
135
|
+
const splitEdge = dep.split('@');
|
|
136
|
+
const splitGroupName = splitEdge[0].split('/');
|
|
137
|
+
const name = splitGroupName.pop();
|
|
138
|
+
const lastSlash = splitEdge[0].lastIndexOf('/');
|
|
139
|
+
let group = splitEdge[0].substring(0, lastSlash);
|
|
140
|
+
const hash = getHash(splitEdge[0]);
|
|
141
|
+
group = checkGroupExists(group, name);
|
|
142
|
+
const transitiveDep = {
|
|
143
|
+
artifactID: name,
|
|
144
|
+
group: group,
|
|
145
|
+
version: splitEdge[1],
|
|
146
|
+
scope: 'compile',
|
|
147
|
+
type: 'transitive',
|
|
148
|
+
hash: hash,
|
|
149
|
+
edges: {}
|
|
150
|
+
};
|
|
151
|
+
rootNodes[Object.keys(rootNodes)[0]][dep] = transitiveDep;
|
|
152
|
+
});
|
|
153
|
+
rootNodes[Object.keys(rootNodes)[0]][dep] = transitiveDep;
|
|
154
|
+
});
|
|
155
|
+
};
|
|
156
|
+
module.exports = {
|
|
157
|
+
parseGoDependencies
|
|
158
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const child_process = require('child_process');
|
|
3
|
+
const i18n = require('i18n');
|
|
4
|
+
const getGoDependencies = config => {
|
|
5
|
+
let cmdStdout;
|
|
6
|
+
let cwd = config.projectPath
|
|
7
|
+
? config.projectPath.replace('go.mod', '')
|
|
8
|
+
: process.cwd();
|
|
9
|
+
try {
|
|
10
|
+
cmdStdout = child_process.execSync('go mod graph', { cwd });
|
|
11
|
+
return cmdStdout.toString();
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
if (err.message === 'spawnSync /bin/sh ENOENT') {
|
|
15
|
+
err.message =
|
|
16
|
+
'\n\n*************** No transitive dependencies ***************\n\nWe are unable to build a dependency tree view from your repository as there were no transitive dependencies found.';
|
|
17
|
+
}
|
|
18
|
+
console.log(i18n.__('goReadProjectFile', cwd, `${err.message ? err.message : ''}`));
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
module.exports = {
|
|
22
|
+
getGoDependencies
|
|
23
|
+
};
|