@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.
Files changed (138) hide show
  1. package/.prettierignore +0 -5
  2. package/dist/audit/autodetection/autoDetectLanguage.js +3 -3
  3. package/dist/audit/catalogueApplication/catalogueApplication.js +23 -5
  4. package/dist/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +4 -2
  5. package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +2 -1
  6. package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +2 -1
  7. package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +2 -1
  8. package/dist/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +5 -5
  9. package/dist/audit/languageAnalysisEngine/getProjectRootFilenames.js +9 -9
  10. package/dist/audit/languageAnalysisEngine/index.js +2 -2
  11. package/dist/audit/languageAnalysisEngine/languageAnalysisFactory.js +6 -27
  12. package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +25 -5
  13. package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +99 -20
  14. package/dist/audit/languageAnalysisEngine/report/models/reportListModel.js +2 -1
  15. package/dist/audit/languageAnalysisEngine/report/models/reportOutputModel.js +24 -0
  16. package/dist/audit/languageAnalysisEngine/report/models/reportSeverityModel.js +3 -1
  17. package/dist/audit/languageAnalysisEngine/report/models/severityCountModel.js +16 -0
  18. package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +35 -14
  19. package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +58 -47
  20. package/dist/audit/languageAnalysisEngine/sendSnapshot.js +65 -3
  21. package/dist/audit/save.js +29 -0
  22. package/dist/commands/audit/auditController.js +22 -6
  23. package/dist/commands/audit/help.js +24 -1
  24. package/dist/commands/audit/processAudit.js +8 -2
  25. package/dist/commands/audit/saveFile.js +7 -3
  26. package/dist/commands/scan/processScan.js +1 -1
  27. package/dist/commands/scan/sca/scaAnalysis.js +48 -11
  28. package/dist/common/HTTPClient.js +56 -15
  29. package/dist/common/errorHandling.js +6 -1
  30. package/dist/common/versionChecker.js +20 -5
  31. package/dist/constants/constants.js +13 -3
  32. package/dist/constants/locales.js +15 -12
  33. package/dist/constants.js +9 -4
  34. package/dist/index.js +4 -3
  35. package/dist/lambda/analytics.js +11 -0
  36. package/dist/lambda/lambda.js +35 -4
  37. package/dist/lambda/types.js +13 -0
  38. package/dist/sbom/generateSbom.js +4 -3
  39. package/dist/scaAnalysis/common/formatMessage.js +46 -1
  40. package/dist/scaAnalysis/common/treeUpload.js +1 -3
  41. package/dist/scaAnalysis/go/goAnalysis.js +17 -0
  42. package/dist/scaAnalysis/go/goParseDeps.js +158 -0
  43. package/dist/scaAnalysis/go/goReadDepFile.js +21 -0
  44. package/dist/scaAnalysis/java/analysis.js +11 -22
  45. package/dist/scaAnalysis/java/index.js +6 -6
  46. package/dist/scaAnalysis/java/javaBuildDepsParser.js +14 -1
  47. package/dist/scaAnalysis/javascript/analysis.js +110 -0
  48. package/dist/scaAnalysis/javascript/index.js +41 -0
  49. package/dist/scaAnalysis/php/analysis.js +89 -0
  50. package/dist/scaAnalysis/php/index.js +10 -0
  51. package/dist/scaAnalysis/python/analysis.js +42 -0
  52. package/dist/scaAnalysis/python/index.js +10 -0
  53. package/dist/scaAnalysis/ruby/analysis.js +226 -0
  54. package/dist/scaAnalysis/ruby/index.js +10 -0
  55. package/dist/scan/autoDetection.js +8 -4
  56. package/dist/scan/fileUtils.js +26 -8
  57. package/dist/scan/formatScanOutput.js +18 -17
  58. package/dist/scan/models/groupedResultsModel.js +1 -1
  59. package/dist/scan/models/scanResultsModel.js +3 -1
  60. package/dist/scan/populateProjectIdAndProjectName.js +2 -1
  61. package/dist/scan/scan.js +5 -3
  62. package/dist/scan/scanConfig.js +6 -1
  63. package/dist/scan/scanController.js +26 -6
  64. package/dist/scan/scanResults.js +20 -6
  65. package/dist/utils/commonApi.js +4 -1
  66. package/dist/utils/filterProjectPath.js +7 -2
  67. package/dist/utils/oraWrapper.js +5 -1
  68. package/package.json +13 -9
  69. package/src/audit/autodetection/autoDetectLanguage.ts +3 -3
  70. package/src/audit/catalogueApplication/catalogueApplication.js +28 -7
  71. package/src/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +11 -8
  72. package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +2 -1
  73. package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +2 -1
  74. package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +2 -1
  75. package/src/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +5 -5
  76. package/src/audit/languageAnalysisEngine/getProjectRootFilenames.js +11 -11
  77. package/src/audit/languageAnalysisEngine/index.js +2 -2
  78. package/src/audit/languageAnalysisEngine/languageAnalysisFactory.js +11 -31
  79. package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +35 -32
  80. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +179 -25
  81. package/src/audit/languageAnalysisEngine/report/models/reportLibraryModel.ts +3 -3
  82. package/src/audit/languageAnalysisEngine/report/models/reportListModel.ts +18 -11
  83. package/src/audit/languageAnalysisEngine/report/models/reportOutputModel.ts +29 -0
  84. package/src/audit/languageAnalysisEngine/report/models/reportSeverityModel.ts +12 -3
  85. package/src/audit/languageAnalysisEngine/report/models/severityCountModel.ts +20 -0
  86. package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +50 -18
  87. package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +88 -66
  88. package/src/audit/languageAnalysisEngine/sendSnapshot.js +78 -3
  89. package/src/audit/save.js +32 -0
  90. package/src/commands/audit/auditController.ts +23 -15
  91. package/src/commands/audit/help.ts +24 -1
  92. package/src/commands/audit/processAudit.ts +7 -4
  93. package/src/commands/audit/saveFile.ts +5 -1
  94. package/src/commands/scan/processScan.js +2 -1
  95. package/src/commands/scan/sca/scaAnalysis.js +70 -29
  96. package/src/common/HTTPClient.js +72 -25
  97. package/src/common/errorHandling.ts +10 -1
  98. package/src/common/versionChecker.ts +24 -5
  99. package/src/constants/constants.js +13 -3
  100. package/src/constants/locales.js +15 -12
  101. package/src/constants.js +9 -4
  102. package/src/index.ts +5 -3
  103. package/src/lambda/analytics.ts +9 -0
  104. package/src/lambda/arn.ts +2 -1
  105. package/src/lambda/lambda.ts +37 -17
  106. package/src/lambda/types.ts +35 -0
  107. package/src/lambda/utils.ts +2 -7
  108. package/src/sbom/generateSbom.ts +1 -1
  109. package/src/scaAnalysis/common/formatMessage.js +51 -1
  110. package/src/scaAnalysis/common/treeUpload.js +1 -6
  111. package/src/scaAnalysis/go/goAnalysis.js +19 -0
  112. package/src/scaAnalysis/go/goParseDeps.js +203 -0
  113. package/src/scaAnalysis/go/goReadDepFile.js +30 -0
  114. package/src/scaAnalysis/java/analysis.js +15 -32
  115. package/src/scaAnalysis/java/index.js +6 -6
  116. package/src/scaAnalysis/java/javaBuildDepsParser.js +15 -2
  117. package/src/scaAnalysis/javascript/analysis.js +127 -0
  118. package/src/scaAnalysis/javascript/index.js +56 -0
  119. package/src/scaAnalysis/php/analysis.js +98 -0
  120. package/src/scaAnalysis/php/index.js +11 -0
  121. package/src/scaAnalysis/python/analysis.js +49 -0
  122. package/src/scaAnalysis/python/index.js +11 -0
  123. package/src/scaAnalysis/ruby/analysis.js +282 -0
  124. package/src/scaAnalysis/ruby/index.js +11 -0
  125. package/src/scan/autoDetection.js +11 -7
  126. package/src/scan/fileUtils.js +27 -8
  127. package/src/scan/formatScanOutput.ts +26 -18
  128. package/src/scan/models/groupedResultsModel.ts +3 -3
  129. package/src/scan/models/resultContentModel.ts +1 -1
  130. package/src/scan/models/scanResultsModel.ts +5 -2
  131. package/src/scan/populateProjectIdAndProjectName.js +3 -1
  132. package/src/scan/scan.ts +8 -6
  133. package/src/scan/scanConfig.js +5 -1
  134. package/src/scan/scanController.js +30 -9
  135. package/src/scan/scanResults.js +31 -10
  136. package/src/utils/commonApi.js +4 -1
  137. package/src/utils/filterProjectPath.js +6 -2
  138. 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 analysis');
