@contrast/contrast 1.0.5 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierignore +0 -5
- package/dist/audit/autodetection/autoDetectLanguage.js +3 -3
- package/dist/audit/catalogueApplication/catalogueApplication.js +23 -5
- 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/getIdentifiedLanguageInfo.js +5 -5
- package/dist/audit/languageAnalysisEngine/getProjectRootFilenames.js +9 -9
- package/dist/audit/languageAnalysisEngine/index.js +2 -2
- package/dist/audit/languageAnalysisEngine/languageAnalysisFactory.js +6 -27
- package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +25 -5
- package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +99 -20
- package/dist/audit/languageAnalysisEngine/report/models/reportListModel.js +2 -1
- 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 +16 -0
- package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +35 -14
- package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +58 -47
- package/dist/audit/languageAnalysisEngine/sendSnapshot.js +65 -3
- package/dist/audit/save.js +29 -0
- package/dist/commands/audit/auditController.js +22 -6
- package/dist/commands/audit/help.js +24 -1
- package/dist/commands/audit/processAudit.js +8 -2
- package/dist/commands/audit/saveFile.js +7 -3
- package/dist/commands/scan/processScan.js +1 -1
- package/dist/commands/scan/sca/scaAnalysis.js +48 -11
- package/dist/common/HTTPClient.js +56 -15
- package/dist/common/errorHandling.js +6 -1
- package/dist/common/versionChecker.js +20 -5
- package/dist/constants/constants.js +13 -3
- package/dist/constants/locales.js +15 -12
- package/dist/constants.js +9 -4
- package/dist/index.js +4 -3
- package/dist/lambda/analytics.js +11 -0
- package/dist/lambda/lambda.js +35 -4
- package/dist/lambda/types.js +13 -0
- package/dist/sbom/generateSbom.js +4 -3
- package/dist/scaAnalysis/common/formatMessage.js +46 -1
- package/dist/scaAnalysis/common/treeUpload.js +1 -3
- package/dist/scaAnalysis/go/goAnalysis.js +17 -0
- package/dist/scaAnalysis/go/goParseDeps.js +158 -0
- package/dist/scaAnalysis/go/goReadDepFile.js +21 -0
- package/dist/scaAnalysis/java/analysis.js +11 -22
- package/dist/scaAnalysis/java/index.js +6 -6
- package/dist/scaAnalysis/java/javaBuildDepsParser.js +14 -1
- package/dist/scaAnalysis/javascript/analysis.js +110 -0
- package/dist/scaAnalysis/javascript/index.js +41 -0
- package/dist/scaAnalysis/php/analysis.js +89 -0
- package/dist/scaAnalysis/php/index.js +10 -0
- package/dist/scaAnalysis/python/analysis.js +42 -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 +8 -4
- package/dist/scan/fileUtils.js +26 -8
- package/dist/scan/formatScanOutput.js +18 -17
- package/dist/scan/models/groupedResultsModel.js +1 -1
- package/dist/scan/models/scanResultsModel.js +3 -1
- package/dist/scan/populateProjectIdAndProjectName.js +2 -1
- package/dist/scan/scan.js +5 -3
- package/dist/scan/scanConfig.js +6 -1
- package/dist/scan/scanController.js +26 -6
- package/dist/scan/scanResults.js +20 -6
- package/dist/utils/commonApi.js +4 -1
- package/dist/utils/filterProjectPath.js +7 -2
- package/dist/utils/oraWrapper.js +5 -1
- package/package.json +13 -9
- package/src/audit/autodetection/autoDetectLanguage.ts +3 -3
- package/src/audit/catalogueApplication/catalogueApplication.js +28 -7
- 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/getIdentifiedLanguageInfo.js +5 -5
- package/src/audit/languageAnalysisEngine/getProjectRootFilenames.js +11 -11
- package/src/audit/languageAnalysisEngine/index.js +2 -2
- package/src/audit/languageAnalysisEngine/languageAnalysisFactory.js +11 -31
- package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +35 -32
- package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +179 -25
- package/src/audit/languageAnalysisEngine/report/models/reportLibraryModel.ts +3 -3
- package/src/audit/languageAnalysisEngine/report/models/reportListModel.ts +18 -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 +20 -0
- package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +50 -18
- package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +88 -66
- package/src/audit/languageAnalysisEngine/sendSnapshot.js +78 -3
- package/src/audit/save.js +32 -0
- package/src/commands/audit/auditController.ts +23 -15
- package/src/commands/audit/help.ts +24 -1
- package/src/commands/audit/processAudit.ts +7 -4
- package/src/commands/audit/saveFile.ts +5 -1
- package/src/commands/scan/processScan.js +2 -1
- package/src/commands/scan/sca/scaAnalysis.js +70 -29
- package/src/common/HTTPClient.js +72 -25
- package/src/common/errorHandling.ts +10 -1
- package/src/common/versionChecker.ts +24 -5
- package/src/constants/constants.js +13 -3
- package/src/constants/locales.js +15 -12
- package/src/constants.js +9 -4
- package/src/index.ts +5 -3
- 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/sbom/generateSbom.ts +1 -1
- package/src/scaAnalysis/common/formatMessage.js +51 -1
- package/src/scaAnalysis/common/treeUpload.js +1 -6
- package/src/scaAnalysis/go/goAnalysis.js +19 -0
- package/src/scaAnalysis/go/goParseDeps.js +203 -0
- package/src/scaAnalysis/go/goReadDepFile.js +30 -0
- package/src/scaAnalysis/java/analysis.js +15 -32
- package/src/scaAnalysis/java/index.js +6 -6
- package/src/scaAnalysis/java/javaBuildDepsParser.js +15 -2
- package/src/scaAnalysis/javascript/analysis.js +127 -0
- package/src/scaAnalysis/javascript/index.js +56 -0
- package/src/scaAnalysis/php/analysis.js +98 -0
- package/src/scaAnalysis/php/index.js +11 -0
- package/src/scaAnalysis/python/analysis.js +49 -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 +11 -7
- package/src/scan/fileUtils.js +27 -8
- package/src/scan/formatScanOutput.ts +26 -18
- package/src/scan/models/groupedResultsModel.ts +3 -3
- package/src/scan/models/resultContentModel.ts +1 -1
- package/src/scan/models/scanResultsModel.ts +5 -2
- package/src/scan/populateProjectIdAndProjectName.js +3 -1
- package/src/scan/scan.ts +8 -6
- package/src/scan/scanConfig.js +5 -1
- package/src/scan/scanController.js +30 -9
- package/src/scan/scanResults.js +31 -10
- package/src/utils/commonApi.js +4 -1
- package/src/utils/filterProjectPath.js +6 -2
- package/src/utils/oraWrapper.js +6 -1
|
@@ -11,6 +11,10 @@ const autoDetectFileAndLanguage = async (configToUse) => {
|
|
|
11
11
|
console.log(i18n.__('fileHasWhiteSpacesError'));
|
|
12
12
|
process.exit(1);
|
|
13
13
|
}
|
|
14
|
+
if (fileFinder.fileIsEmpty(entries[0])) {
|
|
15
|
+
console.log(i18n.__('scanFileIsEmpty'));
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
14
18
|
configToUse.file = entries[0];
|
|
15
19
|
if (configToUse.name === undefined) {
|
|
16
20
|
configToUse.name = entries[0];
|
|
@@ -33,14 +37,14 @@ const autoDetectAuditFilesAndLanguages = async () => {
|
|
|
33
37
|
return languagesFound;
|
|
34
38
|
}
|
|
35
39
|
else {
|
|
36
|
-
console.log('found multiple languages, please specify one using --file to run SCA
|
|
40
|
+
console.log('found multiple languages, please specify one using --file to run SCA audit');
|
|
37
41
|
}
|
|
38
42
|
};
|
|
39
|
-
const manualDetectAuditFilesAndLanguages =
|
|
40
|
-
let projectRootFilenames =
|
|
43
|
+
const manualDetectAuditFilesAndLanguages = file => {
|
|
44
|
+
let projectRootFilenames = rootFile.getProjectRootFilenames(file);
|
|
41
45
|
let identifiedLanguages = languageResolver.deduceLanguageScaAnalysis(projectRootFilenames);
|
|
42
46
|
if (Object.keys(identifiedLanguages).length === 0) {
|
|
43
|
-
console.log(i18n.__('languageAnalysisNoLanguage',
|
|
47
|
+
console.log(i18n.__('languageAnalysisNoLanguage', file));
|
|
44
48
|
return [];
|
|
45
49
|
}
|
|
46
50
|
return [identifiedLanguages];
|
package/dist/scan/fileUtils.js
CHANGED
|
@@ -17,18 +17,18 @@ const findFilesJava = async (languagesFound) => {
|
|
|
17
17
|
onlyFiles: true
|
|
18
18
|
});
|
|
19
19
|
if (result.length > 0) {
|
|
20
|
-
return languagesFound.push({
|
|
20
|
+
return languagesFound.push({ JAVA: result });
|
|
21
21
|
}
|
|
22
22
|
return languagesFound;
|
|
23
23
|
};
|
|
24
24
|
const findFilesJavascript = async (languagesFound) => {
|
|
25
|
-
const result = await fg(['**/package.json', '**/yarn.lock', '**/package
|
|
25
|
+
const result = await fg(['**/package.json', '**/yarn.lock', '**/package-lock.json'], {
|
|
26
26
|
dot: false,
|
|
27
27
|
deep: 1,
|
|
28
28
|
onlyFiles: true
|
|
29
29
|
});
|
|
30
30
|
if (result.length > 0) {
|
|
31
|
-
return languagesFound.push({
|
|
31
|
+
return languagesFound.push({ JAVASCRIPT: result });
|
|
32
32
|
}
|
|
33
33
|
return languagesFound;
|
|
34
34
|
};
|
|
@@ -39,7 +39,7 @@ const findFilesPython = async (languagesFound) => {
|
|
|
39
39
|
onlyFiles: true
|
|
40
40
|
});
|
|
41
41
|
if (result.length > 0) {
|
|
42
|
-
return languagesFound.push({
|
|
42
|
+
return languagesFound.push({ PYTHON: result });
|
|
43
43
|
}
|
|
44
44
|
return languagesFound;
|
|
45
45
|
};
|
|
@@ -50,7 +50,7 @@ const findFilesGo = async (languagesFound) => {
|
|
|
50
50
|
onlyFiles: true
|
|
51
51
|
});
|
|
52
52
|
if (result.length > 0) {
|
|
53
|
-
return languagesFound.push({
|
|
53
|
+
return languagesFound.push({ GO: result });
|
|
54
54
|
}
|
|
55
55
|
return languagesFound;
|
|
56
56
|
};
|
|
@@ -61,7 +61,7 @@ const findFilesRuby = async (languagesFound) => {
|
|
|
61
61
|
onlyFiles: true
|
|
62
62
|
});
|
|
63
63
|
if (result.length > 0) {
|
|
64
|
-
return languagesFound.push({
|
|
64
|
+
return languagesFound.push({ RUBY: result });
|
|
65
65
|
}
|
|
66
66
|
return languagesFound;
|
|
67
67
|
};
|
|
@@ -72,7 +72,7 @@ const findFilesPhp = async (languagesFound) => {
|
|
|
72
72
|
onlyFiles: true
|
|
73
73
|
});
|
|
74
74
|
if (result.length > 0) {
|
|
75
|
-
return languagesFound.push({
|
|
75
|
+
return languagesFound.push({ PHP: result });
|
|
76
76
|
}
|
|
77
77
|
return languagesFound;
|
|
78
78
|
};
|
|
@@ -90,6 +90,23 @@ const checkFilePermissions = file => {
|
|
|
90
90
|
const fileExists = path => {
|
|
91
91
|
return fs.existsSync(path);
|
|
92
92
|
};
|
|
93
|
+
const fileIsEmpty = path => {
|
|
94
|
+
if (fileExists(path) && checkFilePermissions(path)) {
|
|
95
|
+
try {
|
|
96
|
+
return fs.readFileSync(path).length === 0;
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
if (e.message.toString().includes('illegal operation on a directory, read')) {
|
|
100
|
+
console.log('file provided cannot be a directory');
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
console.log(e.message.toString());
|
|
104
|
+
}
|
|
105
|
+
process.exit(0);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return false;
|
|
109
|
+
};
|
|
93
110
|
module.exports = {
|
|
94
111
|
findFile,
|
|
95
112
|
fileExists,
|
|
@@ -99,5 +116,6 @@ module.exports = {
|
|
|
99
116
|
findFilesPython,
|
|
100
117
|
findFilesGo,
|
|
101
118
|
findFilesPhp,
|
|
102
|
-
findFilesRuby
|
|
119
|
+
findFilesRuby,
|
|
120
|
+
fileIsEmpty
|
|
103
121
|
};
|
|
@@ -12,7 +12,7 @@ const cli_table3_1 = __importDefault(require("cli-table3"));
|
|
|
12
12
|
const constants_1 = require("../constants/constants");
|
|
13
13
|
function formatScanOutput(scanResults) {
|
|
14
14
|
const { scanResultsInstances } = scanResults;
|
|
15
|
-
|
|
15
|
+
const projectOverview = getProjectOverview(scanResultsInstances);
|
|
16
16
|
if (scanResultsInstances.content.length === 0) {
|
|
17
17
|
console.log(i18n_1.default.__('scanNoVulnerabilitiesFound'));
|
|
18
18
|
console.log(i18n_1.default.__('scanNoVulnerabilitiesFoundSecureCode'));
|
|
@@ -52,7 +52,7 @@ function formatScanOutput(scanResults) {
|
|
|
52
52
|
});
|
|
53
53
|
let learnRow = [];
|
|
54
54
|
let adviceRow = [];
|
|
55
|
-
|
|
55
|
+
const headerRow = [
|
|
56
56
|
chalk_1.default
|
|
57
57
|
.hex(entry.colour)
|
|
58
58
|
.bold(`CONTRAST-${count.toString().padStart(3, '0')}`),
|
|
@@ -60,12 +60,13 @@ function formatScanOutput(scanResults) {
|
|
|
60
60
|
chalk_1.default.hex(entry.colour).bold(`[${entry.severity}] ${entry.ruleId}`) +
|
|
61
61
|
entry.message
|
|
62
62
|
];
|
|
63
|
-
|
|
63
|
+
const codePath = entry.codePath?.replace(/^@/, '');
|
|
64
|
+
const codeRow = [
|
|
64
65
|
chalk_1.default.hex('#F6F5F5').bold(`Code`),
|
|
65
66
|
chalk_1.default.hex('#F6F5F5').bold(`:`),
|
|
66
|
-
chalk_1.default.hex('#F6F5F5').bold(`${
|
|
67
|
+
chalk_1.default.hex('#F6F5F5').bold(`${codePath}`)
|
|
67
68
|
];
|
|
68
|
-
|
|
69
|
+
const issueRow = [chalk_1.default.bold(`Issue`), chalk_1.default.bold(`:`), `${entry.issue}`];
|
|
69
70
|
table.push(headerRow, codeRow, issueRow);
|
|
70
71
|
if (entry?.advice) {
|
|
71
72
|
adviceRow = [
|
|
@@ -97,8 +98,8 @@ function printVulnInfo(projectOverview) {
|
|
|
97
98
|
console.log(chalk_1.default.bold(`Found ${totalVulnerabilities} ${vulMessage}`));
|
|
98
99
|
console.log(i18n_1.default.__('foundDetailedVulnerabilities', String(projectOverview.critical), String(projectOverview.high), String(projectOverview.medium), String(projectOverview.low), String(projectOverview.note)));
|
|
99
100
|
}
|
|
100
|
-
function getProjectOverview(
|
|
101
|
-
|
|
101
|
+
function getProjectOverview(scanResultsInstances) {
|
|
102
|
+
const acc = {
|
|
102
103
|
critical: 0,
|
|
103
104
|
high: 0,
|
|
104
105
|
medium: 0,
|
|
@@ -106,16 +107,19 @@ function getProjectOverview(content) {
|
|
|
106
107
|
note: 0,
|
|
107
108
|
total: 0
|
|
108
109
|
};
|
|
109
|
-
content
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
if (scanResultsInstances?.content &&
|
|
111
|
+
scanResultsInstances.content.length > 0) {
|
|
112
|
+
scanResultsInstances.content.forEach((i) => {
|
|
113
|
+
acc[i.severity.toLowerCase()] += 1;
|
|
114
|
+
acc.total += 1;
|
|
115
|
+
return acc;
|
|
116
|
+
});
|
|
117
|
+
}
|
|
114
118
|
return acc;
|
|
115
119
|
}
|
|
116
120
|
exports.getProjectOverview = getProjectOverview;
|
|
117
121
|
function formatLinks(objName, entry) {
|
|
118
|
-
|
|
122
|
+
const line = chalk_1.default.bold(objName + ' : ');
|
|
119
123
|
if (entry.length === 1) {
|
|
120
124
|
console.log(line + chalk_1.default.hex('#97DCF7').bold.underline(entry[0]));
|
|
121
125
|
}
|
|
@@ -176,10 +180,7 @@ function getCodeFlowInfo(resultEntry) {
|
|
|
176
180
|
}
|
|
177
181
|
exports.getCodeFlowInfo = getCodeFlowInfo;
|
|
178
182
|
function stripTags(oldString) {
|
|
179
|
-
return oldString
|
|
180
|
-
.replace(/\n/g, ' ')
|
|
181
|
-
.replace(/\s+/g, ' ')
|
|
182
|
-
.trim();
|
|
183
|
+
return oldString.replace(/\n/g, ' ').replace(/\s+/g, ' ').trim();
|
|
183
184
|
}
|
|
184
185
|
exports.stripTags = stripTags;
|
|
185
186
|
function assignBySeverity(entry, assignedObj) {
|
|
@@ -5,7 +5,9 @@ class ScanResultsModel {
|
|
|
5
5
|
constructor(scan) {
|
|
6
6
|
this.projectOverview = scan.projectOverview;
|
|
7
7
|
this.scanDetail = scan.scanDetail;
|
|
8
|
-
this.scanResultsInstances =
|
|
8
|
+
this.scanResultsInstances =
|
|
9
|
+
scan.scanResultsInstances;
|
|
10
|
+
this.newProject = scan.newProject;
|
|
9
11
|
}
|
|
10
12
|
}
|
|
11
13
|
exports.ScanResultsModel = ScanResultsModel;
|
|
@@ -8,8 +8,9 @@ const populateProjectId = async (config) => {
|
|
|
8
8
|
proj = await getExistingProjectIdByName(config, client).then(res => {
|
|
9
9
|
return res;
|
|
10
10
|
});
|
|
11
|
+
return { projectId: proj, isNewProject: false };
|
|
11
12
|
}
|
|
12
|
-
return proj;
|
|
13
|
+
return { projectId: proj, isNewProject: true };
|
|
13
14
|
};
|
|
14
15
|
const createProjectId = async (config, client) => {
|
|
15
16
|
return client
|
package/dist/scan/scan.js
CHANGED
|
@@ -41,19 +41,21 @@ const sendScan = async (config) => {
|
|
|
41
41
|
}
|
|
42
42
|
else {
|
|
43
43
|
if (config.debug) {
|
|
44
|
-
console.log(res.statusCode);
|
|
45
44
|
console.log(config);
|
|
45
|
+
oraWrapper_1.default.failSpinner(startUploadSpinner, i18n_1.default.__('uploadingScanFail'));
|
|
46
|
+
console.log(i18n_1.default.__('genericServiceError', res.statusCode));
|
|
46
47
|
}
|
|
47
|
-
oraWrapper_1.default.failSpinner(startUploadSpinner, i18n_1.default.__('uploadingScanFail'));
|
|
48
48
|
if (res.statusCode === 403) {
|
|
49
49
|
console.log(i18n_1.default.__('permissionsError'));
|
|
50
50
|
process.exit(1);
|
|
51
51
|
}
|
|
52
|
-
|
|
52
|
+
oraWrapper_1.default.stopSpinner(startUploadSpinner);
|
|
53
|
+
console.log('Contrast Scan Finished');
|
|
53
54
|
process.exit(1);
|
|
54
55
|
}
|
|
55
56
|
})
|
|
56
57
|
.catch(err => {
|
|
58
|
+
oraWrapper_1.default.stopSpinner(startUploadSpinner);
|
|
57
59
|
console.log(err);
|
|
58
60
|
});
|
|
59
61
|
}
|
package/dist/scan/scanConfig.js
CHANGED
|
@@ -21,10 +21,15 @@ const getScanConfig = argv => {
|
|
|
21
21
|
process.exit(1);
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
+
let projectNameSource;
|
|
24
25
|
if (!scanParams.name && scanParams.file) {
|
|
25
26
|
scanParams.name = getFileName(scanParams.file);
|
|
27
|
+
projectNameSource = 'AUTO';
|
|
26
28
|
}
|
|
27
|
-
|
|
29
|
+
else {
|
|
30
|
+
projectNameSource = 'USER';
|
|
31
|
+
}
|
|
32
|
+
return { ...paramsAuth, ...scanParams, projectNameSource };
|
|
28
33
|
};
|
|
29
34
|
const getFileName = file => {
|
|
30
35
|
return file.split(path.sep).pop();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const i18n = require('i18n');
|
|
3
|
-
const { returnOra, startSpinner, succeedSpinner } = require('../utils/oraWrapper');
|
|
3
|
+
const { returnOra, startSpinner, succeedSpinner, stopSpinner } = require('../utils/oraWrapper');
|
|
4
4
|
const populateProjectIdAndProjectName = require('./populateProjectIdAndProjectName');
|
|
5
5
|
const scan = require('./scan');
|
|
6
6
|
const scanResults = require('./scanResults');
|
|
@@ -24,6 +24,10 @@ const fileAndLanguageLogic = async (configToUse) => {
|
|
|
24
24
|
console.log(i18n.__('fileNotExist'));
|
|
25
25
|
process.exit(1);
|
|
26
26
|
}
|
|
27
|
+
if (fileFunctions.fileIsEmpty(configToUse.file)) {
|
|
28
|
+
console.log(i18n.__('scanFileIsEmpty'));
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
27
31
|
return configToUse;
|
|
28
32
|
}
|
|
29
33
|
else {
|
|
@@ -35,20 +39,36 @@ const fileAndLanguageLogic = async (configToUse) => {
|
|
|
35
39
|
const startScan = async (configToUse) => {
|
|
36
40
|
const startTime = performance.now();
|
|
37
41
|
await fileAndLanguageLogic(configToUse);
|
|
42
|
+
let newProject;
|
|
38
43
|
if (!configToUse.projectId) {
|
|
39
|
-
|
|
44
|
+
const { projectId, isNewProject } = await populateProjectIdAndProjectName.populateProjectId(configToUse);
|
|
45
|
+
configToUse.projectId = projectId;
|
|
46
|
+
newProject = isNewProject;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
newProject = false;
|
|
40
50
|
}
|
|
41
51
|
const codeArtifactId = await scan.sendScan(configToUse);
|
|
42
52
|
if (!configToUse.ff) {
|
|
43
53
|
const startScanSpinner = returnOra('🚀 Contrast Scan started');
|
|
44
54
|
startSpinner(startScanSpinner);
|
|
45
|
-
const scanDetail = await scanResults.returnScanResults(configToUse, codeArtifactId, getTimeout(configToUse), startScanSpinner);
|
|
55
|
+
const scanDetail = await scanResults.returnScanResults(configToUse, codeArtifactId, newProject, getTimeout(configToUse), startScanSpinner);
|
|
46
56
|
const scanResultsInstances = await scanResults.returnScanResultsInstances(configToUse, scanDetail.id);
|
|
47
57
|
const endTime = performance.now();
|
|
48
58
|
const scanDurationMs = endTime - startTime;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
59
|
+
if (scanResultsInstances.statusCode !== 200) {
|
|
60
|
+
stopSpinner(startScanSpinner);
|
|
61
|
+
console.log('Result Service is unavailable, please try again later');
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
succeedSpinner(startScanSpinner, 'Contrast Scan complete');
|
|
66
|
+
console.log(`----- Scan completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`);
|
|
67
|
+
return {
|
|
68
|
+
scanDetail,
|
|
69
|
+
scanResultsInstances: scanResultsInstances.body
|
|
70
|
+
};
|
|
71
|
+
}
|
|
52
72
|
}
|
|
53
73
|
};
|
|
54
74
|
module.exports = {
|
package/dist/scan/scanResults.js
CHANGED
|
@@ -4,6 +4,7 @@ const requestUtils = require('../../src/utils/requestUtils');
|
|
|
4
4
|
const oraFunctions = require('../utils/oraWrapper');
|
|
5
5
|
const _ = require('lodash');
|
|
6
6
|
const i18n = require('i18n');
|
|
7
|
+
const oraWrapper = require('../utils/oraWrapper');
|
|
7
8
|
const getScanId = async (config, codeArtifactId, client) => {
|
|
8
9
|
return client
|
|
9
10
|
.getScanId(config, codeArtifactId)
|
|
@@ -25,9 +26,13 @@ const pollScanResults = async (config, scanId, client) => {
|
|
|
25
26
|
console.log(err);
|
|
26
27
|
});
|
|
27
28
|
};
|
|
28
|
-
const returnScanResults = async (config, codeArtifactId, timeout, startScanSpinner) => {
|
|
29
|
+
const returnScanResults = async (config, codeArtifactId, newProject, timeout, startScanSpinner) => {
|
|
29
30
|
const client = commonApi.getHttpClient(config);
|
|
30
31
|
let scanId = await getScanId(config, codeArtifactId, client);
|
|
32
|
+
if (process.env.CODESEC_INVOCATION_ENVIRONMENT &&
|
|
33
|
+
process.env.CODESEC_INVOCATION_ENVIRONMENT.toUpperCase() === 'GITHUB') {
|
|
34
|
+
await client.createNewEvent(config, scanId, newProject);
|
|
35
|
+
}
|
|
31
36
|
let startTime = new Date();
|
|
32
37
|
let complete = false;
|
|
33
38
|
if (!_.isNil(scanId)) {
|
|
@@ -40,12 +45,16 @@ const returnScanResults = async (config, codeArtifactId, timeout, startScanSpinn
|
|
|
40
45
|
}
|
|
41
46
|
if (result.body.status === 'FAILED') {
|
|
42
47
|
complete = true;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
if (config.debug) {
|
|
49
|
+
oraFunctions.failSpinner(startScanSpinner, i18n.__('scanNotCompleted', 'https://docs.contrastsecurity.com/en/binary-package-preparation.html'));
|
|
50
|
+
}
|
|
51
|
+
if (result?.body?.errorMessage ===
|
|
46
52
|
'Unable to determine language for code artifact') {
|
|
53
|
+
console.log(result.body.errorMessage);
|
|
47
54
|
console.log('Try scanning again using --language param. ', i18n.__('scanOptionsLanguageSummary'));
|
|
48
55
|
}
|
|
56
|
+
oraWrapper.stopSpinner(startScanSpinner);
|
|
57
|
+
console.log('Contrast Scan Finished');
|
|
49
58
|
process.exit(1);
|
|
50
59
|
}
|
|
51
60
|
}
|
|
@@ -64,11 +73,16 @@ const returnScanResultsInstances = async (config, scanId) => {
|
|
|
64
73
|
try {
|
|
65
74
|
result = await client.getScanResultsInstances(config, scanId);
|
|
66
75
|
if (JSON.stringify(result.statusCode) == 200) {
|
|
67
|
-
return result.body;
|
|
76
|
+
return { body: result.body, statusCode: result.statusCode };
|
|
77
|
+
}
|
|
78
|
+
if (JSON.stringify(result.statusCode) == 503) {
|
|
79
|
+
return { statusCode: result.statusCode };
|
|
68
80
|
}
|
|
69
81
|
}
|
|
70
82
|
catch (e) {
|
|
71
|
-
|
|
83
|
+
if (config.debug) {
|
|
84
|
+
console.log(e.message.toString());
|
|
85
|
+
}
|
|
72
86
|
}
|
|
73
87
|
};
|
|
74
88
|
module.exports = {
|
package/dist/utils/commonApi.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const HttpClient = require('./../common/HTTPClient');
|
|
3
|
-
const { badRequestError, unauthenticatedError, forbiddenError, proxyError, genericError } = require('../common/errorHandling');
|
|
3
|
+
const { badRequestError, unauthenticatedError, forbiddenError, proxyError, genericError, maxAppError } = require('../common/errorHandling');
|
|
4
4
|
const handleResponseErrors = (res, api) => {
|
|
5
5
|
if (res.statusCode === 400) {
|
|
6
6
|
api === 'catalogue' ? badRequestError(true) : badRequestError(false);
|
|
@@ -14,6 +14,9 @@ const handleResponseErrors = (res, api) => {
|
|
|
14
14
|
else if (res.statusCode === 407) {
|
|
15
15
|
proxyError();
|
|
16
16
|
}
|
|
17
|
+
else if (res.statusCode === 412) {
|
|
18
|
+
maxAppError();
|
|
19
|
+
}
|
|
17
20
|
else {
|
|
18
21
|
genericError();
|
|
19
22
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const path = require('path');
|
|
3
|
+
const child_process = require('child_process');
|
|
3
4
|
function resolveFilePath(filepath) {
|
|
4
5
|
if (filepath[0] === '~') {
|
|
5
6
|
return path.join(process.env.HOME, filepath.slice(1));
|
|
@@ -7,11 +8,15 @@ function resolveFilePath(filepath) {
|
|
|
7
8
|
return filepath;
|
|
8
9
|
}
|
|
9
10
|
const returnProjectPath = () => {
|
|
10
|
-
if (process.
|
|
11
|
+
if (process.platform == 'win32') {
|
|
12
|
+
let winPath = child_process.execSync('cd').toString();
|
|
13
|
+
return winPath.replace(/\//g, '\\').trim();
|
|
14
|
+
}
|
|
15
|
+
else if (process.env.PWD !== (undefined || null || 'undefined')) {
|
|
11
16
|
return process.env.PWD;
|
|
12
17
|
}
|
|
13
18
|
else {
|
|
14
|
-
return process.argv[process.argv.indexOf('--
|
|
19
|
+
return process.argv[process.argv.indexOf('--file') + 1];
|
|
15
20
|
}
|
|
16
21
|
};
|
|
17
22
|
module.exports = {
|
package/dist/utils/oraWrapper.js
CHANGED
|
@@ -6,6 +6,9 @@ const returnOra = text => {
|
|
|
6
6
|
const startSpinner = spinner => {
|
|
7
7
|
spinner.start();
|
|
8
8
|
};
|
|
9
|
+
const stopSpinner = spinner => {
|
|
10
|
+
spinner.stop();
|
|
11
|
+
};
|
|
9
12
|
const succeedSpinner = (spinner, text) => {
|
|
10
13
|
spinner.succeed(text);
|
|
11
14
|
};
|
|
@@ -16,5 +19,6 @@ module.exports = {
|
|
|
16
19
|
returnOra,
|
|
17
20
|
startSpinner,
|
|
18
21
|
succeedSpinner,
|
|
19
|
-
failSpinner
|
|
22
|
+
failSpinner,
|
|
23
|
+
stopSpinner
|
|
20
24
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contrast/contrast",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "Contrast Security's command line tool",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -23,9 +23,10 @@
|
|
|
23
23
|
"test": "jest --testPathIgnorePatterns=./test-integration/",
|
|
24
24
|
"test-int": "jest ./test-integration/",
|
|
25
25
|
"test-int-scan": "jest ./test-integration/scan",
|
|
26
|
-
"test-int-audit": "jest ./test-integration/audit",
|
|
27
|
-
"
|
|
28
|
-
"
|
|
26
|
+
"test-int-audit": "jest ./test-integration/audit/audit.spec.js",
|
|
27
|
+
"test-int-audit-experimental": "jest ./test-integration/audit/audit-experimental.spec.js",
|
|
28
|
+
"format": "prettier --write \"**/*.{ts,tsx,js,json,md,yml}\" .eslintrc.*",
|
|
29
|
+
"check-format": "prettier --check \"**/*.{ts,tsx,js,json,md,yml}\" .eslintrc.*",
|
|
29
30
|
"coverage-local": "nyc --reporter=text mocha './test/**/*.spec.js'",
|
|
30
31
|
"coverage": "yarn test --coverage",
|
|
31
32
|
"lint": "eslint --config .eslintrc.json . --ext .ts",
|
|
@@ -53,7 +54,6 @@
|
|
|
53
54
|
"fast-glob": "^3.2.11",
|
|
54
55
|
"i18n": "^0.14.2",
|
|
55
56
|
"js-yaml": "^4.1.0",
|
|
56
|
-
"latest-version": "5.1.0",
|
|
57
57
|
"lodash": "^4.17.21",
|
|
58
58
|
"log-symbols": "^4.1.0",
|
|
59
59
|
"open": "^8.4.0",
|
|
@@ -74,12 +74,13 @@
|
|
|
74
74
|
"@types/i18n": "^0.13.2",
|
|
75
75
|
"@types/jest": "^27.4.1",
|
|
76
76
|
"@types/lodash": "^4.14.182",
|
|
77
|
+
"@types/node": "*",
|
|
77
78
|
"@typescript-eslint/eslint-plugin": "^5.21.0",
|
|
78
79
|
"@typescript-eslint/parser": "^5.21.0",
|
|
79
80
|
"csv-writer": "^1.6.0",
|
|
80
81
|
"eslint": "^8.14.0",
|
|
81
82
|
"eslint-config-prettier": "^8.5.0",
|
|
82
|
-
"eslint-plugin-prettier": "^4.
|
|
83
|
+
"eslint-plugin-prettier": "^4.2.1",
|
|
83
84
|
"husky": "^3.1.0",
|
|
84
85
|
"jest": "^27.5.1",
|
|
85
86
|
"jest-junit": "^13.2.0",
|
|
@@ -87,7 +88,7 @@
|
|
|
87
88
|
"npm-license-crawler": "^0.2.1",
|
|
88
89
|
"nyc": "^15.1.0",
|
|
89
90
|
"pkg": "^5.6.0",
|
|
90
|
-
"prettier": "^
|
|
91
|
+
"prettier": "^2.7.1",
|
|
91
92
|
"tmp": "^0.2.1",
|
|
92
93
|
"ts-jest": "^27.1.4",
|
|
93
94
|
"ts-node": "^10.7.0",
|
|
@@ -103,12 +104,15 @@
|
|
|
103
104
|
],
|
|
104
105
|
"prettier": {
|
|
105
106
|
"semi": false,
|
|
107
|
+
"trailingComma": "none",
|
|
108
|
+
"arrowParens": "avoid",
|
|
109
|
+
"bracketSpacing": true,
|
|
106
110
|
"singleQuote": true,
|
|
111
|
+
"bracketSameLine": true,
|
|
107
112
|
"overrides": [
|
|
108
113
|
{
|
|
109
114
|
"files": [
|
|
110
|
-
".eslintrc
|
|
111
|
-
".babelrc"
|
|
115
|
+
".eslintrc"
|
|
112
116
|
],
|
|
113
117
|
"options": {
|
|
114
118
|
"parser": "json"
|
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
import { getProjectRootFilenames } from '../languageAnalysisEngine/getProjectRootFilenames'
|
|
9
9
|
|
|
10
10
|
export function identifyLanguages(config: any) {
|
|
11
|
-
const {
|
|
12
|
-
const projectRootFilenames = getProjectRootFilenames(
|
|
11
|
+
const { file } = config
|
|
12
|
+
const projectRootFilenames = getProjectRootFilenames(file)
|
|
13
13
|
|
|
14
14
|
const identifiedLanguages = projectRootFilenames.reduce(
|
|
15
15
|
(accumulator: any, filename: string) => {
|
|
@@ -20,7 +20,7 @@ export function identifyLanguages(config: any) {
|
|
|
20
20
|
)
|
|
21
21
|
|
|
22
22
|
if (Object.keys(identifiedLanguages).length === 0) {
|
|
23
|
-
throw new Error(i18n.__('languageAnalysisNoLanguage',
|
|
23
|
+
throw new Error(i18n.__('languageAnalysisNoLanguage', file))
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
return reduceIdentifiedLanguages(identifiedLanguages)
|
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
const i18n = require('i18n')
|
|
2
1
|
const { getHttpClient, handleResponseErrors } = require('../../utils/commonApi')
|
|
3
2
|
|
|
4
|
-
const displaySuccessMessage = () => {
|
|
5
|
-
console.log(i18n.__('catalogueSuccessCommand'))
|
|
6
|
-
}
|
|
7
|
-
|
|
8
3
|
const catalogueApplication = async config => {
|
|
9
4
|
const client = getHttpClient(config)
|
|
10
5
|
let appId
|
|
@@ -14,8 +9,9 @@ const catalogueApplication = async config => {
|
|
|
14
9
|
if (res.statusCode === 201) {
|
|
15
10
|
//displaySuccessMessage(config, res.body.application.app_id)
|
|
16
11
|
appId = res.body.application.app_id
|
|
12
|
+
} else if (doesMessagesContainAppId(res)) {
|
|
13
|
+
appId = tryRetrieveAppIdFromMessages(res.body.messages)
|
|
17
14
|
} else {
|
|
18
|
-
// console.log(res.statusCode)
|
|
19
15
|
handleResponseErrors(res, 'catalogue')
|
|
20
16
|
}
|
|
21
17
|
})
|
|
@@ -25,6 +21,31 @@ const catalogueApplication = async config => {
|
|
|
25
21
|
return appId
|
|
26
22
|
}
|
|
27
23
|
|
|
24
|
+
const doesMessagesContainAppId = res => {
|
|
25
|
+
const regex = /(Application ID =)/
|
|
26
|
+
if (
|
|
27
|
+
res.statusCode === 400 &&
|
|
28
|
+
res.body.messages.filter(message => regex.exec(message))[0]
|
|
29
|
+
) {
|
|
30
|
+
return true
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return false
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const tryRetrieveAppIdFromMessages = messages => {
|
|
37
|
+
let appId
|
|
38
|
+
messages.forEach(message => {
|
|
39
|
+
if (message.includes('Application ID')) {
|
|
40
|
+
appId = message.split('=')[1].replace(/\s+/g, '')
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
return appId
|
|
45
|
+
}
|
|
46
|
+
|
|
28
47
|
module.exports = {
|
|
29
|
-
catalogueApplication: catalogueApplication
|
|
48
|
+
catalogueApplication: catalogueApplication,
|
|
49
|
+
doesMessagesContainAppId,
|
|
50
|
+
tryRetrieveAppIdFromMessages
|
|
30
51
|
}
|
|
@@ -34,12 +34,13 @@ const formatKeyName = value => {
|
|
|
34
34
|
return tempArr[0] + '/' + tempArr[1] + '@' + tempArr[versionIndex]
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
const shaveConsoleOutputUntilItFindsFirsDigraphMention =
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
mvnDependancyTreeOutput.
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
const shaveConsoleOutputUntilItFindsFirsDigraphMention =
|
|
38
|
+
mvnDependancyTreeOutput => {
|
|
39
|
+
//shaves of the console output until it reaches the first digraph
|
|
40
|
+
return mvnDependancyTreeOutput.substring(
|
|
41
|
+
mvnDependancyTreeOutput.indexOf('digraph')
|
|
42
|
+
)
|
|
43
|
+
}
|
|
43
44
|
|
|
44
45
|
const getDigraphObjInfo = editedOutput => {
|
|
45
46
|
//turns the output into an array of digraph information
|
|
@@ -211,10 +212,12 @@ const parseMvn = mvnDependancyTreeOutput => {
|
|
|
211
212
|
}
|
|
212
213
|
|
|
213
214
|
// testing purposes
|
|
214
|
-
exports.shaveConsoleOutputUntilItFindsFirsDigraphMention =
|
|
215
|
+
exports.shaveConsoleOutputUntilItFindsFirsDigraphMention =
|
|
216
|
+
shaveConsoleOutputUntilItFindsFirsDigraphMention
|
|
215
217
|
exports.getDigraphObjInfo = getDigraphObjInfo
|
|
216
218
|
exports.createDigraphObjKey = createDigraphObjKey
|
|
217
|
-
exports.turnDigraphDependanciesIntoArrOfInnerDep =
|
|
219
|
+
exports.turnDigraphDependanciesIntoArrOfInnerDep =
|
|
220
|
+
turnDigraphDependanciesIntoArrOfInnerDep
|
|
218
221
|
exports.hasVersion = hasVersion
|
|
219
222
|
exports.formatKeyName = formatKeyName
|
|
220
223
|
exports.createOuterDependanciesAndType = createOuterDependanciesAndType
|
|
@@ -32,4 +32,5 @@ const checkForMultipleIdentifiedLanguages = identifiedLanguages => {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
//For testing purposes
|
|
35
|
-
exports.checkForMultipleIdentifiedLanguages =
|
|
35
|
+
exports.checkForMultipleIdentifiedLanguages =
|
|
36
|
+
checkForMultipleIdentifiedLanguages
|
|
@@ -38,4 +38,5 @@ const checkForMultipleIdentifiedProjectFiles = identifiedLanguages => {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
//For testing purposes
|
|
41
|
-
exports.checkForMultipleIdentifiedProjectFiles =
|
|
41
|
+
exports.checkForMultipleIdentifiedProjectFiles =
|
|
42
|
+
checkForMultipleIdentifiedProjectFiles
|