@contrast/contrast 1.0.8 → 1.0.11

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 (217) hide show
  1. package/README.md +2 -2
  2. package/dist/audit/languageAnalysisEngine/getProjectRootFilenames.js +16 -25
  3. package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +103 -57
  4. package/dist/audit/languageAnalysisEngine/report/models/reportGuidanceModel.js +6 -0
  5. package/dist/audit/languageAnalysisEngine/report/models/reportOutputModel.js +3 -3
  6. package/dist/audit/languageAnalysisEngine/report/models/severityCountModel.js +1 -0
  7. package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +68 -17
  8. package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +39 -7
  9. package/dist/audit/languageAnalysisEngine/sendSnapshot.js +6 -30
  10. package/dist/audit/save.js +21 -13
  11. package/dist/commands/audit/auditConfig.js +3 -19
  12. package/dist/commands/audit/auditController.js +1 -10
  13. package/dist/commands/audit/help.js +7 -24
  14. package/dist/commands/audit/processAudit.js +5 -9
  15. package/dist/commands/audit/saveFile.js +2 -2
  16. package/dist/commands/auth/auth.js +1 -1
  17. package/dist/commands/config/config.js +2 -2
  18. package/dist/commands/scan/processScan.js +11 -4
  19. package/dist/commands/scan/sca/scaAnalysis.js +37 -13
  20. package/dist/common/HTTPClient.js +17 -8
  21. package/dist/common/errorHandling.js +2 -2
  22. package/dist/common/fail.js +66 -0
  23. package/dist/common/versionChecker.js +1 -1
  24. package/dist/constants/constants.js +7 -2
  25. package/dist/constants/locales.js +40 -38
  26. package/dist/constants.js +62 -12
  27. package/dist/index.js +57 -45
  28. package/dist/lambda/lambda.js +5 -2
  29. package/dist/sbom/generateSbom.js +2 -2
  30. package/dist/scaAnalysis/common/formatMessage.js +7 -1
  31. package/dist/scaAnalysis/common/scaParserForGoAndJava.js +32 -0
  32. package/dist/scaAnalysis/common/treeUpload.js +24 -10
  33. package/dist/scaAnalysis/dotnet/analysis.js +55 -0
  34. package/dist/scaAnalysis/dotnet/index.js +10 -0
  35. package/dist/scaAnalysis/go/goAnalysis.js +8 -2
  36. package/dist/scaAnalysis/java/analysis.js +10 -6
  37. package/dist/scaAnalysis/java/index.js +7 -1
  38. package/dist/scaAnalysis/java/javaBuildDepsParser.js +19 -3
  39. package/dist/scaAnalysis/javascript/analysis.js +4 -7
  40. package/dist/scaAnalysis/javascript/index.js +16 -4
  41. package/dist/scaAnalysis/php/analysis.js +14 -33
  42. package/dist/scaAnalysis/php/index.js +11 -4
  43. package/dist/scaAnalysis/python/analysis.js +43 -5
  44. package/dist/scaAnalysis/python/index.js +7 -2
  45. package/dist/scaAnalysis/ruby/analysis.js +16 -14
  46. package/dist/scan/autoDetection.js +13 -24
  47. package/dist/scan/fileUtils.js +31 -12
  48. package/dist/scan/formatScanOutput.js +9 -8
  49. package/dist/scan/populateProjectIdAndProjectName.js +5 -0
  50. package/dist/scan/scan.js +4 -0
  51. package/dist/scan/scanConfig.js +5 -5
  52. package/dist/scan/scanResults.js +39 -3
  53. package/dist/telemetry/telemetry.js +137 -0
  54. package/dist/utils/commonApi.js +1 -1
  55. package/dist/utils/getConfig.js +3 -8
  56. package/dist/utils/parsedCLIOptions.js +3 -1
  57. package/dist/utils/requestUtils.js +7 -1
  58. package/package.json +2 -3
  59. package/src/audit/languageAnalysisEngine/getProjectRootFilenames.js +21 -57
  60. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +155 -77
  61. package/src/audit/languageAnalysisEngine/report/models/reportGuidanceModel.ts +5 -0
  62. package/src/audit/languageAnalysisEngine/report/models/reportOutputModel.ts +5 -5
  63. package/src/audit/languageAnalysisEngine/report/models/severityCountModel.ts +2 -0
  64. package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +56 -27
  65. package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +45 -6
  66. package/src/audit/languageAnalysisEngine/sendSnapshot.js +6 -32
  67. package/src/audit/save.js +32 -16
  68. package/src/commands/audit/auditConfig.ts +10 -28
  69. package/src/commands/audit/auditController.ts +0 -11
  70. package/src/commands/audit/help.ts +7 -24
  71. package/src/commands/audit/processAudit.ts +16 -8
  72. package/src/commands/audit/saveFile.ts +2 -2
  73. package/src/commands/auth/auth.js +3 -1
  74. package/src/commands/config/config.js +4 -2
  75. package/src/commands/scan/processScan.js +18 -5
  76. package/src/commands/scan/sca/scaAnalysis.js +50 -18
  77. package/src/common/HTTPClient.js +23 -9
  78. package/src/common/errorHandling.ts +2 -3
  79. package/src/common/fail.js +75 -0
  80. package/src/common/versionChecker.ts +1 -1
  81. package/src/constants/constants.js +9 -3
  82. package/src/constants/locales.js +70 -45
  83. package/src/constants.js +67 -13
  84. package/src/index.ts +91 -66
  85. package/src/lambda/lambda.ts +5 -2
  86. package/src/lambda/types.ts +1 -0
  87. package/src/sbom/generateSbom.ts +2 -2
  88. package/src/scaAnalysis/common/formatMessage.js +8 -1
  89. package/src/scaAnalysis/common/scaParserForGoAndJava.js +41 -0
  90. package/src/scaAnalysis/common/treeUpload.js +25 -11
  91. package/src/scaAnalysis/dotnet/analysis.js +72 -0
  92. package/src/scaAnalysis/dotnet/index.js +11 -0
  93. package/src/scaAnalysis/go/goAnalysis.js +9 -2
  94. package/src/scaAnalysis/java/analysis.js +11 -6
  95. package/src/scaAnalysis/java/index.js +9 -1
  96. package/src/scaAnalysis/java/javaBuildDepsParser.js +25 -6
  97. package/src/scaAnalysis/javascript/analysis.js +6 -7
  98. package/src/scaAnalysis/javascript/index.js +25 -6
  99. package/src/scaAnalysis/php/analysis.js +15 -35
  100. package/src/scaAnalysis/php/index.js +15 -4
  101. package/src/scaAnalysis/python/analysis.js +49 -5
  102. package/src/scaAnalysis/python/index.js +7 -2
  103. package/src/scaAnalysis/ruby/analysis.js +18 -15
  104. package/src/scan/autoDetection.js +14 -27
  105. package/src/scan/fileUtils.js +33 -12
  106. package/src/scan/formatScanOutput.ts +10 -8
  107. package/src/scan/populateProjectIdAndProjectName.js +5 -1
  108. package/src/scan/scan.ts +4 -0
  109. package/src/scan/scanConfig.js +7 -7
  110. package/src/scan/scanResults.js +46 -3
  111. package/src/telemetry/telemetry.ts +154 -0
  112. package/src/utils/commonApi.js +1 -1
  113. package/src/utils/getConfig.ts +5 -18
  114. package/src/utils/parsedCLIOptions.js +14 -1
  115. package/src/utils/requestUtils.js +8 -1
  116. package/dist/audit/AnalysisEngine.js +0 -37
  117. package/dist/audit/autodetection/autoDetectLanguage.js +0 -32
  118. package/dist/audit/dotnetAnalysisEngine/index.js +0 -25
  119. package/dist/audit/dotnetAnalysisEngine/parseLockFileContents.js +0 -35
  120. package/dist/audit/dotnetAnalysisEngine/parseProjectFileContents.js +0 -15
  121. package/dist/audit/dotnetAnalysisEngine/readLockFileContents.js +0 -18
  122. package/dist/audit/dotnetAnalysisEngine/readProjectFileContents.js +0 -14
  123. package/dist/audit/dotnetAnalysisEngine/sanitizer.js +0 -9
  124. package/dist/audit/goAnalysisEngine/index.js +0 -17
  125. package/dist/audit/goAnalysisEngine/parseProjectFileContents.js +0 -164
  126. package/dist/audit/goAnalysisEngine/readProjectFileContents.js +0 -21
  127. package/dist/audit/goAnalysisEngine/sanitizer.js +0 -5
  128. package/dist/audit/javaAnalysisEngine/index.js +0 -34
  129. package/dist/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +0 -155
  130. package/dist/audit/javaAnalysisEngine/parseProjectFileContents.js +0 -353
  131. package/dist/audit/javaAnalysisEngine/readProjectFileContents.js +0 -98
  132. package/dist/audit/javaAnalysisEngine/sanitizer.js +0 -5
  133. package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +0 -25
  134. package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +0 -25
  135. package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasLockFile.js +0 -35
  136. package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +0 -24
  137. package/dist/audit/languageAnalysisEngine/constants.js +0 -20
  138. package/dist/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +0 -25
  139. package/dist/audit/languageAnalysisEngine/index.js +0 -39
  140. package/dist/audit/languageAnalysisEngine/languageAnalysisFactory.js +0 -66
  141. package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +0 -166
  142. package/dist/audit/nodeAnalysisEngine/handleNPMLockFileV2.js +0 -40
  143. package/dist/audit/nodeAnalysisEngine/index.js +0 -31
  144. package/dist/audit/nodeAnalysisEngine/parseNPMLockFileContents.js +0 -18
  145. package/dist/audit/nodeAnalysisEngine/parseYarnLockFileContents.js +0 -18
  146. package/dist/audit/nodeAnalysisEngine/readNPMLockFileContents.js +0 -17
  147. package/dist/audit/nodeAnalysisEngine/readProjectFileContents.js +0 -14
  148. package/dist/audit/nodeAnalysisEngine/readYarnLockFileContents.js +0 -24
  149. package/dist/audit/nodeAnalysisEngine/sanitizer.js +0 -9
  150. package/dist/audit/phpAnalysisEngine/index.js +0 -23
  151. package/dist/audit/phpAnalysisEngine/parseLockFileContents.js +0 -52
  152. package/dist/audit/phpAnalysisEngine/readLockFileContents.js +0 -13
  153. package/dist/audit/phpAnalysisEngine/readProjectFileContents.js +0 -16
  154. package/dist/audit/phpAnalysisEngine/sanitizer.js +0 -5
  155. package/dist/audit/pythonAnalysisEngine/index.js +0 -25
  156. package/dist/audit/pythonAnalysisEngine/parsePipfileLockContents.js +0 -17
  157. package/dist/audit/pythonAnalysisEngine/parseProjectFileContents.js +0 -21
  158. package/dist/audit/pythonAnalysisEngine/readPipfileLockFileContents.js +0 -13
  159. package/dist/audit/pythonAnalysisEngine/readPythonProjectFileContents.js +0 -14
  160. package/dist/audit/pythonAnalysisEngine/sanitizer.js +0 -7
  161. package/dist/audit/rubyAnalysisEngine/index.js +0 -25
  162. package/dist/audit/rubyAnalysisEngine/parseGemfileLockContents.js +0 -176
  163. package/dist/audit/rubyAnalysisEngine/parsedGemfile.js +0 -22
  164. package/dist/audit/rubyAnalysisEngine/readGemfileContents.js +0 -14
  165. package/dist/audit/rubyAnalysisEngine/readGemfileLockContents.js +0 -14
  166. package/dist/audit/rubyAnalysisEngine/sanitizer.js +0 -6
  167. package/src/audit/AnalysisEngine.js +0 -103
  168. package/src/audit/autodetection/autoDetectLanguage.ts +0 -40
  169. package/src/audit/dotnetAnalysisEngine/index.js +0 -26
  170. package/src/audit/dotnetAnalysisEngine/parseLockFileContents.js +0 -47
  171. package/src/audit/dotnetAnalysisEngine/parseProjectFileContents.js +0 -29
  172. package/src/audit/dotnetAnalysisEngine/readLockFileContents.js +0 -30
  173. package/src/audit/dotnetAnalysisEngine/readProjectFileContents.js +0 -26
  174. package/src/audit/dotnetAnalysisEngine/sanitizer.js +0 -11
  175. package/src/audit/goAnalysisEngine/index.js +0 -18
  176. package/src/audit/goAnalysisEngine/parseProjectFileContents.js +0 -209
  177. package/src/audit/goAnalysisEngine/readProjectFileContents.js +0 -31
  178. package/src/audit/goAnalysisEngine/sanitizer.js +0 -7
  179. package/src/audit/javaAnalysisEngine/index.js +0 -41
  180. package/src/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +0 -225
  181. package/src/audit/javaAnalysisEngine/parseProjectFileContents.js +0 -420
  182. package/src/audit/javaAnalysisEngine/readProjectFileContents.js +0 -141
  183. package/src/audit/javaAnalysisEngine/sanitizer.js +0 -6
  184. package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +0 -36
  185. package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +0 -42
  186. package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasLockFile.js +0 -54
  187. package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +0 -33
  188. package/src/audit/languageAnalysisEngine/constants.js +0 -23
  189. package/src/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +0 -41
  190. package/src/audit/languageAnalysisEngine/index.js +0 -45
  191. package/src/audit/languageAnalysisEngine/languageAnalysisFactory.js +0 -96
  192. package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +0 -251
  193. package/src/audit/nodeAnalysisEngine/handleNPMLockFileV2.js +0 -49
  194. package/src/audit/nodeAnalysisEngine/index.js +0 -35
  195. package/src/audit/nodeAnalysisEngine/parseNPMLockFileContents.js +0 -20
  196. package/src/audit/nodeAnalysisEngine/parseYarnLockFileContents.js +0 -26
  197. package/src/audit/nodeAnalysisEngine/readNPMLockFileContents.js +0 -23
  198. package/src/audit/nodeAnalysisEngine/readProjectFileContents.js +0 -27
  199. package/src/audit/nodeAnalysisEngine/readYarnLockFileContents.js +0 -36
  200. package/src/audit/nodeAnalysisEngine/sanitizer.js +0 -11
  201. package/src/audit/phpAnalysisEngine/index.js +0 -27
  202. package/src/audit/phpAnalysisEngine/parseLockFileContents.js +0 -60
  203. package/src/audit/phpAnalysisEngine/readLockFileContents.js +0 -14
  204. package/src/audit/phpAnalysisEngine/readProjectFileContents.js +0 -25
  205. package/src/audit/phpAnalysisEngine/sanitizer.js +0 -4
  206. package/src/audit/pythonAnalysisEngine/index.js +0 -55
  207. package/src/audit/pythonAnalysisEngine/parsePipfileLockContents.js +0 -23
  208. package/src/audit/pythonAnalysisEngine/parseProjectFileContents.js +0 -33
  209. package/src/audit/pythonAnalysisEngine/readPipfileLockFileContents.js +0 -16
  210. package/src/audit/pythonAnalysisEngine/readPythonProjectFileContents.js +0 -22
  211. package/src/audit/pythonAnalysisEngine/sanitizer.js +0 -9
  212. package/src/audit/rubyAnalysisEngine/index.js +0 -30
  213. package/src/audit/rubyAnalysisEngine/parseGemfileLockContents.js +0 -215
  214. package/src/audit/rubyAnalysisEngine/parsedGemfile.js +0 -39
  215. package/src/audit/rubyAnalysisEngine/readGemfileContents.js +0 -18
  216. package/src/audit/rubyAnalysisEngine/readGemfileLockContents.js +0 -17
  217. package/src/audit/rubyAnalysisEngine/sanitizer.js +0 -8