40
+ console.log('found multiple languages, please specify one using --file to run SCA audit');
37
41
  }
38
42
  };
39
- const manualDetectAuditFilesAndLanguages = async (projectPath) => {
40
- let projectRootFilenames = await rootFile.getProjectRootFilenames(projectPath);
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', projectPath));
47
+ console.log(i18n.__('languageAnalysisNoLanguage', file));
44
48
  return [];
45
49
  }
46
50
  return [identifiedLanguages];
@@ -17,18 +17,18 @@ const findFilesJava = async (languagesFound) => {
17
17
  onlyFiles: true
18
18
  });
19
19
  if (result.length > 0) {
20
- return languagesFound.push({ java: result });
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.lock.json'], {
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({ javascript: result });
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({ python: result });
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({ go: result });
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({ ruby: result });
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({ php: result });
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
- let projectOverview = getProjectOverview(scanResultsInstances.content);
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
- let headerRow = [
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
- let codeRow = [
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(`${entry.codePath}`)
67
+ chalk_1.default.hex('#F6F5F5').bold(`${codePath}`)
67
68
  ];
68
- let issueRow = [chalk_1.default.bold(`Issue`), chalk_1.default.bold(`:`), `${entry.issue}`];
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(content) {
101
- let acc = {
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.forEach((i) => {
110
- acc[i.severity.toLowerCase()] += 1;
111
- acc.total += 1;
112
- return acc;
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
- let line = chalk_1.default.bold(objName + ' : ');
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,7 @@ class GroupedResultsModel {
5
5
  constructor(ruleId) {
6
6
  this.ruleId = ruleId;
7
7
  this.colour = '#999999';
8
- this.codePathSet = new Set;
8
+ this.codePathSet = new Set();
9
9
  }
10
10
  }
11
11
  exports.GroupedResultsModel = GroupedResultsModel;
@@ -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 = scan.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
- console.log(i18n_1.default.__('genericServiceError', res.statusCode));
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
  }
@@ -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
- return { ...paramsAuth, ...scanParams };
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
- configToUse.projectId = await populateProjectIdAndProjectName.populateProjectId(configToUse);
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
- succeedSpinner(startScanSpinner, 'Contrast Scan complete');
50
- console.log(`----- Scan completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`);
51
- return { scanDetail, scanResultsInstances };
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 = {
@@ -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
- oraFunctions.failSpinner(startScanSpinner, i18n.__('scanNotCompleted', 'https://docs.contrastsecurity.com/en/binary-package-preparation.html'));
44
- result.body.errorMessage ? console.log(result.body.errorMessage) : '';
45
- if (result.body.errorMessage ===
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
- console.log(e.message.toString());
83
+ if (config.debug) {
84
+ console.log(e.message.toString());
85
+ }
72
86
  }
73
87
  };
74
88
  module.exports = {
@@ -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.env.PWD !== (undefined || null || 'undefined')) {
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('--project_path') + 1];
19
+ return process.argv[process.argv.indexOf('--file') + 1];
15
20
  }
16
21
  };
17
22
  module.exports = {
@@ -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.5",
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
- "format": "prettier --write \"**/*.{ts,tsx,js,css,scss,json,md,yml}\" .eslintrc.* .babelrc",
28
- "check-format": "prettier --check \"**/*.{ts,tsx,js,css,scss,json,md,yml}\" .eslintrc.* .babelrc",
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.0.0",
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": "^1.19.1",
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.ng",
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 { projectPath } = config
12
- const projectRootFilenames = getProjectRootFilenames(projectPath)
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', projectPath))
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 = mvnDependancyTreeOutput => {
38
- //shaves of the console output until it reaches the first digraph
39
- return mvnDependancyTreeOutput.substring(
40
- mvnDependancyTreeOutput.indexOf('digraph')
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 = shaveConsoleOutputUntilItFindsFirsDigraphMention
215
+ exports.shaveConsoleOutputUntilItFindsFirsDigraphMention =
216
+ shaveConsoleOutputUntilItFindsFirsDigraphMention
215
217
  exports.getDigraphObjInfo = getDigraphObjInfo
216
218
  exports.createDigraphObjKey = createDigraphObjKey
217
- exports.turnDigraphDependanciesIntoArrOfInnerDep = 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 = 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 = checkForMultipleIdentifiedProjectFiles
41
+ exports.checkForMultipleIdentifiedProjectFiles =
42
+ checkForMultipleIdentifiedProjectFiles