@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
@@ -4,14 +4,29 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.isCorrectNodeVersion = exports.findLatestCLIVersion = void 0;
7
- const latest_version_1 = __importDefault(require("latest-version"));
8
7
  const constants_1 = require("../constants/constants");
9
8
  const boxen_1 = __importDefault(require("boxen"));
10
9
  const chalk_1 = __importDefault(require("chalk"));
11
10
  const semver_1 = __importDefault(require("semver"));
12
- async function findLatestCLIVersion(updateMessageHidden) {
13
- if (!updateMessageHidden) {
14
- const latestCLIVersion = await (0, latest_version_1.default)('@contrast/contrast');
11
+ const commonApi_1 = __importDefault(require("../utils/commonApi"));
12
+ const http2_1 = require("http2");
13
+ const getLatestVersion = async (config) => {
14
+ const client = commonApi_1.default.getHttpClient(config);
15
+ try {
16
+ const res = await client.getLatestVersion();
17
+ if (res.statusCode === http2_1.constants.HTTP_STATUS_OK) {
18
+ return res.body;
19
+ }
20
+ }
21
+ catch (e) {
22
+ return;
23
+ }
24
+ };
25
+ async function findLatestCLIVersion(config) {
26
+ const messageHidden = config.get('updateMessageHidden');
27
+ if (!messageHidden) {
28
+ let latestCLIVersion = await getLatestVersion(config);
29
+ latestCLIVersion = latestCLIVersion.substring(8);
15
30
  if (semver_1.default.lt(constants_1.APP_VERSION, latestCLIVersion)) {
16
31
  const updateAvailableMessage = `Update available ${chalk_1.default.yellow(constants_1.APP_VERSION)} → ${chalk_1.default.green(latestCLIVersion)}`;
17
32
  const npmUpdateAvailableCommand = `Run ${chalk_1.default.cyan('npm i @contrast/contrast -g')} to update via npm`;
@@ -27,6 +42,6 @@ async function findLatestCLIVersion(updateMessageHidden) {
27
42
  }
28
43
  exports.findLatestCLIVersion = findLatestCLIVersion;
29
44
  async function isCorrectNodeVersion(currentVersion) {
30
- return semver_1.default.satisfies(currentVersion, '>=16.13.2 <17');
45
+ return semver_1.default.satisfies(currentVersion, '>=16');
31
46
  }
32
47
  exports.isCorrectNodeVersion = isCorrectNodeVersion;
@@ -12,13 +12,18 @@ const MEDIUM = 'MEDIUM';
12
12
  const HIGH = 'HIGH';
13
13
  const CRITICAL = 'CRITICAL';
14
14
  const APP_NAME = 'contrast';
15
- const APP_VERSION = '1.0.5';
15
+ const APP_VERSION = '1.0.8';
16
16
  const TIMEOUT = 120000;
17
17
  const HIGH_COLOUR = '#ff9900';
18
18
  const CRITICAL_COLOUR = '#e35858';
19
19
  const MEDIUM_COLOUR = '#f1c232';
20
- const LOW_COLOUR = '#ff9900';
20
+ const LOW_COLOUR = '#b7b7b7';
21
21
  const NOTE_COLOUR = '#999999';
22
+ const CRITICAL_PRIORITY = 1;
23
+ const HIGH_PRIORITY = 2;
24
+ const MEDIUM_PRIORITY = 3;
25
+ const LOW_PRIORITY = 4;
26
+ const NOTE_PRIORITY = 5;
22
27
  const AUTH_UI_URL = 'https://cli-auth.contrastsecurity.com';
23
28
  const AUTH_CALLBACK_URL = 'https://cli-auth-api.contrastsecurity.com';
24
29
  const SARIF_FILE = 'SARIF';
@@ -40,5 +45,10 @@ module.exports = {
40
45
  MEDIUM_COLOUR,
41
46
  LOW_COLOUR,
42
47
  NOTE_COLOUR,
43
- CE_URL
48
+ CE_URL,
49
+ CRITICAL_PRIORITY,
50
+ HIGH_PRIORITY,
51
+ MEDIUM_PRIORITY,
52
+ LOW_PRIORITY,
53
+ NOTE_PRIORITY
44
54
  };
@@ -12,7 +12,7 @@ const en_locales = () => {
12
12
  vulnerabilitiesFailureMessage: 'Unable to retrieve library vulnerabilities',
13
13
  catchErrorMessage: 'Contrast UI error: ',
14
14
  dependenciesNote: 'Please Note: We currently only support projects with one .csproj AND *.package.lock.json',
15
- languageAnalysisFailureMessage: 'SCA Analysis Failure',
15
+ languageAnalysisFailureMessage: 'SCA audit Failure',
16
16
  languageAnalysisFactoryFailureHeader: 'FAIL',
17
17
  libraryAnalysisError: 'Please ensure the language parameter is set in accordance to the language specified on the project path.\nContrast CLI must be run in the same directory as the project manifest file OR the project_path parameter must be used to identify the directory containing the project manifest file.\n\nFor further information please read our usage guide, which can be accessed with the following command:\n\ncontrast-cli --help',
18
18
  yamlMissingParametersHeader: 'Missing Parameters',
@@ -78,7 +78,7 @@ const en_locales = () => {
78
78
  constantsApplicationName: 'The name of the application cataloged by Contrast UI',
79
79
  constantsCatalogueApplication: 'Provide this if you want to catalogue an application',
80
80
  constantsLanguage: 'Valid values are JAVA, DOTNET, NODE, PYTHON and RUBY. If there are multiple project configuration files in the project_path, language is also required. Also, provide this when cataloguing an application',
81
- constantsProjectPath: 'The directory root of a project/application that you would like analyzed. Defaults to current directory.',
81
+ constantsFilePath: 'The directory root of a project/application that you would like analyzed. Defaults to current directory.',
82
82
  constantsSilent: 'Silences JSON output.',
83
83
  constantsAppGroups: 'Assign your application to one or more pre-existing groups when using the catalogue command. Group lists should be comma separated.',
84
84
  constantsVersion: 'Displays CLI Version you are currently on.',
@@ -90,13 +90,13 @@ const en_locales = () => {
90
90
  constantsProjectName: 'Contrast project name. If not specified, Contrast uses contrast.settings to identify the project or creates a project.',
91
91
  constantsProjectId: 'The ID associated with a scan project. Replace <ProjectID> with the ID for the scan project. To find the ID, select a scan project in Contrast and locate the last number in the URL.',
92
92
  constantsReport: 'Display vulnerability information for this application',
93
- constantsFail: 'Set the process to fail if this option is set in combination with the --report and --cve_severity.',
94
- failOptionErrorMessage: " FAIL - CVE's have been detected that match at least the cve_severity or cve_threshold option specified.",
95
- constantsSeverity: 'Combined with the --report command, allows the user to report libraries with vulnerabilities above a chosen severity level. For example, cve_severity medium only reports libraries with vulnerabilities at medium or higher severity. Values for level are high, medium or low.',
96
- constantsCount: "The number of CVE's that must be exceeded to fail a build",
93
+ constantsFail: 'Set the process to fail if this option is set in combination with --cve_severity.',
94
+ failOptionErrorMessage: ' FAIL - CVEs have been detected that match at least the cve_severity or cve_threshold option specified.',
95
+ constantsSeverity: 'Allows the user to report libraries with vulnerabilities above a chosen severity level. For example, cve_severity medium only reports libraries with vulnerabilities at medium or higher severity. Values for level are high, medium or low.',
96
+ constantsCount: 'The number of CVEs that must be exceeded to fail a build',
97
97
  constantsHeader: 'CodeSec by Contrast Security',
98
98
  constantsPrerequisitesContentScanLanguages: 'Java & JavaScript supported',
99
- constantsContrastContent: 'Use the Contrast CLI to run a scan (Java, JavaScript and .NET ) or lambda command (Java and Python) to find your vulnerabilities and start securing your code.',
99
+ constantsContrastContent: "Use the 'contrast' command for fast and accurate security analysis of your applications and APIs (Java, JavaScript and .NET ) as well as serverless functions (AWS lambda, Java and Python).",
100
100
  constantsUsageGuideContentRecommendation: 'Our recommendation is that this is invoked as part of a CI pipeline so that running the cli is automated as part of your build process.',
101
101
  constantsPrerequisitesHeader: 'Pre-requisites',
102
102
  constantsAuthUsageHeader: 'Usage',
@@ -162,7 +162,7 @@ const en_locales = () => {
162
162
  constantsIgnoreCertErrors: 'For EOP users with a local Teamserver install, this will bypass the SSL certificate and recognise a self signed certificate.',
163
163
  constantsSave: 'Saves the Scan Results SARIF to file.',
164
164
  scanLabel: "adds a label to the scan - defaults to 'Started by CLI tool at current date'",
165
- constantsIgnoreDev: 'Combined with the --report command excludes developer dependencies from the vulnerabilities report. By default all dependencies are included in a report.',
165
+ constantsIgnoreDev: 'Excludes developer dependencies from the output. By default all dependencies are included.',
166
166
  constantsCommands: 'Commands',
167
167
  constantsScanOptions: 'Scan Options',
168
168
  sbomError: 'All required parameters are not present.',
@@ -247,6 +247,7 @@ const en_locales = () => {
247
247
  redirectAuth: '\nOpening the authentication page in your web browser.\nSign in and complete the steps.\nReturn here to start using Contrast.\n\nIf your browser has trouble loading, try this:\n%s \n',
248
248
  scanZipError: 'A .zip archive can be used for Javascript Scan. Archive found %s does not contain .JS files for Scan.',
249
249
  fileNotExist: 'File specified does not exist, please check and try again.',
250
+ scanFileIsEmpty: 'File specified is empty. Please choose another.',
250
251
  fileHasWhiteSpacesError: 'File cannot have spaces, please rename or choose another file to Scan.',
251
252
  zipFileException: 'Error reading zip file',
252
253
  connectionError: 'An error has occurred when trying to get the Project Id please check your internet connection or provide the Project Id manually',
@@ -276,11 +277,12 @@ const en_locales = () => {
276
277
  auditOptionsIgnoreDevDependencies: '-igd, --ignore-dev',
277
278
  auditOptionsIgnoreDevDependenciesDescription: 'ignores DevDependencies',
278
279
  auditOptionsSave: '-s, --save',
279
- auditOptionsSaveDescription: 'saves the output in specified format Txt text, sbom',
280
+ auditOptionsSaveDescription: 'saves the output in specified format, options: sbom',
280
281
  scanNotCompleted: 'Scan not completed. Check for framework and language support here: %s',
281
- scanNoVulnerabilitiesFound: '👏 No vulnerabilities found',
282
+ auditNotCompleted: 'audit not completed. Please try again',
283
+ scanNoVulnerabilitiesFound: '🎉 No vulnerabilities found.',
282
284
  scanNoVulnerabilitiesFoundSecureCode: '👍 Your code looks secure.',
283
- scanNoVulnerabilitiesFoundGoodWork: '👏 Keep up the good work.',
285
+ scanNoVulnerabilitiesFoundGoodWork: ' Keep up the good work.',
284
286
  scanNoFiletypeSpecifiedForSave: 'Please specify file type to save results to, accepted value is SARIF',
285
287
  auditSBOMSaveSuccess: '\n Software Bill of Materials (SBOM) saved successfully',
286
288
  auditNoFiletypeSpecifiedForSave: `\n ${chalk.yellow.bold('No file type specified for --save option to save audit results to. Use audit --help to see valid --save options.')}`,
@@ -289,7 +291,8 @@ const en_locales = () => {
289
291
  auditReportFail: 'Report Retrieval Failed, please try again',
290
292
  auditReportSuccessMessage: 'Report successfully retrieved',
291
293
  auditReportFailureMessage: 'Unable to generate library report',
292
- auditSCAAnalysisBegins: 'Contrast SCA analysis begins',
294
+ auditSCAAnalysisBegins: 'Contrast SCA audit started',
295
+ auditSCAAnalysisComplete: 'Contrast SCA audit complete',
293
296
  ...lambda
294
297
  };
295
298
  };
package/dist/constants.js CHANGED
@@ -43,7 +43,6 @@ const scanOptionDefinitions = [
43
43
  },
44
44
  {
45
45
  name: 'project-path',
46
- alias: 'i',
47
46
  description: '{bold ' +
48
47
  i18n.__('constantsOptional') +
49
48
  '}: ' +
@@ -188,12 +187,13 @@ const auditOptionDefinitions = [
188
187
  i18n.__('constantsApplicationName')
189
188
  },
190
189
  {
191
- name: 'project-path',
192
- defaultValue: process.env.PWD,
190
+ name: 'file',
191
+ alias: 'f',
192
+ defaultValue: process.cwd(),
193
193
  description: '{bold ' +
194
194
  i18n.__('constantsOptional') +
195
195
  '}: ' +
196
- i18n.__('constantsProjectPath')
196
+ i18n.__('constantsFilePath')
197
197
  },
198
198
  {
199
199
  name: 'app-groups',
@@ -295,6 +295,11 @@ const auditOptionDefinitions = [
295
295
  i18n.__('constantsOptional') +
296
296
  '}: ' +
297
297
  i18n.__('auditOptionsSaveDescription')
298
+ },
299
+ {
300
+ name: 'experimental',
301
+ alias: 'e',
302
+ type: Boolean
298
303
  }
299
304
  ];
300
305
  const mainUsageGuide = commandLineUsage([
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env node
1
2
  "use strict";
2
3
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
@@ -36,12 +37,12 @@ const start = async () => {
36
37
  argvMain.includes('--v') ||
37
38
  argvMain.includes('--version')) {
38
39
  console.log(constants_2.APP_VERSION);
39
- await (0, versionChecker_1.findLatestCLIVersion)(config.get('updateMessageHidden'));
40
+ await (0, versionChecker_1.findLatestCLIVersion)(config);
40
41
  return;
41
42
  }
42
43
  config.set('numOfRuns', config.get('numOfRuns') + 1);
43
- if (config.get('numOfRuns') >= 5) {
44
- await (0, versionChecker_1.findLatestCLIVersion)(config.get('updateMessageHidden'));
44
+ if (config.get('numOfRuns') >= 1) {
45
+ await (0, versionChecker_1.findLatestCLIVersion)(config);
45
46
  config.set('numOfRuns', 0);
46
47
  }
47
48
  if (command === 'config') {
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.postAnalytics = void 0;
4
+ const commonApi_1 = require("../utils/commonApi");
5
+ const paramHandler_1 = require("../utils/paramsUtil/paramHandler");
6
+ const postAnalytics = (data, provider = 'aws') => {
7
+ const config = (0, paramHandler_1.getAuth)();
8
+ const client = (0, commonApi_1.getHttpClient)(config);
9
+ return client.postAnalyticsFunction(config, provider, data);
10
+ };
11
+ exports.postAnalytics = postAnalytics;
@@ -20,6 +20,8 @@ const utils_1 = require("./utils");
20
20
  const lambdaUtils_1 = require("./lambdaUtils");
21
21
  const requestUtils_1 = require("../utils/requestUtils");
22
22
  const oraWrapper_1 = __importDefault(require("../utils/oraWrapper"));
23
+ const analytics_1 = require("./analytics");
24
+ const types_1 = require("./types");
23
25
  const failedStates = [
24
26
  'UNSUPPORTED',
25
27
  'EXCLUDED',
@@ -57,9 +59,19 @@ const getLambdaOptions = (argv) => {
57
59
  }
58
60
  };
59
61
  const processLambda = async (argv) => {
62
+ let errorMsg;
63
+ let scanInfo;
64
+ const commandSessionId = Date.now().toString(36);
60
65
  try {
61
66
  const lambdaOptions = getLambdaOptions(argv);
62
67
  const { help } = lambdaOptions;
68
+ const startCommandAnalytics = {
69
+ arguments: lambdaOptions,
70
+ sessionId: commandSessionId,
71
+ eventType: types_1.EventType.START
72
+ };
73
+ (0, analytics_1.postAnalytics)(startCommandAnalytics).catch((error) => {
74
+ });
63
75
  if (help) {
64
76
  return handleLambdaHelp();
65
77
  }
@@ -68,17 +80,35 @@ const processLambda = async (argv) => {
68
80
  await getAvailableFunctions(lambdaOptions);
69
81
  }
70
82
  else {
71
- await actualProcessLambda(lambdaOptions);
83
+ scanInfo = await actualProcessLambda(lambdaOptions);
72
84
  }
73
85
  }
74
86
  catch (error) {
75
87
  if (error instanceof cliError_1.CliError) {
76
- console.error(error.getErrorMessage());
88
+ errorMsg = error.getErrorMessage();
77
89
  }
78
90
  else if (error instanceof Error) {
79
- console.error(error.message);
91
+ errorMsg = error.message;
92
+ }
93
+ }
94
+ finally {
95
+ const endCommandAnalytics = {
96
+ sessionId: commandSessionId,
97
+ eventType: types_1.EventType.END,
98
+ status: errorMsg ? types_1.StatusType.FAILED : types_1.StatusType.SUCCESS
99
+ };
100
+ if (errorMsg) {
101
+ endCommandAnalytics.errorMsg = errorMsg;
102
+ console.error(errorMsg);
103
+ }
104
+ if (scanInfo) {
105
+ endCommandAnalytics.scanFunctionData = scanInfo;
106
+ }
107
+ await (0, analytics_1.postAnalytics)(endCommandAnalytics).catch((error) => {
108
+ });
109
+ if (errorMsg) {
110
+ process.exit(1);
80
111
  }
81
- process.exit(1);
82
112
  }
83
113
  };
84
114
  exports.processLambda = processLambda;
@@ -127,6 +157,7 @@ const actualProcessLambda = async (lambdaOptions) => {
127
157
  if (results?.length) {
128
158
  (0, utils_1.printResults)(results);
129
159
  }
160
+ return { functionArn, scanId };
130
161
  };
131
162
  const validateRequiredLambdaParams = (options) => {
132
163
  if (options._unknown?.length) {
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EventType = exports.StatusType = void 0;
4
+ var StatusType;
5
+ (function (StatusType) {
6
+ StatusType["FAILED"] = "failed";
7
+ StatusType["SUCCESS"] = "success";
8
+ })(StatusType = exports.StatusType || (exports.StatusType = {}));
9
+ var EventType;
10
+ (function (EventType) {
11
+ EventType["START"] = "start_command_session";
12
+ EventType["END"] = "end_command_session";
13
+ })(EventType = exports.EventType || (exports.EventType = {}));
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateSbom = void 0;
3
4
  const commonApi_1 = require("../utils/commonApi");
4
- function generateSbom(config) {
5
+ const generateSbom = (config) => {
5
6
  const client = (0, commonApi_1.getHttpClient)(config);
6
7
  return client
7
8
  .getSbom(config)
@@ -16,5 +17,5 @@ function generateSbom(config) {
16
17
  .catch((err) => {
17
18
  console.log(err);
18
19
  });
19
- }
20
- exports.default = generateSbom;
20
+ };
21
+ exports.generateSbom = generateSbom;
@@ -6,6 +6,51 @@ const createJavaTSMessage = javaTree => {
6
6
  }
7
7
  };
8
8
  };
9
+ const createJavaScriptTSMessage = js => {
10
+ let message = {
11
+ node: {
12
+ packageJSON: js.packageJSON
13
+ }
14
+ };
15
+ if (js.yarn !== undefined) {
16
+ message.node.yarnLockFile = js.yarn.yarnLockFile;
17
+ message.node.yarnVersion = js.yarn.yarnVersion;
18
+ }
19
+ else {
20
+ message.node.npmLockFile = js.npmLockFile;
21
+ }
22
+ return message;
23
+ };
24
+ const createGoTSMessage = goTree => {
25
+ return {
26
+ go: {
27
+ goDependencyTrees: goTree
28
+ }
29
+ };
30
+ };
31
+ const createRubyTSMessage = rubyTree => {
32
+ return {
33
+ ruby: rubyTree
34
+ };
35
+ };
36
+ const createPythonTSMessage = pythonTree => {
37
+ return {
38
+ python: pythonTree
39
+ };
40
+ };
41
+ const createPhpTSMessage = phpTree => {
42
+ return {
43
+ php: {
44
+ composerJSON: phpTree.composerJSON,
45
+ lockFile: phpTree.lockFile
46
+ }
47
+ };
48
+ };
9
49
  module.exports = {
10
- createJavaTSMessage
50
+ createJavaScriptTSMessage,
51
+ createJavaTSMessage,
52
+ createGoTSMessage,
53
+ createPhpTSMessage,
54
+ createRubyTSMessage,
55
+ createPythonTSMessage
11
56
  };
@@ -1,6 +1,5 @@
1
1
  "use strict";
2
2
  const { getHttpClient } = require('../../utils/commonApi');
3
- const { handleResponseErrors } = require('../../common/errorHandling');
4
3
  const { APP_VERSION } = require('../../constants/constants');
5
4
  const commonSendSnapShot = async (analysis, config) => {
6
5
  const requestBody = {
@@ -13,12 +12,11 @@ const commonSendSnapShot = async (analysis, config) => {
13
12
  .sendSnapshot(requestBody, config)
14
13
  .then(res => {
15
14
  if (res.statusCode === 201) {
16
- console.log('snapshot processed successfully');
17
15
  return res.body;
18
16
  }
19
17
  else {
20
18
  console.log(res.statusCode);
21
- handleResponseErrors(res, 'snapshot');
19
+ console.log('error processing dependencies');
22
20
  }
23
21
  })
24
22
  .catch(err => {
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ const { createGoTSMessage } = require('../common/formatMessage');
3
+ const goReadDepFile = require('./goReadDepFile');
4
+ const goParseDeps = require('./goParseDeps');
5
+ const goAnalysis = (config, languageFiles) => {
6
+ try {
7
+ const rawGoDependencies = goReadDepFile.getGoDependencies(config);
8
+ const parsedGoDependencies = goParseDeps.parseGoDependencies(rawGoDependencies);
9
+ return createGoTSMessage(parsedGoDependencies);
10
+ }
11
+ catch (e) {
12
+ console.log(e.message.toString());
13
+ }
14
+ };
15
+ module.exports = {
16
+ goAnalysis
17
+ };
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ const crypto = require('crypto');
3
+ const parseGoDependencies = goDeps => {
4
+ return parseGo(goDeps);
5
+ };
6
+ const parseGo = modGraphOutput => {
7
+ let splitLines = splitAllLinesIntoArray(modGraphOutput);
8
+ const directDepNames = getDirectDepNames(splitLines);
9
+ const uniqueTransitiveDepNames = getAllUniqueTransitiveDepNames(splitLines, directDepNames);
10
+ let rootNodes = createRootNodes(splitLines);
11
+ createTransitiveDeps(uniqueTransitiveDepNames, splitLines, rootNodes);
12
+ return rootNodes;
13
+ };
14
+ const splitAllLinesIntoArray = modGraphOutput => {
15
+ return modGraphOutput.split(/\r\n|\r|\n/);
16
+ };
17
+ const getAllDepsOfADepAsEdge = (dep, deps) => {
18
+ let edges = {};
19
+ const depRows = deps.filter(line => {
20
+ return line.startsWith(dep);
21
+ });
22
+ depRows.forEach(dep => {
23
+ const edgeName = dep.split(' ')[1];
24
+ edges[edgeName] = edgeName;
25
+ });
26
+ return edges;
27
+ };
28
+ const getAllDepsOfADepAsName = (dep, deps) => {
29
+ let edges = [];
30
+ const depRows = deps.filter(line => {
31
+ return line.startsWith(dep);
32
+ });
33
+ depRows.forEach(dep => {
34
+ const edgeName = dep.split(' ')[1];
35
+ edges.push(edgeName);
36
+ });
37
+ return edges;
38
+ };
39
+ const createRootNodes = deps => {
40
+ let rootDep = {};
41
+ const rootDeps = getRootDeps(deps);
42
+ const edges = rootDeps.map(dep => {
43
+ return dep.split(' ')[1];
44
+ });
45
+ rootDep[rootDeps[0].split(' ')[0]] = {};
46
+ edges.forEach(edge => {
47
+ const splitEdge = edge.split('@');
48
+ const splitGroupName = splitEdge[0].split('/');
49
+ const name = splitGroupName.pop();
50
+ const lastSlash = splitEdge[0].lastIndexOf('/');
51
+ let group = splitEdge[0].substring(0, lastSlash);
52
+ const hash = getHash(splitEdge[0]);
53
+ group = checkGroupExists(group, name);
54
+ const edgesOfDep = getAllDepsOfADepAsEdge(edge, deps);
55
+ rootDep[rootDeps[0].split(' ')[0]][edge] = {
56
+ artifactID: name,
57
+ group: group,
58
+ version: splitEdge[1],
59
+ scope: '"compile',
60
+ type: 'direct',
61
+ hash: hash,
62
+ edges: edgesOfDep
63
+ };
64
+ });
65
+ return rootDep;
66
+ };
67
+ const getRootDeps = deps => {
68
+ const rootDeps = deps.filter(dep => {
69
+ const parentDep = dep.split(' ')[0];
70
+ if (parentDep.split('@v').length === 1) {
71
+ return dep;
72
+ }
73
+ });
74
+ return rootDeps;
75
+ };
76
+ const getHash = library => {
77
+ let shaSum = crypto.createHash('sha1');
78
+ shaSum.update(library);
79
+ return shaSum.digest('hex');
80
+ };
81
+ const getDirectDepNames = deps => {
82
+ const directDepNames = [];
83
+ deps.forEach(dep => {
84
+ const parentDep = dep.split(' ')[0];
85
+ if (parentDep.split('@v').length === 1) {
86
+ dep.split(' ')[1] !== undefined
87
+ ? directDepNames.push(dep.split(' ')[1])
88
+ : null;
89
+ }
90
+ });
91
+ return directDepNames;
92
+ };
93
+ const getAllUniqueTransitiveDepNames = (deps, directDepNames) => {
94
+ let uniqueDeps = [];
95
+ deps.forEach(dep => {
96
+ const parentDep = dep.split(' ')[0];
97
+ if (parentDep.split('@v').length !== 1) {
98
+ if (!directDepNames.includes(parentDep)) {
99
+ if (!uniqueDeps.includes(parentDep)) {
100
+ parentDep.length > 1 ? uniqueDeps.push(parentDep) : null;
101
+ }
102
+ }
103
+ }
104
+ });
105
+ return uniqueDeps;
106
+ };
107
+ const checkGroupExists = (group, name) => {
108
+ if (group === null || group === '') {
109
+ return name;
110
+ }
111
+ return group;
112
+ };
113
+ const createTransitiveDeps = (transitiveDeps, splitLines, rootNodes) => {
114
+ transitiveDeps.forEach(dep => {
115
+ const splitEdge = dep.split('@');
116
+ const splitGroupName = splitEdge[0].split('/');
117
+ const name = splitGroupName.pop();
118
+ const lastSlash = splitEdge[0].lastIndexOf('/');
119
+ let group = splitEdge[0].substring(0, lastSlash);
120
+ const hash = getHash(splitEdge[0]);
121
+ group = checkGroupExists(group, name);
122
+ const transitiveDep = {
123
+ artifactID: name,
124
+ group: group,
125
+ version: splitEdge[1],
126
+ scope: 'compile',
127
+ type: 'transitive',
128
+ hash: hash,
129
+ edges: {}
130
+ };
131
+ const edges = getAllDepsOfADepAsEdge(dep, splitLines);
132
+ transitiveDep.edges = edges;
133
+ const edgesAsName = getAllDepsOfADepAsName(dep, splitLines);
134
+ edgesAsName.forEach(dep => {
135
+ const splitEdge = dep.split('@');
136
+ const splitGroupName = splitEdge[0].split('/');
137
+ const name = splitGroupName.pop();
138
+ const lastSlash = splitEdge[0].lastIndexOf('/');
139
+ let group = splitEdge[0].substring(0, lastSlash);
140
+ const hash = getHash(splitEdge[0]);
141
+ group = checkGroupExists(group, name);
142
+ const transitiveDep = {
143
+ artifactID: name,
144
+ group: group,
145
+ version: splitEdge[1],
146
+ scope: 'compile',
147
+ type: 'transitive',
148
+ hash: hash,
149
+ edges: {}
150
+ };
151
+ rootNodes[Object.keys(rootNodes)[0]][dep] = transitiveDep;
152
+ });
153
+ rootNodes[Object.keys(rootNodes)[0]][dep] = transitiveDep;
154
+ });
155
+ };
156
+ module.exports = {
157
+ parseGoDependencies
158
+ };
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ const child_process = require('child_process');
3
+ const i18n = require('i18n');
4
+ const getGoDependencies = config => {
5
+ let cmdStdout;
6
+ let cwd = config.file ? config.file.replace('go.mod', '') : process.cwd();
7
+ try {
8
+ cmdStdout = child_process.execSync('go mod graph', { cwd });
9
+ return cmdStdout.toString();
10
+ }
11
+ catch (err) {
12
+ if (err.message === 'spawnSync /bin/sh ENOENT') {
13
+ err.message =
14
+ '\n\n*************** No transitive dependencies ***************\n\nWe are unable to build a dependency tree view from your repository as there were no transitive dependencies found.';
15
+ }
16
+ console.log(i18n.__('goReadProjectFile', cwd, `${err.message ? err.message : ''}`));
17
+ }
18
+ };
19
+ module.exports = {
20
+ getGoDependencies
21
+ };