@contrast/contrast 1.0.0 → 1.0.3

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 (213) hide show
  1. package/.prettierignore +3 -0
  2. package/README.md +115 -78
  3. package/dist/audit/AnalysisEngine.js +37 -0
  4. package/dist/audit/catalogueApplication/catalogueApplication.js +36 -0
  5. package/dist/audit/dotnetAnalysisEngine/index.js +25 -0
  6. package/dist/audit/dotnetAnalysisEngine/parseLockFileContents.js +35 -0
  7. package/dist/audit/dotnetAnalysisEngine/parseProjectFileContents.js +15 -0
  8. package/dist/audit/dotnetAnalysisEngine/readLockFileContents.js +18 -0
  9. package/dist/audit/dotnetAnalysisEngine/readProjectFileContents.js +14 -0
  10. package/dist/audit/dotnetAnalysisEngine/sanitizer.js +9 -0
  11. package/dist/audit/goAnalysisEngine/index.js +17 -0
  12. package/dist/audit/goAnalysisEngine/parseProjectFileContents.js +164 -0
  13. package/dist/audit/goAnalysisEngine/readProjectFileContents.js +21 -0
  14. package/dist/audit/goAnalysisEngine/sanitizer.js +5 -0
  15. package/dist/audit/javaAnalysisEngine/index.js +34 -0
  16. package/dist/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +153 -0
  17. package/dist/audit/javaAnalysisEngine/parseProjectFileContents.js +353 -0
  18. package/dist/audit/javaAnalysisEngine/readProjectFileContents.js +98 -0
  19. package/dist/audit/javaAnalysisEngine/sanitizer.js +5 -0
  20. package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +24 -0
  21. package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +24 -0
  22. package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasLockFile.js +35 -0
  23. package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +23 -0
  24. package/dist/audit/languageAnalysisEngine/commonApi.js +18 -0
  25. package/dist/audit/languageAnalysisEngine/constants.js +20 -0
  26. package/dist/audit/languageAnalysisEngine/filterProjectPath.js +20 -0
  27. package/dist/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +25 -0
  28. package/dist/audit/languageAnalysisEngine/getProjectRootFilenames.js +39 -0
  29. package/dist/audit/languageAnalysisEngine/index.js +39 -0
  30. package/dist/audit/languageAnalysisEngine/langugageAnalysisFactory.js +95 -0
  31. package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +121 -0
  32. package/dist/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +17 -0
  33. package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +257 -0
  34. package/dist/audit/languageAnalysisEngine/report/newReportingFeature.js +81 -0
  35. package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +133 -0
  36. package/dist/audit/languageAnalysisEngine/sendSnapshot.js +41 -0
  37. package/dist/audit/languageAnalysisEngine/util/capabilities.js +11 -0
  38. package/dist/audit/languageAnalysisEngine/util/generalAPI.js +39 -0
  39. package/dist/audit/languageAnalysisEngine/util/requestUtils.js +14 -0
  40. package/dist/audit/nodeAnalysisEngine/handleNPMLockFileV2.js +40 -0
  41. package/dist/audit/nodeAnalysisEngine/index.js +31 -0
  42. package/dist/audit/nodeAnalysisEngine/parseNPMLockFileContents.js +18 -0
  43. package/dist/audit/nodeAnalysisEngine/parseYarn2LockFileContents.js +51 -0
  44. package/dist/audit/nodeAnalysisEngine/parseYarnLockFileContents.js +18 -0
  45. package/dist/audit/nodeAnalysisEngine/readNPMLockFileContents.js +17 -0
  46. package/dist/audit/nodeAnalysisEngine/readProjectFileContents.js +14 -0
  47. package/dist/audit/nodeAnalysisEngine/readYarnLockFileContents.js +24 -0
  48. package/dist/audit/nodeAnalysisEngine/sanitizer.js +9 -0
  49. package/dist/audit/phpAnalysisEngine/index.js +23 -0
  50. package/dist/audit/phpAnalysisEngine/parseLockFileContents.js +52 -0
  51. package/dist/audit/phpAnalysisEngine/readLockFileContents.js +13 -0
  52. package/dist/audit/phpAnalysisEngine/readProjectFileContents.js +16 -0
  53. package/dist/audit/phpAnalysisEngine/sanitizer.js +5 -0
  54. package/dist/audit/pythonAnalysisEngine/index.js +25 -0
  55. package/dist/audit/pythonAnalysisEngine/parsePipfileLockContents.js +17 -0
  56. package/dist/audit/pythonAnalysisEngine/parseProjectFileContents.js +21 -0
  57. package/dist/audit/pythonAnalysisEngine/readPipfileLockFileContents.js +13 -0
  58. package/dist/audit/pythonAnalysisEngine/readPythonProjectFileContents.js +14 -0
  59. package/dist/audit/pythonAnalysisEngine/sanitizer.js +7 -0
  60. package/dist/audit/rubyAnalysisEngine/index.js +25 -0
  61. package/dist/audit/rubyAnalysisEngine/parseGemfileLockContents.js +176 -0
  62. package/dist/audit/rubyAnalysisEngine/parsedGemfile.js +22 -0
  63. package/dist/audit/rubyAnalysisEngine/readGemfileContents.js +14 -0
  64. package/dist/audit/rubyAnalysisEngine/readGemfileLockContents.js +14 -0
  65. package/dist/audit/rubyAnalysisEngine/sanitizer.js +6 -0
  66. package/dist/commands/audit/auditConfig.js +25 -0
  67. package/dist/commands/audit/auditController.js +31 -0
  68. package/dist/commands/audit/help.js +52 -0
  69. package/dist/commands/audit/processAudit.js +18 -0
  70. package/dist/commands/audit/saveFile.js +11 -0
  71. package/dist/commands/auth/auth.js +20 -2
  72. package/dist/commands/config/config.js +19 -8
  73. package/dist/commands/scan/processScan.js +9 -13
  74. package/dist/common/HTTPClient.js +112 -13
  75. package/dist/common/errorHandling.js +65 -1
  76. package/dist/common/versionChecker.js +30 -0
  77. package/dist/constants/constants.js +4 -2
  78. package/dist/constants/lambda.js +32 -4
  79. package/dist/constants/locales.js +60 -21
  80. package/dist/constants.js +181 -21
  81. package/dist/index.js +50 -23
  82. package/dist/lambda/aws.js +14 -11
  83. package/dist/lambda/help.js +4 -0
  84. package/dist/lambda/lambda.js +50 -27
  85. package/dist/lambda/lambdaUtils.js +72 -0
  86. package/dist/lambda/logUtils.js +11 -1
  87. package/dist/lambda/scanDetailCompletion.js +4 -4
  88. package/dist/lambda/scanRequest.js +11 -5
  89. package/dist/lambda/utils.js +110 -53
  90. package/dist/sbom/generateSbom.js +20 -0
  91. package/dist/scan/autoDetection.js +0 -32
  92. package/dist/scan/fileUtils.js +1 -1
  93. package/dist/scan/help.js +14 -40
  94. package/dist/scan/populateProjectIdAndProjectName.js +5 -0
  95. package/dist/scan/saveResults.js +14 -0
  96. package/dist/scan/scan.js +105 -40
  97. package/dist/scan/scanConfig.js +39 -0
  98. package/dist/scan/scanController.js +19 -16
  99. package/dist/scan/scanResults.js +24 -16
  100. package/dist/utils/commonApi.js +3 -3
  101. package/dist/utils/paramsUtil/commandlineParams.js +1 -20
  102. package/dist/utils/paramsUtil/paramHandler.js +3 -6
  103. package/dist/utils/parsedCLIOptions.js +14 -8
  104. package/dist/utils/requestUtils.js +1 -1
  105. package/dist/utils/saveFile.js +19 -0
  106. package/package.json +26 -21
  107. package/src/audit/AnalysisEngine.js +103 -0
  108. package/src/audit/catalogueApplication/catalogueApplication.js +42 -0
  109. package/src/audit/dotnetAnalysisEngine/index.js +26 -0
  110. package/src/audit/dotnetAnalysisEngine/parseLockFileContents.js +47 -0
  111. package/src/audit/dotnetAnalysisEngine/parseProjectFileContents.js +29 -0
  112. package/src/audit/dotnetAnalysisEngine/readLockFileContents.js +30 -0
  113. package/src/audit/dotnetAnalysisEngine/readProjectFileContents.js +26 -0
  114. package/src/audit/dotnetAnalysisEngine/sanitizer.js +11 -0
  115. package/src/audit/goAnalysisEngine/index.js +18 -0
  116. package/src/audit/goAnalysisEngine/parseProjectFileContents.js +209 -0
  117. package/src/audit/goAnalysisEngine/readProjectFileContents.js +31 -0
  118. package/src/audit/goAnalysisEngine/sanitizer.js +7 -0
  119. package/src/audit/javaAnalysisEngine/index.js +41 -0
  120. package/src/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +222 -0
  121. package/src/audit/javaAnalysisEngine/parseProjectFileContents.js +420 -0
  122. package/src/audit/javaAnalysisEngine/readProjectFileContents.js +141 -0
  123. package/src/audit/javaAnalysisEngine/sanitizer.js +6 -0
  124. package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +35 -0
  125. package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +41 -0
  126. package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasLockFile.js +54 -0
  127. package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +32 -0
  128. package/src/audit/languageAnalysisEngine/commonApi.js +20 -0
  129. package/src/audit/languageAnalysisEngine/constants.js +23 -0
  130. package/src/audit/languageAnalysisEngine/filterProjectPath.js +21 -0
  131. package/src/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +41 -0
  132. package/src/audit/languageAnalysisEngine/getProjectRootFilenames.js +72 -0
  133. package/src/audit/languageAnalysisEngine/index.js +45 -0
  134. package/src/audit/languageAnalysisEngine/langugageAnalysisFactory.js +126 -0
  135. package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +177 -0
  136. package/src/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +27 -0
  137. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.js +303 -0
  138. package/src/audit/languageAnalysisEngine/report/newReportingFeature.js +124 -0
  139. package/src/audit/languageAnalysisEngine/report/reportingFeature.js +190 -0
  140. package/src/audit/languageAnalysisEngine/sendSnapshot.js +51 -0
  141. package/src/audit/languageAnalysisEngine/util/capabilities.js +12 -0
  142. package/src/audit/languageAnalysisEngine/util/generalAPI.js +43 -0
  143. package/src/audit/languageAnalysisEngine/util/requestUtils.js +17 -0
  144. package/src/audit/nodeAnalysisEngine/handleNPMLockFileV2.js +49 -0
  145. package/src/audit/nodeAnalysisEngine/index.js +35 -0
  146. package/src/audit/nodeAnalysisEngine/parseNPMLockFileContents.js +20 -0
  147. package/src/audit/nodeAnalysisEngine/parseYarn2LockFileContents.js +63 -0
  148. package/src/audit/nodeAnalysisEngine/parseYarnLockFileContents.js +26 -0
  149. package/src/audit/nodeAnalysisEngine/readNPMLockFileContents.js +23 -0
  150. package/src/audit/nodeAnalysisEngine/readProjectFileContents.js +27 -0
  151. package/src/audit/nodeAnalysisEngine/readYarnLockFileContents.js +36 -0
  152. package/src/audit/nodeAnalysisEngine/sanitizer.js +11 -0
  153. package/src/audit/phpAnalysisEngine/index.js +27 -0
  154. package/src/audit/phpAnalysisEngine/parseLockFileContents.js +60 -0
  155. package/src/audit/phpAnalysisEngine/readLockFileContents.js +14 -0
  156. package/src/audit/phpAnalysisEngine/readProjectFileContents.js +25 -0
  157. package/src/audit/phpAnalysisEngine/sanitizer.js +4 -0
  158. package/src/audit/pythonAnalysisEngine/index.js +55 -0
  159. package/src/audit/pythonAnalysisEngine/parsePipfileLockContents.js +23 -0
  160. package/src/audit/pythonAnalysisEngine/parseProjectFileContents.js +33 -0
  161. package/src/audit/pythonAnalysisEngine/readPipfileLockFileContents.js +16 -0
  162. package/src/audit/pythonAnalysisEngine/readPythonProjectFileContents.js +22 -0
  163. package/src/audit/pythonAnalysisEngine/sanitizer.js +9 -0
  164. package/src/audit/rubyAnalysisEngine/index.js +30 -0
  165. package/src/audit/rubyAnalysisEngine/parseGemfileLockContents.js +215 -0
  166. package/src/audit/rubyAnalysisEngine/parsedGemfile.js +39 -0
  167. package/src/audit/rubyAnalysisEngine/readGemfileContents.js +18 -0
  168. package/src/audit/rubyAnalysisEngine/readGemfileLockContents.js +17 -0
  169. package/src/audit/rubyAnalysisEngine/sanitizer.js +8 -0
  170. package/src/commands/audit/auditConfig.ts +30 -0
  171. package/src/commands/audit/auditController.ts +31 -0
  172. package/src/commands/audit/help.ts +48 -0
  173. package/src/commands/audit/processAudit.ts +18 -0
  174. package/src/commands/audit/saveFile.ts +6 -0
  175. package/src/commands/auth/auth.js +26 -2
  176. package/src/commands/config/config.js +22 -8
  177. package/src/commands/scan/processScan.js +9 -13
  178. package/src/common/HTTPClient.js +149 -14
  179. package/src/common/errorHandling.ts +85 -2
  180. package/src/common/versionChecker.ts +39 -0
  181. package/src/constants/constants.js +5 -4
  182. package/src/constants/lambda.js +45 -4
  183. package/src/constants/locales.js +76 -26
  184. package/src/constants.js +204 -23
  185. package/src/index.ts +67 -27
  186. package/src/lambda/aws.ts +13 -12
  187. package/src/lambda/help.ts +4 -0
  188. package/src/lambda/lambda.ts +53 -34
  189. package/src/lambda/lambdaUtils.ts +111 -0
  190. package/src/lambda/logUtils.ts +19 -1
  191. package/src/lambda/scanDetailCompletion.ts +4 -4
  192. package/src/lambda/scanRequest.ts +13 -11
  193. package/src/lambda/utils.ts +149 -81
  194. package/src/sbom/generateSbom.ts +17 -0
  195. package/src/scan/autoDetection.js +0 -29
  196. package/src/scan/fileUtils.js +1 -1
  197. package/src/scan/help.js +14 -45
  198. package/src/scan/populateProjectIdAndProjectName.js +5 -0
  199. package/src/scan/saveResults.js +14 -0
  200. package/src/scan/scan.js +127 -58
  201. package/src/scan/scanConfig.js +54 -0
  202. package/src/scan/scanController.js +22 -15
  203. package/src/scan/scanResults.js +32 -19
  204. package/src/utils/commonApi.js +2 -3
  205. package/src/utils/getConfig.ts +2 -0
  206. package/src/utils/paramsUtil/commandlineParams.js +1 -26
  207. package/src/utils/paramsUtil/paramHandler.js +3 -7
  208. package/src/utils/parsedCLIOptions.js +11 -9
  209. package/src/utils/requestUtils.js +1 -1
  210. package/src/utils/saveFile.js +19 -0
  211. package/dist/lambda/scanDetail.js +0 -30
  212. package/dist/scan/fileFinder.js +0 -15
  213. package/dist/utils/paramsUtil/yamlParams.js +0 -6