@@ -10,72 +10,90 @@ const findFile = async () => {
10
10
  onlyFiles: true
11
11
  });
12
12
  };
13
- const findFilesJava = async (languagesFound) => {
13
+ const findFilesJava = async (languagesFound, filePath) => {
14
14
  const result = await fg(['**/pom.xml', '**/build.gradle', '**/build.gradle.kts'], {
15
15
  dot: false,
16
16
  deep: 1,
17
- onlyFiles: true
17
+ onlyFiles: true,
18
+ cwd: filePath ? filePath : process.cwd()
18
19
  });
19
20
  if (result.length > 0) {
20
21
  return languagesFound.push({ JAVA: result });
21
22
  }
22
23
  return languagesFound;
23
24
  };
24
- const findFilesJavascript = async (languagesFound) => {
25
+ const findFilesJavascript = async (languagesFound, filePath) => {
25
26
  const result = await fg(['**/package.json', '**/yarn.lock', '**/package-lock.json'], {
26
27
  dot: false,
27
28
  deep: 1,
28
- onlyFiles: true
29
+ onlyFiles: true,
30
+ cwd: filePath ? filePath : process.cwd()
29
31
  });
30
32
  if (result.length > 0) {
31
33
  return languagesFound.push({ JAVASCRIPT: result });
32
34
  }
33
35
  return languagesFound;
34
36
  };
35
- const findFilesPython = async (languagesFound) => {
37
+ const findFilesPython = async (languagesFound, filePath) => {
36
38
  const result = await fg(['**/Pipfile.lock', '**/Pipfile'], {
37
39
  dot: false,
38
40
  deep: 3,
39
- onlyFiles: true
41
+ onlyFiles: true,
42
+ cwd: filePath ? filePath : process.cwd()
40
43
  });
41
44
  if (result.length > 0) {
42
45
  return languagesFound.push({ PYTHON: result });
43
46
  }
44
47
  return languagesFound;
45
48
  };
46
- const findFilesGo = async (languagesFound) => {
49
+ const findFilesGo = async (languagesFound, filePath) => {
47
50
  const result = await fg(['**/go.mod'], {
48
51
  dot: false,
49
52
  deep: 3,
50
- onlyFiles: true
53
+ onlyFiles: true,
54
+ cwd: filePath ? filePath : process.cwd()
51
55
  });
52
56
  if (result.length > 0) {
53
57
  return languagesFound.push({ GO: result });
54
58
  }
55
59
  return languagesFound;
56
60
  };
57
- const findFilesRuby = async (languagesFound) => {
61
+ const findFilesRuby = async (languagesFound, filePath) => {
58
62
  const result = await fg(['**/Gemfile', '**/Gemfile.lock'], {
59
63
  dot: false,
60
64
  deep: 3,
61
- onlyFiles: true
65
+ onlyFiles: true,
66
+ cwd: filePath ? filePath : process.cwd()
62
67
  });
63
68
  if (result.length > 0) {
64
69
  return languagesFound.push({ RUBY: result });
65
70
  }
66
71
  return languagesFound;
67
72
  };
68
- const findFilesPhp = async (languagesFound) => {
73
+ const findFilesPhp = async (languagesFound, filePath) => {
69
74
  const result = await fg(['**/composer.json', '**/composer.lock'], {
70
75
  dot: false,
71
76
  deep: 3,
72
- onlyFiles: true
77
+ onlyFiles: true,
78
+ cwd: filePath ? filePath : process.cwd()
73
79
  });
74
80
  if (result.length > 0) {
75
81
  return languagesFound.push({ PHP: result });
76
82
  }
77
83
  return languagesFound;
78
84
  };
85
+ const findFilesDotNet = async (languagesFound, filePath) => {
86
+ const result = await fg(['**/*.csproj', '**/packages.lock.json'], {
87
+ dot: false,
88
+ deep: 3,
89
+ onlyFiles: true,
90
+ cwd: filePath ? filePath : process.cwd()
91
+ });
92
+ if (result.length > 0) {
93
+ return languagesFound.push({ DOTNET: result });
94
+ }
95
+ return languagesFound;
96
+ };
79
97
  const checkFilePermissions = file => {
80
98
  let readableFile = false;
81
99
  try {
@@ -117,5 +135,6 @@ module.exports = {
117
135
  findFilesGo,
118
136
  findFilesPhp,
119
137
  findFilesRuby,
138
+ findFilesDotNet,
120
139
  fileIsEmpty
121
140
  };
@@ -25,8 +25,9 @@ function formatScanOutput(scanResults) {
25
25
  console.log(chalk_1.default.bold(message));
26
26
  console.log();
27
27
  let defaultView = getDefaultView(scanResultsInstances.content);
28
- let count = defaultView.length;
28
+ let count = 0;
29
29
  defaultView.forEach(entry => {
30
+ count++;
30
31
  let table = new cli_table3_1.default({
31
32
  chars: {
32
33
  top: '',
@@ -52,12 +53,12 @@ function formatScanOutput(scanResults) {
52
53
  });
53
54
  let learnRow = [];
54
55
  let adviceRow = [];
56
+ const headerColour = chalk_1.default.hex(entry.colour);
55
57
  const headerRow = [
56
- chalk_1.default
57
- .hex(entry.colour)
58
- .bold(`CONTRAST-${count.toString().padStart(3, '0')}`),
59
- chalk_1.default.hex(entry.colour).bold('-'),
60
- chalk_1.default.hex(entry.colour).bold(`[${entry.severity}] ${entry.ruleId}`) +
58
+ headerColour(`CONTRAST-${count.toString().padStart(3, '0')}`),
59
+ headerColour(`-`),
60
+ headerColour(`[${entry.severity}] `) +
61
+ headerColour.bold(`${entry.ruleId}`) +
61
62
  entry.message
62
63
  ];
63
64
  const codePath = entry.codePath?.replace(/^@/, '');
@@ -84,12 +85,12 @@ function formatScanOutput(scanResults) {
84
85
  ];
85
86
  table.push(learnRow);
86
87
  }
87
- count--;
88
88
  console.log(table.toString());
89
89
  console.log();
90
90
  });
91
91
  }
92
92
  printVulnInfo(projectOverview);
93
+ return projectOverview;
93
94
  }
94
95
  exports.formatScanOutput = formatScanOutput;
95
96
  function printVulnInfo(projectOverview) {
@@ -149,7 +150,7 @@ function getDefaultView(content) {
149
150
  groupTypeResults.push(groupResultsObj);
150
151
  assignBySeverity(resultEntry, groupResultsObj);
151
152
  });
152
- return (0, lodash_1.sortBy)(groupTypeResults, ['priority']).reverse();
153
+ return (0, lodash_1.sortBy)(groupTypeResults, ['priority']);
153
154
  }
154
155
  exports.getDefaultView = getDefaultView;
155
156
  function editVulName(message) {
@@ -25,6 +25,11 @@ const createProjectId = async (config, client) => {
25
25
  process.exit(1);
26
26
  return;
27
27
  }
28
+ if (res.statusCode === 429) {
29
+ console.log(i18n.__('exceededFreeTier'));
30
+ process.exit(1);
31
+ return;
32
+ }
28
33
  if (res.statusCode === 201) {
29
34
  console.log(i18n.__('projectCreatedScan'));
30
35
  if (config.verbose) {
package/dist/scan/scan.js CHANGED
@@ -45,6 +45,10 @@ const sendScan = async (config) => {
45
45
  oraWrapper_1.default.failSpinner(startUploadSpinner, i18n_1.default.__('uploadingScanFail'));
46
46
  console.log(i18n_1.default.__('genericServiceError', res.statusCode));
47
47
  }
48
+ if (res.statusCode === 429) {
49
+ console.log(i18n_1.default.__('exceededFreeTier'));
50
+ process.exit(1);
51
+ }
48
52
  if (res.statusCode === 403) {
49
53
  console.log(i18n_1.default.__('permissionsError'));
50
54
  process.exit(1);
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
  const paramHandler = require('../utils/paramsUtil/paramHandler');
3
3
  const constants = require('../../src/constants.js');
4
- const parsedCLIOptions = require('../../src/utils/parsedCLIOptions');
5
4
  const path = require('path');
6
- const { supportedLanguages } = require('../audit/languageAnalysisEngine/constants');
5
+ const { supportedLanguagesScan } = require('../constants/constants');
7
6
  const i18n = require('i18n');
8
7
  const { scanUsageGuide } = require('./help');
9
- const getScanConfig = argv => {
10
- let scanParams = parsedCLIOptions.getCommandLineArgsCustom(argv, constants.commandLineDefinitions.scanOptionDefinitions);
8
+ const parsedCLIOptions = require('../utils/parsedCLIOptions');
9
+ const getScanConfig = async (contrastConf, command, argv) => {
10
+ let scanParams = await parsedCLIOptions.getCommandLineArgsCustom(contrastConf, command, argv, constants.commandLineDefinitions.scanOptionDefinitions);
11
11
  if (scanParams.help) {
12
12
  printHelpMessage();
13
13
  process.exit(0);
@@ -15,7 +15,7 @@ const getScanConfig = argv => {
15
15
  const paramsAuth = paramHandler.getAuth(scanParams);
16
16
  if (scanParams.language) {
17
17
  scanParams.language = scanParams.language.toUpperCase();
18
- if (!Object.values(supportedLanguages).includes(scanParams.language)) {
18
+ if (!Object.values(supportedLanguagesScan).includes(scanParams.language)) {
19
19
  console.log(`Did not recognise --language ${scanParams.language}`);
20
20
  console.log(i18n.__('constantsHowToRunDev3'));
21
21
  process.exit(1);
@@ -5,10 +5,14 @@ const oraFunctions = require('../utils/oraWrapper');
5
5
  const _ = require('lodash');
6
6
  const i18n = require('i18n');
7
7
  const oraWrapper = require('../utils/oraWrapper');
8
+ const readLine = require('readline');
8
9
  const getScanId = async (config, codeArtifactId, client) => {
9
10
  return client
10
11
  .getScanId(config, codeArtifactId)
11
12
  .then(res => {
13
+ if (res.statusCode == 429) {
14
+ throw new Error(i18n.__('exceededFreeTier'));
15
+ }
12
16
  return res.body.id;
13
17
  })
14
18
  .catch(err => {
@@ -61,12 +65,43 @@ const returnScanResults = async (config, codeArtifactId, newProject, timeout, st
61
65
  let endTime = new Date() - startTime;
62
66
  if (requestUtils.millisToSeconds(endTime) > timeout) {
63
67
  oraFunctions.failSpinner(startScanSpinner, 'Contrast Scan timed out at the specified ' + timeout + ' seconds.');
64
- console.log('Please try again, allowing more time.');
65
- process.exit(1);
68
+ if (!config.isCI) {
69
+ const retry = await retryScanPrompt();
70
+ timeout = retry.timeout;
71
+ }
66
72
  }
67
73
  }
68
74
  }
69
75
  };
76
+ const retryScanPrompt = async () => {
77
+ const rl = readLine.createInterface({
78
+ input: process.stdin,
79
+ output: process.stdout
80
+ });
81
+ return new Promise((resolve, reject) => {
82
+ requestUtils.timeOutError(30000, reject);
83
+ rl.question('🔁 Do you want to continue waiting on Scan? [Y/N]\n', async (input) => {
84
+ if (input.toLowerCase() === 'yes' || input.toLowerCase() === 'y') {
85
+ console.log('Continuing wait for Scan');
86
+ rl.close();
87
+ resolve({ timeout: 300 });
88
+ }
89
+ else if (input.toLowerCase() === 'no' ||
90
+ input.toLowerCase() === 'n') {
91
+ rl.close();
92
+ console.log('Contrast Scan Retry Cancelled: Exiting');
93
+ resolve(process.exit(1));
94
+ }
95
+ else {
96
+ rl.close();
97
+ console.log('Invalid Input: Exiting');
98
+ resolve(process.exit(1));
99
+ }
100
+ });
101
+ }).catch(e => {
102
+ throw e;
103
+ });
104
+ };
70
105
  const returnScanResultsInstances = async (config, scanId) => {
71
106
  const client = commonApi.getHttpClient(config);
72
107
  let result;
@@ -89,5 +124,6 @@ module.exports = {
89
124
  getScanId: getScanId,
90
125
  returnScanResults: returnScanResults,
91
126
  pollScanResults: pollScanResults,
92
- returnScanResultsInstances: returnScanResultsInstances
127
+ returnScanResultsInstances: returnScanResultsInstances,
128
+ retryScanPrompt
93
129
  };
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.sha1Base64Value = exports.findParamValueFromArgs = exports.paramExists = exports.obfuscateParams = exports.sendTelemetryRequest = exports.sendTelemetryConfigAsObject = exports.sendTelemetryConfigAsConfObj = exports.TELEMETRY_CLI_TIME_TO_AUTH_EVENT = exports.TELEMETRY_CLI_COMMANDS_EVENT = void 0;
27
+ const commonApi_1 = require("../utils/commonApi");
28
+ const crypto = __importStar(require("crypto"));
29
+ exports.TELEMETRY_CLI_COMMANDS_EVENT = 'CLI_COMMANDS';
30
+ exports.TELEMETRY_CLI_TIME_TO_AUTH_EVENT = 'CLI_TIME_TO_AUTH';
31
+ const sendTelemetryConfigAsConfObj = async (config, command, argv, result, language) => {
32
+ const hostParam = '--host';
33
+ const hostParamAlias = '-h';
34
+ const orgIdParam = '--organization-id';
35
+ const orgIdParamAlias = '-o';
36
+ const authParam = '--authorization';
37
+ const apiKeyParam = '--api-key';
38
+ let configToUse;
39
+ if ((0, exports.paramExists)(argv, hostParam, hostParamAlias) &&
40
+ (0, exports.paramExists)(argv, orgIdParam, orgIdParamAlias) &&
41
+ (0, exports.paramExists)(argv, authParam, null) &&
42
+ (0, exports.paramExists)(argv, apiKeyParam, null)) {
43
+ configToUse = {
44
+ host: (0, exports.findParamValueFromArgs)(argv, hostParam, hostParamAlias),
45
+ organizationId: (0, exports.findParamValueFromArgs)(argv, orgIdParam, orgIdParamAlias),
46
+ authorization: (0, exports.findParamValueFromArgs)(argv, authParam, null),
47
+ apiKey: (0, exports.findParamValueFromArgs)(argv, apiKeyParam, null)
48
+ };
49
+ }
50
+ else if (config &&
51
+ config.get('host') &&
52
+ config.get('organizationId') &&
53
+ config.get('authorization') &&
54
+ config.get('apiKey')) {
55
+ configToUse = {
56
+ host: config.get('host')?.slice(0, -1),
57
+ organizationId: config.get('organizationId'),
58
+ authorization: config.get('authorization'),
59
+ apiKey: config.get('apiKey')
60
+ };
61
+ }
62
+ else {
63
+ return;
64
+ }
65
+ return await (0, exports.sendTelemetryConfigAsObject)(configToUse, command, argv, result, language);
66
+ };
67
+ exports.sendTelemetryConfigAsConfObj = sendTelemetryConfigAsConfObj;
68
+ const sendTelemetryConfigAsObject = async (config, command, argv, result, language) => {
69
+ const obfuscatedParams = (0, exports.obfuscateParams)(argv);
70
+ const requestBody = {
71
+ event: exports.TELEMETRY_CLI_COMMANDS_EVENT,
72
+ details: {
73
+ ip_address: '',
74
+ account_name: '',
75
+ account_host: '',
76
+ company_domain: '',
77
+ command: `contrast ${command} ${obfuscatedParams}`,
78
+ app_id: config && config.applicationId
79
+ ? (0, exports.sha1Base64Value)(config.applicationId)
80
+ : 'undefined',
81
+ project_id: config && config.projectId
82
+ ? (0, exports.sha1Base64Value)(config.projectId)
83
+ : 'undefined',
84
+ language: language,
85
+ result: result,
86
+ additional_info: '',
87
+ timestamp: new Date().toUTCString()
88
+ }
89
+ };
90
+ return await (0, exports.sendTelemetryRequest)(config, requestBody);
91
+ };
92
+ exports.sendTelemetryConfigAsObject = sendTelemetryConfigAsObject;
93
+ const sendTelemetryRequest = async (config, requestBody) => {
94
+ const client = (0, commonApi_1.getHttpClient)(config);
95
+ return client
96
+ .postTelemetry(config, requestBody)
97
+ .then((res) => {
98
+ if (res.statusCode !== 200 && config.debug === true) {
99
+ console.log('Telemetry failed to send with status', res.statusCode);
100
+ }
101
+ return { statusCode: res.statusCode, statusMessage: res.statusMessage };
102
+ })
103
+ .catch((err) => {
104
+ return;
105
+ });
106
+ };
107
+ exports.sendTelemetryRequest = sendTelemetryRequest;
108
+ const obfuscateParams = (argv) => {
109
+ return argv
110
+ .join(' ')
111
+ .replace(/--(authorization [A-Z0-9]+)/gi, '--authorization *****')
112
+ .replace(/-(o [A-Z0-9-]+)/gi, '-o *****')
113
+ .replace(/--(organization-id [A-Z0-9-]+)/gi, '--organization-id *****')
114
+ .replace(/--(api-key [A-Z0-9]+)/gi, '--api-key *****');
115
+ };
116
+ exports.obfuscateParams = obfuscateParams;
117
+ const paramExists = (argv, param, paramAlias) => {
118
+ return argv.find((arg) => arg === param || arg === paramAlias);
119
+ };
120
+ exports.paramExists = paramExists;
121
+ const findParamValueFromArgs = (argv, param, paramAlias) => {
122
+ let paramAsValue;
123
+ argv.forEach((arg, index) => {
124
+ if (arg === param ||
125
+ (arg === paramAlias &&
126
+ argv[index + 1] !== undefined &&
127
+ argv[index + 1] !== null)) {
128
+ paramAsValue = argv[index + 1];
129
+ }
130
+ });
131
+ return paramAsValue;
132
+ };
133
+ exports.findParamValueFromArgs = findParamValueFromArgs;
134
+ const sha1Base64Value = (value) => {
135
+ return crypto.createHash('sha1').update(value).digest('base64');
136
+ };
137
+ exports.sha1Base64Value = sha1Base64Value;
@@ -18,7 +18,7 @@ const handleResponseErrors = (res, api) => {
18
18
  maxAppError();
19
19
  }
20
20
  else {
21
- genericError();
21
+ genericError(res);
22
22
  }
23
23
  };
24
24
  const getProtocol = host => {
@@ -3,15 +3,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.setConfigValues = exports.createConfigFromYaml = exports.localConfig = void 0;
6
+ exports.setConfigValues = exports.localConfig = void 0;
7
7
  const conf_1 = __importDefault(require("conf"));
8
8
  const localConfig = (name, version) => {
9
9
  const config = new conf_1.default({
10
10
  configName: name
11
11
  });
12
12
  config.set('version', version);
13
- if (process.env.CONTRAST_CODSEC_DISABLE_UPDATE_MESSAGE) {
14
- config.set('updateMessageHidden', JSON.parse(process.env.CONTRAST_CODSEC_DISABLE_UPDATE_MESSAGE.toLowerCase()));
13
+ if (process.env.CONTRAST_CODSEC_CI) {
14
+ config.set('isCI', JSON.parse(process.env.CONTRAST_CODSEC_CI.toLowerCase()));
15
15
  }
16
16
  if (!config.has('host')) {
17
17
  config.set('host', 'https://ce.contrastsecurity.com/');
@@ -19,11 +19,6 @@ const localConfig = (name, version) => {
19
19
  return config;
20
20
  };
21
21
  exports.localConfig = localConfig;
22
- const createConfigFromYaml = (yamlPath) => {
23
- const yamlConfig = {};
24
- return yamlConfig;
25
- };
26
- exports.createConfigFromYaml = createConfigFromYaml;
27
22
  const setConfigValues = (config, values) => {
28
23
  config.set('apiKey', values.apiKey);
29
24
  config.set('organizationId', values.orgId);
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  const commandLineArgs = require('command-line-args');
3
- const getCommandLineArgsCustom = (parameterList, optionDefinitions) => {
3
+ const { sendTelemetryConfigAsConfObj } = require('../telemetry/telemetry');
4
+ const getCommandLineArgsCustom = async (contrastConf, command, parameterList, optionDefinitions) => {
4
5
  try {
5
6
  return commandLineArgs(optionDefinitions, {
6
7
  argv: parameterList,
@@ -10,6 +11,7 @@ const getCommandLineArgsCustom = (parameterList, optionDefinitions) => {
10
11
  });
11
12
  }
12
13
  catch (e) {
14
+ await sendTelemetryConfigAsConfObj(contrastConf, command, parameterList, 'FAILURE', 'undefined');
13
15
  console.log(e.message.toString());
14
16
  process.exit(1);
15
17
  }
@@ -11,8 +11,14 @@ const millisToSeconds = millis => {
11
11
  const sleep = ms => {
12
12
  return new Promise(resolve => setTimeout(resolve, ms));
13
13
  };
14
+ const timeOutError = (ms, reject) => {
15
+ return setTimeout(() => {
16
+ reject(new Error(`No input detected after 30s`));
17
+ }, ms);
18
+ };
14
19
  module.exports = {
15
20
  sendRequest: sendRequest,
16
21
  sleep: sleep,
17
- millisToSeconds: millisToSeconds
22
+ millisToSeconds: millisToSeconds,
23
+ timeOutError: timeOutError
18
24
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrast/contrast",
3
- "version": "1.0.8",
3
+ "version": "1.0.11",
4
4
  "description": "Contrast Security's command line tool",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -23,8 +23,7 @@
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/audit.spec.js",
27
- "test-int-audit-experimental": "jest ./test-integration/audit/audit-experimental.spec.js",
26
+ "test-int-audit": "jest test-integration/audit/audit-int.spec.js",
28
27
  "format": "prettier --write \"**/*.{ts,tsx,js,json,md,yml}\" .eslintrc.*",
29
28
  "check-format": "prettier --check \"**/*.{ts,tsx,js,json,md,yml}\" .eslintrc.*",
30
29
  "coverage-local": "nyc --reporter=text mocha './test/**/*.spec.js'",
@@ -1,72 +1,36 @@
1
1
  const fs = require('fs')
2
2
  const path = require('path')
3
3
  const i18n = require('i18n')
4
- /**
5
- * Will get the filenames from the project path provided to the SCA CLI tool. If
6
- * the project path points to a file and not a directory will return the
7
- * filename in the same fashion as if a directory had been read.
8
- *
9
- * Will fail and throw for a manner of reasons when doing file/directory
10
- * inspection.
11
- *
12
- * @param {string} file - The path to a projects root directory or a
13
- * specific project file
14
- *
15
- * @return {string[]} List of filenames associated with a projects root
16
- * directory or the name of the specific project file if that was provided to
17
- * the 'file' parameter
18
- *
19
- * @throws {Error} If the project path doesn't exist
20
- * @throws {Error} If the project path information can't be collected
21
- * @throws {Error} If a non-file or non-directory inspected
22
- */
23
- module.exports = exports = (analysis, next) => {
24
- const { file, languageAnalysis } = analysis
25
- try {
26
- languageAnalysis.projectRootFilenames = getProjectRootFilenames(file)
27
- } catch (err) {
28
- next(err)
29
- return
4
+
5
+ const getDirectoryFromPathGiven = file => {
6
+ let projectStats = getProjectStats(file)
7
+
8
+ if (projectStats.isFile()) {
9
+ let newPath = path.resolve(file)
10
+ return path.dirname(newPath)
11
+ }
12
+
13
+ if (projectStats.isDirectory()) {
14
+ return file
30
15
  }
31
- next()
32
16
  }
33
17
 
34
- const getProjectRootFilenames = file => {
35
- let projectStats = null
18
+ const getProjectStats = file => {
36
19
  try {
37
- projectStats = fs.statSync(file)
20
+ //might not need this
21
+ if (file.endsWith('/')) {
22
+ file = file.slice(0, -1)
23
+ }
24
+ return fs.statSync(file)
38
25
  } catch (err) {
39
26
  throw new Error(
40
27
  i18n.__('languageAnalysisProjectRootFileNameFailure', file) +
41
28
  `${err.message}`
42
29
  )
43
30
  }
44
-
45
- // Return the contents of a directory...
46
- if (projectStats.isDirectory()) {
47
- try {
48
- return fs.readdirSync(file)
49
- } catch (err) {
50
- throw new Error(
51
- i18n.__('languageAnalysisProjectRootFileNameReadError', file) +
52
- `${err.message}`
53
- )
54
- }
55
- }
56
-
57
- // If we are working with a file return it in a list as we do when we work
58
- // with a directory...
59
- if (projectStats.isFile()) {
60
- return [path.basename(file)]
61
- }
62
-
63
- // Error out if we are working with something like a socket file or some
64
- // other craziness...
65
- throw new Error(
66
- i18n.__('languageAnalysisProjectRootFileNameMissingError'),
67
- file
68
- )
69
31
  }
70
32
 
71
- //For testing purposes
72
- exports.getProjectRootFilenames = getProjectRootFilenames
33
+ module.exports = {
34
+ getProjectStats,
35
+ getDirectoryFromPathGiven: getDirectoryFromPathGiven
36
+ }