@@ -19,6 +19,11 @@ const createProjectId = async (config, client) => {
19
19
  console.log(i18n.__('foundExistingProjectScan'));
20
20
  return;
21
21
  }
22
+ if (res.statusCode === 403) {
23
+ console.log(i18n.__('permissionsError'));
24
+ process.exit(1);
25
+ return;
26
+ }
22
27
  if (res.statusCode === 201) {
23
28
  console.log(i18n.__('projectCreatedScan'));
24
29
  if (config.verbose) {
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ const fs = require('fs');
3
+ const writeResultsToFile = async (responseBody, name = 'results.sarif') => {
4
+ try {
5
+ fs.writeFileSync(name, JSON.stringify(responseBody, null, 2));
6
+ console.log(`Scan Results saved to ${name}`);
7
+ }
8
+ catch (err) {
9
+ console.log('Error writing Scan Results to file');
10
+ }
11
+ };
12
+ module.exports = {
13
+ writeResultsToFile: writeResultsToFile
14
+ };
package/dist/scan/scan.js CHANGED
@@ -1,11 +1,10 @@
1
1
  "use strict";
2
2
  const commonApi = require('../utils/commonApi.js');
3
3
  const fileUtils = require('../scan/fileUtils');
4
- const allowedFileTypes = ['.jar', '.war', '.js', '.zip'];
4
+ const allowedFileTypes = ['.jar', '.war', '.js', '.zip', '.exe'];
5
5
  const i18n = require('i18n');
6
- const AdmZip = require('adm-zip');
7
6
  const oraWrapper = require('../utils/oraWrapper');
8
- const { supportedLanguages } = require('../constants/constants');
7
+ const chalk = require('chalk');
9
8
  const isFileAllowed = scanOption => {
10
9
  let valid = false;
11
10
  allowedFileTypes.forEach(fileType => {
@@ -15,6 +14,14 @@ const isFileAllowed = scanOption => {
15
14
  });
16
15
  return valid;
17
16
  };
17
+ const stripMustacheTags = oldString => {
18
+ return oldString
19
+ .replace(/\n/g, ' ')
20
+ .replace(/{{.*?}}/g, '\n')
21
+ .replace(/\$\$LINK_DELIM\$\$/g, '\n')
22
+ .replace(/\s+/g, ' ')
23
+ .trim();
24
+ };
18
25
  const sendScan = async (config) => {
19
26
  if (!isFileAllowed(config.file)) {
20
27
  console.log(i18n.__('scanErrorFileMessage'));
@@ -36,7 +43,16 @@ const sendScan = async (config) => {
36
43
  return res.body.id;
37
44
  }
38
45
  else {
46
+ if (config.debug) {
47
+ console.log(res.statusCode);
48
+ console.log(config);
49
+ }
39
50
  oraWrapper.failSpinner(startUploadSpinner, i18n.__('uploadingScanFail'));
51
+ if (res.statusCode === 403) {
52
+ console.log(i18n.__('permissionsError'));
53
+ process.exit(1);
54
+ }
55
+ console.log(i18n.__('genericServiceError', res.statusCode));
40
56
  process.exit(1);
41
57
  }
42
58
  })
@@ -45,52 +61,101 @@ const sendScan = async (config) => {
45
61
  });
46
62
  }
47
63
  };
48
- const zipValidator = configToUse => {
49
- if (configToUse.file.endsWith('.zip')) {
50
- let zipFileName = configToUse.file.split('/').pop();
51
- try {
52
- let zip = new AdmZip(configToUse.file);
53
- let zipEntries = zip.getEntries();
54
- zipEntries.forEach(function (zipEntry) {
55
- if (!zipEntry.entryName.includes('._') &&
56
- !zipEntry.entryName.includes('/.')) {
57
- if (!zipEntry.isDirectory) {
58
- if (!zipEntry.entryName.endsWith('.js')) {
59
- console.log(i18n.__('scanZipError', zipFileName));
60
- process.exit(1);
61
- }
62
- }
63
- }
64
+ const formatScanOutput = (overview, results) => {
65
+ console.log();
66
+ if (results.content.length === 0) {
67
+ console.log(i18n.__('scanNoVulnerabilitiesFound'));
68
+ }
69
+ else {
70
+ let message = overview.critical || overview.high
71
+ ? 'Here are your top priorities to fix'
72
+ : "No major issues, here's what we found";
73
+ console.log(chalk.bold(message));
74
+ console.log();
75
+ const groups = getGroups(results.content);
76
+ groups.forEach(entry => {
77
+ console.log(chalk.bold(`${entry.severity} | ${entry.ruleId} (${entry.lineInfoSet.size})`));
78
+ let count = 1;
79
+ entry.lineInfoSet.forEach(lineInfo => {
80
+ console.log(`\t ${count}. ${lineInfo}`);
81
+ count++;
64
82
  });
65
- configToUse.language = supportedLanguages.JAVASCRIPT;
66
- }
67
- catch {
68
- console.log(i18n.__('zipFileException'));
69
- }
83
+ if (entry?.cwe && entry?.cwe.length > 0) {
84
+ formatLinks('cwe', entry.cwe);
85
+ }
86
+ if (entry?.reference && entry?.reference.length > 0) {
87
+ formatLinks('reference', entry.reference);
88
+ }
89
+ if (entry?.owasp && entry?.owasp.length > 0) {
90
+ formatLinks('owasp', entry.owasp);
91
+ }
92
+ console.log(chalk.bold('How to fix:'));
93
+ console.log(entry.recommendation);
94
+ console.log();
95
+ });
96
+ const totalVulnerabilities = overview.critical +
97
+ overview.high +
98
+ overview.medium +
99
+ overview.low +
100
+ overview.note;
101
+ let vulMessage = totalVulnerabilities === 1 ? `vulnerability` : `vulnerabilities`;
102
+ console.log(chalk.bold(`Found ${totalVulnerabilities} ${vulMessage}`));
103
+ console.log(i18n.__('foundDetailedVulnerabilities', overview.critical, overview.high, overview.medium, overview.low, overview.note));
70
104
  }
71
105
  };
72
- const formatScanOutput = (overview, results) => {
73
- console.log();
74
- console.log('Here are your top priorities to fix');
106
+ const formatLinks = (objName, entry) => {
107
+ console.log(chalk.bold(objName + ':'));
108
+ entry.forEach(link => {
109
+ console.log(link);
110
+ });
75
111
  console.log();
76
- results.content.forEach(entry => {
77
- console.log(entry.severity, 'ID:', entry.id);
78
- console.log(entry.ruleId, 'in', entry.locations[0]?.physicalLocation.artifactLocation.uri, '@', entry.codeFlows[0]?.threadFlows[0]?.locations[0]?.location
79
- ?.physicalLocation?.region?.startLine);
80
- console.log();
112
+ };
113
+ const getGroups = content => {
114
+ const groupTypeSet = new Set(content.map(({ ruleId }) => ruleId));
115
+ let groupTypeResults = [];
116
+ groupTypeSet.forEach(groupName => {
117
+ let groupResultsObj = {
118
+ ruleId: groupName,
119
+ lineInfoSet: new Set(),
120
+ cwe: '',
121
+ owasp: '',
122
+ reference: '',
123
+ recommendation: '',
124
+ severity: ''
125
+ };
126
+ content.forEach(resultEntry => {
127
+ if (resultEntry.ruleId === groupName) {
128
+ groupResultsObj.severity = resultEntry.severity;
129
+ groupResultsObj.cwe = resultEntry.cwe;
130
+ groupResultsObj.owasp = resultEntry.owasp;
131
+ groupResultsObj.reference = resultEntry.reference;
132
+ groupResultsObj.recommendation = resultEntry.recommendation
133
+ ? stripMustacheTags(resultEntry.recommendation)
134
+ : 'No Recommendations Data Found';
135
+ groupResultsObj.lineInfoSet.add(formattedCodeLine(resultEntry));
136
+ }
137
+ });
138
+ groupTypeResults.push(groupResultsObj);
81
139
  });
82
- const totalVulnerabilities = overview.critical +
83
- overview.high +
84
- overview.medium +
85
- overview.low +
86
- overview.note;
87
- console.log(`Found ${totalVulnerabilities} vulnerabilities`);
88
- console.log(i18n.__('foundDetailedVulnerabilities', overview.critical, overview.high, overview.medium, overview.low, overview.note));
140
+ return groupTypeResults;
141
+ };
142
+ const formattedCodeLine = resultEntry => {
143
+ let lineUri = resultEntry.locations[0]?.physicalLocation.artifactLocation.uri;
144
+ return lineUri + ' @ ' + setLineNumber(resultEntry);
145
+ };
146
+ const setLineNumber = resultEntry => {
147
+ return resultEntry.codeFlows?.[0]?.threadFlows[0]?.locations[0]?.location
148
+ ?.physicalLocation?.region?.startLine
149
+ ? resultEntry.codeFlows[0]?.threadFlows[0]?.locations[0]?.location
150
+ ?.physicalLocation?.region?.startLine
151
+ : resultEntry.locations[0]?.physicalLocation?.region?.startLine;
89
152
  };
90
153
  module.exports = {
91
154
  sendScan: sendScan,
155
+ getGroups: getGroups,
92
156
  allowedFileTypes: allowedFileTypes,
93
157
  isFileAllowed: isFileAllowed,
158
+ stripMustacheTags: stripMustacheTags,
94
159
  formatScanOutput: formatScanOutput,
95
- zipValidator: zipValidator
160
+ formatLinks: formatLinks
96
161
  };
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ const paramHandler = require('../utils/paramsUtil/paramHandler');
3
+ const constants = require('../../src/constants.js');
4
+ const parsedCLIOptions = require('../../src/utils/parsedCLIOptions');
5
+ const path = require('path');
6
+ const { supportedLanguages } = require('../audit/languageAnalysisEngine/constants');
7
+ const i18n = require('i18n');
8
+ const { scanUsageGuide } = require('./help');
9
+ const getScanConfig = argv => {
10
+ let scanParams = parsedCLIOptions.getCommandLineArgsCustom(argv, constants.commandLineDefinitions.scanOptionDefinitions);
11
+ if (scanParams.help) {
12
+ printHelpMessage();
13
+ process.exit(0);
14
+ }
15
+ const paramsAuth = paramHandler.getAuth(scanParams);
16
+ if (scanParams.language) {
17
+ scanParams.language = scanParams.language.toUpperCase();
18
+ if (!Object.values(supportedLanguages).includes(scanParams.language)) {
19
+ console.log(`Did not recognise --language ${scanParams.language}`);
20
+ console.log(i18n.__('constantsHowToRunDev3'));
21
+ process.exit(0);
22
+ }
23
+ }
24
+ if (!scanParams.name && scanParams.file) {
25
+ scanParams.name = getFileName(scanParams.file);
26
+ }
27
+ return { ...paramsAuth, ...scanParams };
28
+ };
29
+ const getFileName = file => {
30
+ return file.split(path.sep).pop();
31
+ };
32
+ const printHelpMessage = () => {
33
+ console.log(scanUsageGuide);
34
+ };
35
+ module.exports = {
36
+ getScanConfig,
37
+ getFileName,
38
+ printHelpMessage
39
+ };
@@ -5,8 +5,8 @@ const populateProjectIdAndProjectName = require('./populateProjectIdAndProjectNa
5
5
  const scan = require('./scan');
6
6
  const scanResults = require('./scanResults');
7
7
  const autoDetection = require('./autoDetection');
8
- const paramHandler = require('../utils/paramsUtil/paramHandler');
9
8
  const fileFunctions = require('./fileUtils');
9
+ const { performance } = require('perf_hooks');
10
10
  const getTimeout = config => {
11
11
  if (config.timeout) {
12
12
  return config.timeout;
@@ -18,35 +18,38 @@ const getTimeout = config => {
18
18
  return 300;
19
19
  }
20
20
  };
21
- const startScan = async () => {
22
- let paramsAuth = paramHandler.getAuth();
23
- let getScanSubCommands = paramHandler.getScanSubCommands();
24
- const configToUse = { ...paramsAuth, ...getScanSubCommands };
25
- if (configToUse.file === undefined || configToUse.file === null) {
26
- await autoDetection.autoDetectFileAndLanguage(configToUse);
21
+ const fileAndLanguageLogic = async (configToUse) => {
22
+ if (configToUse.file) {
23
+ if (!fileFunctions.fileExists(configToUse.file)) {
24
+ console.log(i18n.__('fileNotExist'));
25
+ process.exit(1);
26
+ }
27
+ return configToUse;
27
28
  }
28
29
  else {
29
- if (fileFunctions.fileExists(configToUse.file)) {
30
- scan.zipValidator(configToUse);
31
- autoDetection.assignLanguage([configToUse.file], configToUse);
32
- }
33
- else {
34
- console.log(i18n.__('fileNotExist'));
35
- process.exit(0);
30
+ if (configToUse.file === undefined || configToUse.file === null) {
31
+ await autoDetection.autoDetectFileAndLanguage(configToUse);
36
32
  }
37
33
  }
34
+ };
35
+ const startScan = async (configToUse) => {
36
+ const startTime = performance.now();
37
+ await fileAndLanguageLogic(configToUse);
38
38
  if (!configToUse.projectId) {
39
39
  configToUse.projectId = await populateProjectIdAndProjectName.populateProjectId(configToUse);
40
40
  }
41
41
  const codeArtifactId = await scan.sendScan(configToUse);
42
42
  if (!configToUse.ff) {
43
- const startScanSpinner = returnOra('Contrast Scan started');
43
+ const startScanSpinner = returnOra('🚀 Contrast Scan started');
44
44
  startSpinner(startScanSpinner);
45
45
  const scanDetail = await scanResults.returnScanResults(configToUse, codeArtifactId, getTimeout(configToUse), startScanSpinner);
46
46
  const scanResultsInstances = await scanResults.returnScanResultsInstances(configToUse, scanDetail.id);
47
+ const endTime = performance.now();
48
+ const scanDurationMs = endTime - startTime;
47
49
  succeedSpinner(startScanSpinner, 'Contrast Scan complete');
50
+ console.log(`----- Scan completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`);
48
51
  const projectOverview = await scanResults.returnScanProjectById(configToUse);
49
- return { projectOverview, scanResultsInstances };
52
+ return { projectOverview, scanDetail, scanResultsInstances };
50
53
  }
51
54
  };
52
55
  module.exports = {
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  const commonApi = require('../utils/commonApi');
3
3
  const requestUtils = require('../../src/utils/requestUtils');
4
- const i18n = require('i18n');
5
4
  const oraFunctions = require('../utils/oraWrapper');
5
+ const _ = require('lodash');
6
+ const i18n = require('i18n');
6
7
  const getScanId = async (config, codeArtifactId, client) => {
7
8
  return client
8
9
  .getScanId(config, codeArtifactId)
@@ -29,25 +30,32 @@ const returnScanResults = async (config, codeArtifactId, timeout, startScanSpinn
29
30
  let scanId = await getScanId(config, codeArtifactId, client);
30
31
  let startTime = new Date();
31
32
  let complete = false;
32
- while (!complete) {
33
- let result = await pollScanResults(config, scanId, client);
34
- if (JSON.stringify(result.statusCode) == 200) {
35
- if (result.body.status === 'COMPLETED') {
36
- complete = true;
37
- return result.body;
33
+ if (!_.isNil(scanId)) {
34
+ while (!complete) {
35
+ let result = await pollScanResults(config, scanId, client);
36
+ if (JSON.stringify(result.statusCode) == 200) {
37
+ if (result.body.status === 'COMPLETED') {
38
+ complete = true;
39
+ return result.body;
40
+ }
41
+ if (result.body.status === 'FAILED') {
42
+ complete = true;
43
+ oraFunctions.failSpinner(startScanSpinner, 'Contrast Scan Failed.');
44
+ console.log(result.body.errorMessage);
45
+ if (result.body.errorMessage ===
46
+ 'Unable to determine language for code artifact') {
47
+ console.log('Try scanning again using --language param. ', i18n.__('scanOptionsLanguageSummary'));
48
+ }
49
+ process.exit(1);
50
+ }
38
51
  }
39
- if (result.body.status === 'FAILED') {
40
- complete = true;
41
- oraFunctions.failSpinner(startScanSpinner, 'Contrast Scan Failed.');
52
+ let endTime = new Date() - startTime;
53
+ if (requestUtils.millisToSeconds(endTime) > timeout) {
54
+ oraFunctions.failSpinner(startScanSpinner, 'Contrast Scan timed out at the specified ' + timeout + ' seconds.');
55
+ console.log('Please try again, allowing more time.');
42
56
  process.exit(1);
43
57
  }
44
58
  }
45
- let endTime = new Date() - startTime;
46
- if (requestUtils.millisToSeconds(endTime) > timeout) {
47
- oraFunctions.failSpinner(startScanSpinner, 'Contrast Scan timed out at the specified ' + timeout + ' seconds.');
48
- console.log('Please try again, allowing more time.');
49
- process.exit(1);
50
- }
51
59
  }
52
60
  };
53
61
  const returnScanResultsInstances = async (config, scanId) => {
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  const HttpClient = require('./../common/HTTPClient');
3
- const { badRequestError, unauthenticatedError, forbiddenError, proxyError, hostWarningError, genericError } = require('../common/errorHandling');
4
- const handleResponseErrors = (res, api, hostPresent) => {
3
+ const { badRequestError, unauthenticatedError, forbiddenError, proxyError, genericError } = require('../common/errorHandling');
4
+ const handleResponseErrors = (res, api) => {
5
5
  if (res.statusCode === 400) {
6
6
  api === 'catalogue' ? badRequestError(true) : badRequestError(false);
7
7
  }
@@ -15,7 +15,7 @@ const handleResponseErrors = (res, api, hostPresent) => {
15
15
  proxyError();
16
16
  }
17
17
  else {
18
- hostPresent === false ? hostWarningError() : genericError();
18
+ genericError();
19
19
  }
20
20
  };
21
21
  const getProtocol = host => {
@@ -1,7 +1,5 @@
1
1
  "use strict";
2
- const cliOptions = require('../parsedCLIOptions');
3
- const parsedCLIOptions = cliOptions.getCommandLineArgs();
4
- const getAuth = () => {
2
+ const getAuth = (parsedCLIOptions = {}) => {
5
3
  let params = {};
6
4
  params.apiKey = parsedCLIOptions['apiKey'];
7
5
  params.authorization = parsedCLIOptions['authorization'];
@@ -9,23 +7,6 @@ const getAuth = () => {
9
7
  params.organizationId = parsedCLIOptions['organizationId'];
10
8
  return params;
11
9
  };
12
- const getScanParams = () => {
13
- let scanParams = {};
14
- scanParams.help = parsedCLIOptions['help'];
15
- scanParams.file = parsedCLIOptions['file'];
16
- scanParams.language = parsedCLIOptions['language']
17
- ? parsedCLIOptions['language'].toUpperCase()
18
- : parsedCLIOptions['language'];
19
- scanParams.ff = parsedCLIOptions['ff'];
20
- scanParams.timeout = parsedCLIOptions['timeout'];
21
- scanParams.name = parsedCLIOptions['name'];
22
- scanParams.verbose = parsedCLIOptions['verbose'];
23
- if (!scanParams.name) {
24
- scanParams.name = scanParams.file;
25
- }
26
- return scanParams;
27
- };
28
10
  module.exports = {
29
- getScanParams: getScanParams,
30
11
  getAuth: getAuth
31
12
  };
@@ -4,8 +4,8 @@ const configStoreParams = require('./configStoreParams');
4
4
  const envVariableParams = require('./envVariableParams');
5
5
  const { validateAuthParams } = require('../validationCheck');
6
6
  const i18n = require('i18n');
7
- const getAuth = () => {
8
- let commandLineAuthParamsAuth = commandlineAuth.getAuth();
7
+ const getAuth = params => {
8
+ let commandLineAuthParamsAuth = commandlineAuth.getAuth(params);
9
9
  let envVariableParamsAuth = envVariableParams.getAuth();
10
10
  let configStoreParamsAuth = configStoreParams.getAuth();
11
11
  if (validateAuthParams(commandLineAuthParamsAuth)) {
@@ -22,7 +22,4 @@ const getAuth = () => {
22
22
  process.exit(1);
23
23
  }
24
24
  };
25
- const getScanSubCommands = () => {
26
- return commandlineAuth.getScanParams();
27
- };
28
- module.exports = { getAuth: getAuth, getScanSubCommands: getScanSubCommands };
25
+ module.exports = { getAuth: getAuth };
@@ -1,13 +1,19 @@
1
1
  "use strict";
2
- const constants = require('../constants');
3
2
  const commandLineArgs = require('command-line-args');
4
- const getCommandLineArgs = () => {
5
- return commandLineArgs(constants.commandLineDefinitions.scanOptionDefinitions, {
6
- partial: true,
7
- camelCase: true,
8
- caseInsensitive: true
9
- });
3
+ const getCommandLineArgsCustom = (parameterList, optionDefinitions) => {
4
+ try {
5
+ return commandLineArgs(optionDefinitions, {
6
+ argv: parameterList,
7
+ partial: false,
8
+ camelCase: true,
9
+ caseInsensitive: true
10
+ });
11
+ }
12
+ catch (e) {
13
+ console.log(e.message.toString());
14
+ process.exit(1);
15
+ }
10
16
  };
11
17
  module.exports = {
12
- getCommandLineArgs: getCommandLineArgs
18
+ getCommandLineArgsCustom
13
19
  };
@@ -6,7 +6,7 @@ function sendRequest({ options, method = 'put' }) {
6
6
  return request[`${method}Async`](options.url, options);
7
7
  }
8
8
  const millisToSeconds = millis => {
9
- return ((millis % 60000) / 1000).toFixed(0);
9
+ return (millis / 1000).toFixed(0);
10
10
  };
11
11
  const sleep = ms => {
12
12
  return new Promise(resolve => setTimeout(resolve, ms));
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ const { SARIF_FILE } = require('../constants/constants');
3
+ const commonApi = require('./commonApi');
4
+ const saveResults = require('../scan/saveResults');
5
+ const i18n = require('i18n');
6
+ const saveScanFile = async (config, scanResults) => {
7
+ if (config.save === null || config.save.toUpperCase() === SARIF_FILE) {
8
+ const scanId = scanResults.scanDetail.id;
9
+ const client = commonApi.getHttpClient(config);
10
+ const rawResults = await client.getSpecificScanResultSarif(config, scanId);
11
+ await saveResults.writeResultsToFile(rawResults?.body);
12
+ }
13
+ else {
14
+ console.log(i18n.__('scanNoFiletypeSpecifiedForSave'));
15
+ }
16
+ };
17
+ module.exports = {
18
+ saveScanFile: saveScanFile
19
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrast/contrast",
3
- "version": "1.0.0",
3
+ "version": "1.0.3",
4
4
  "description": "Contrast Security's command line tool",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -21,7 +21,9 @@
21
21
  "scripts": {
22
22
  "build": "tsc",
23
23
  "test": "jest --testPathIgnorePatterns=./test-integration/",
24
- "test-int": "jest ./test-integration/scan/",
24
+ "test-int": "jest ./test-integration/",
25
+ "test-int-scan": "jest ./test-integration/scan",
26
+ "test-int-audit": "jest ./test-integration/audit",
25
27
  "format": "prettier --write \"**/*.{ts,tsx,js,css,scss,json,md,yml}\" .eslintrc.* .babelrc",
26
28
  "check-format": "prettier --check \"**/*.{ts,tsx,js,css,scss,json,md,yml}\" .eslintrc.* .babelrc",
27
29
  "coverage-local": "nyc --reporter=text mocha './test/**/*.spec.js'",
@@ -36,26 +38,28 @@
36
38
  "node": ">=16.13.2 <17"
37
39
  },
38
40
  "dependencies": {
39
- "@aws-sdk/client-iam": "^3.53.0",
40
- "@aws-sdk/client-lambda": "^3.53.0",
41
+ "@aws-sdk/client-iam": "^3.78.0",
42
+ "@aws-sdk/client-lambda": "^3.78.0",
43
+ "@types/semver": "^7.3.9",
41
44
  "@yarnpkg/lockfile": "^1.1.0",
42
- "adm-zip": "^0.5.9",
43
45
  "bluebird": "^3.7.2",
44
- "chalk": "^4.1.2",
46
+ "boxen": "5.1.2",
47
+ "chalk": "4.1.2",
45
48
  "command-line-args": "^5.2.1",
46
- "command-line-usage": "^6.1.1",
47
- "conf": "^10.1.1",
49
+ "command-line-usage": "^6.1.3",
50
+ "conf": "^10.1.2",
48
51
  "dotenv": "^16.0.0",
49
52
  "fast-glob": "^3.2.11",
50
- "i18n": "^0.14.1",
53
+ "i18n": "^0.14.2",
51
54
  "js-yaml": "^4.1.0",
55
+ "latest-version": "5.1.0",
52
56
  "lodash": "^4.17.21",
53
57
  "log-symbols": "^4.1.0",
54
58
  "open": "^8.4.0",
55
59
  "ora": "5.4.1",
56
60
  "prettyjson": "^1.2.5",
57
61
  "request": "^2.88.2",
58
- "semver": "^7.3.5",
62
+ "semver": "^7.3.7",
59
63
  "string-builder": "^0.1.8",
60
64
  "string-multiple-replace": "^1.0.5",
61
65
  "tmp": "^0.2.1",
@@ -68,24 +72,25 @@
68
72
  "@types/command-line-usage": "^5.0.2",
69
73
  "@types/i18n": "^0.13.2",
70
74
  "@types/jest": "^27.4.1",
71
- "@types/lodash": "^4.14.181",
72
- "@typescript-eslint/eslint-plugin": "^5.13.0",
73
- "@typescript-eslint/parser": "^5.13.0",
75
+ "@types/lodash": "^4.14.182",
76
+ "@typescript-eslint/eslint-plugin": "^5.21.0",
77
+ "@typescript-eslint/parser": "^5.21.0",
74
78
  "csv-writer": "^1.6.0",
75
- "eslint": "^8.8.0",
76
- "eslint-config-prettier": "^8.3.0",
79
+ "eslint": "^8.14.0",
80
+ "eslint-config-prettier": "^8.5.0",
77
81
  "eslint-plugin-prettier": "^4.0.0",
78
- "husky": "^3.0.9",
79
- "jest": "^27.4.7",
80
- "mocha": "^9.2.1",
82
+ "husky": "^3.1.0",
83
+ "jest": "^27.5.1",
84
+ "jest-junit": "^13.2.0",
85
+ "mocha": "^9.2.2",
81
86
  "npm-license-crawler": "^0.2.1",
82
87
  "nyc": "^15.1.0",
83
- "pkg": "^5.5.2",
88
+ "pkg": "^5.6.0",
84
89
  "prettier": "^1.19.1",
85
90
  "tmp": "^0.2.1",
86
- "ts-jest": "^27.1.3",
91
+ "ts-jest": "^27.1.4",
87
92
  "ts-node": "^10.7.0",
88
- "typescript": "^4.6.2",
93
+ "typescript": "^4.6.3",
89
94
  "uuid": "^8.3.2"
90
95
  },
91
96
  "resolutions": {