@contrast/contrast 1.0.10 → 1.0.13

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 (112) hide show
  1. package/README.md +1 -1
  2. package/dist/audit/{languageAnalysisEngine/report → report}/commonReportingFunctions.js +56 -35
  3. package/dist/audit/report/models/reportGuidanceModel.js +6 -0
  4. package/dist/audit/{languageAnalysisEngine/report → report}/models/reportLibraryModel.js +0 -0
  5. package/dist/audit/{languageAnalysisEngine/report → report}/models/reportListModel.js +0 -0
  6. package/dist/audit/{languageAnalysisEngine/report → report}/models/reportOutputModel.js +1 -2
  7. package/dist/audit/{languageAnalysisEngine/report → report}/models/reportSeverityModel.js +0 -0
  8. package/dist/audit/{languageAnalysisEngine/report → report}/models/severityCountModel.js +1 -0
  9. package/dist/audit/{languageAnalysisEngine/report → report}/reportingFeature.js +12 -8
  10. package/dist/audit/{languageAnalysisEngine/report → report}/utils/reportUtils.js +3 -4
  11. package/dist/commands/audit/auditConfig.js +3 -3
  12. package/dist/commands/audit/help.js +3 -1
  13. package/dist/commands/audit/processAudit.js +14 -2
  14. package/dist/commands/auth/auth.js +1 -1
  15. package/dist/commands/config/config.js +2 -2
  16. package/dist/commands/scan/processScan.js +20 -4
  17. package/dist/commands/scan/sca/scaAnalysis.js +15 -5
  18. package/dist/common/HTTPClient.js +39 -2
  19. package/dist/common/commonHelp.js +19 -0
  20. package/dist/common/fail.js +70 -0
  21. package/dist/common/versionChecker.js +14 -6
  22. package/dist/constants/constants.js +2 -2
  23. package/dist/constants/locales.js +15 -5
  24. package/dist/constants.js +42 -5
  25. package/dist/index.js +6 -3
  26. package/dist/lambda/help.js +2 -3
  27. package/dist/lambda/lambda.js +7 -0
  28. package/dist/scaAnalysis/common/scaParserForGoAndJava.js +32 -0
  29. package/dist/scaAnalysis/common/scaServicesUpload.js +52 -0
  30. package/dist/scaAnalysis/common/treeUpload.js +20 -5
  31. package/dist/scaAnalysis/dotnet/analysis.js +15 -3
  32. package/dist/scaAnalysis/go/goAnalysis.js +8 -2
  33. package/dist/scaAnalysis/java/analysis.js +10 -6
  34. package/dist/scaAnalysis/java/index.js +7 -1
  35. package/dist/scaAnalysis/java/javaBuildDepsParser.js +19 -3
  36. package/dist/scaAnalysis/javascript/index.js +4 -0
  37. package/dist/scaAnalysis/javascript/scaServiceParser.js +109 -0
  38. package/dist/scaAnalysis/php/analysis.js +1 -1
  39. package/dist/scaAnalysis/php/index.js +12 -6
  40. package/dist/scaAnalysis/php/phpNewServicesMapper.js +62 -0
  41. package/dist/scaAnalysis/python/analysis.js +43 -5
  42. package/dist/scaAnalysis/python/index.js +7 -2
  43. package/dist/scaAnalysis/ruby/analysis.js +116 -9
  44. package/dist/scaAnalysis/ruby/index.js +6 -1
  45. package/dist/scan/formatScanOutput.js +6 -5
  46. package/dist/scan/help.js +2 -3
  47. package/dist/scan/populateProjectIdAndProjectName.js +5 -0
  48. package/dist/scan/scan.js +4 -0
  49. package/dist/scan/scanConfig.js +4 -4
  50. package/dist/scan/scanResults.js +46 -3
  51. package/dist/telemetry/telemetry.js +137 -0
  52. package/dist/{audit/languageAnalysisEngine/util → utils}/capabilities.js +0 -0
  53. package/dist/{audit/languageAnalysisEngine/util → utils}/generalAPI.js +14 -5
  54. package/dist/utils/getConfig.js +2 -4
  55. package/dist/utils/parsedCLIOptions.js +3 -1
  56. package/dist/utils/requestUtils.js +7 -1
  57. package/package.json +4 -2
  58. package/src/audit/{languageAnalysisEngine/report → report}/commonReportingFunctions.ts +80 -44
  59. package/src/audit/report/models/reportGuidanceModel.ts +5 -0
  60. package/src/audit/{languageAnalysisEngine/report → report}/models/reportLibraryModel.ts +0 -0
  61. package/src/audit/{languageAnalysisEngine/report → report}/models/reportListModel.ts +0 -0
  62. package/src/audit/{languageAnalysisEngine/report → report}/models/reportOutputModel.ts +1 -7
  63. package/src/audit/{languageAnalysisEngine/report → report}/models/reportSeverityModel.ts +0 -0
  64. package/src/audit/{languageAnalysisEngine/report → report}/models/severityCountModel.ts +2 -0
  65. package/src/audit/{languageAnalysisEngine/report → report}/reportingFeature.ts +16 -9
  66. package/src/audit/{languageAnalysisEngine/report → report}/utils/reportUtils.ts +4 -4
  67. package/src/commands/audit/auditConfig.ts +10 -3
  68. package/src/commands/audit/help.ts +3 -1
  69. package/src/commands/audit/processAudit.ts +24 -2
  70. package/src/commands/auth/auth.js +3 -1
  71. package/src/commands/config/config.js +4 -2
  72. package/src/commands/scan/processScan.js +32 -4
  73. package/src/commands/scan/sca/scaAnalysis.js +23 -5
  74. package/src/common/HTTPClient.js +59 -2
  75. package/src/common/commonHelp.ts +13 -0
  76. package/src/common/fail.js +79 -0
  77. package/src/common/versionChecker.ts +18 -8
  78. package/src/constants/constants.js +2 -2
  79. package/src/constants/locales.js +19 -7
  80. package/src/constants.js +46 -6
  81. package/src/index.ts +18 -4
  82. package/src/lambda/help.ts +2 -3
  83. package/src/lambda/lambda.ts +12 -0
  84. package/src/scaAnalysis/common/scaParserForGoAndJava.js +41 -0
  85. package/src/scaAnalysis/common/scaServicesUpload.js +54 -0
  86. package/src/scaAnalysis/common/treeUpload.js +21 -5
  87. package/src/scaAnalysis/dotnet/analysis.js +21 -3
  88. package/src/scaAnalysis/go/goAnalysis.js +9 -2
  89. package/src/scaAnalysis/java/analysis.js +11 -6
  90. package/src/scaAnalysis/java/index.js +9 -1
  91. package/src/scaAnalysis/java/javaBuildDepsParser.js +25 -6
  92. package/src/scaAnalysis/javascript/index.js +4 -0
  93. package/src/scaAnalysis/javascript/scaServiceParser.js +145 -0
  94. package/src/scaAnalysis/php/analysis.js +1 -1
  95. package/src/scaAnalysis/php/index.js +12 -6
  96. package/src/scaAnalysis/php/phpNewServicesMapper.js +77 -0
  97. package/src/scaAnalysis/python/analysis.js +49 -5
  98. package/src/scaAnalysis/python/index.js +7 -2
  99. package/src/scaAnalysis/ruby/analysis.js +149 -9
  100. package/src/scaAnalysis/ruby/index.js +6 -1
  101. package/src/scan/formatScanOutput.ts +7 -5
  102. package/src/scan/help.js +2 -3
  103. package/src/scan/populateProjectIdAndProjectName.js +5 -1
  104. package/src/scan/scan.ts +4 -0
  105. package/src/scan/scanConfig.js +6 -4
  106. package/src/scan/scanResults.js +52 -3
  107. package/src/telemetry/telemetry.ts +154 -0
  108. package/src/{audit/languageAnalysisEngine/util → utils}/capabilities.js +0 -0
  109. package/src/{audit/languageAnalysisEngine/util → utils}/generalAPI.js +16 -6
  110. package/src/utils/getConfig.ts +2 -11
  111. package/src/utils/parsedCLIOptions.js +14 -1
  112. package/src/utils/requestUtils.js +8 -1
@@ -3,7 +3,7 @@ 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.isCorrectNodeVersion = exports.findLatestCLIVersion = void 0;
6
+ exports.isCorrectNodeVersion = exports.findLatestCLIVersion = exports.getLatestVersion = void 0;
7
7
  const constants_1 = require("../constants/constants");
8
8
  const boxen_1 = __importDefault(require("boxen"));
9
9
  const chalk_1 = __importDefault(require("chalk"));
@@ -19,14 +19,22 @@ const getLatestVersion = async (config) => {
19
19
  }
20
20
  }
21
21
  catch (e) {
22
- return;
22
+ return undefined;
23
23
  }
24
24
  };
25
+ exports.getLatestVersion = getLatestVersion;
25
26
  async function findLatestCLIVersion(config) {
26
- const messageHidden = config.get('updateMessageHidden');
27
- if (!messageHidden) {
28
- let latestCLIVersion = await getLatestVersion(config);
29
- latestCLIVersion = latestCLIVersion.substring(8);
27
+ const isCI = process.env.CONTRAST_CODESEC_CI
28
+ ? JSON.parse(process.env.CONTRAST_CODESEC_CI.toLowerCase())
29
+ : false;
30
+ if (!isCI) {
31
+ let latestCLIVersion = await (0, exports.getLatestVersion)(config);
32
+ if (latestCLIVersion === undefined) {
33
+ config.set('numOfRuns', 0);
34
+ console.log('Failed to retrieve latest version info. Continuing execution.');
35
+ return;
36
+ }
37
+ latestCLIVersion = latestCLIVersion.substring(8).replace('\n', '');
30
38
  if (semver_1.default.lt(constants_1.APP_VERSION, latestCLIVersion)) {
31
39
  const updateAvailableMessage = `Update available ${chalk_1.default.yellow(constants_1.APP_VERSION)} → ${chalk_1.default.green(latestCLIVersion)}`;
32
40
  const npmUpdateAvailableCommand = `Run ${chalk_1.default.cyan('npm i @contrast/contrast -g')} to update via npm`;
@@ -12,7 +12,7 @@ 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.10';
15
+ const APP_VERSION = '1.0.13';
16
16
  const TIMEOUT = 120000;
17
17
  const HIGH_COLOUR = '#ff9900';
18
18
  const CRITICAL_COLOUR = '#e35858';
@@ -29,7 +29,7 @@ const AUTH_CALLBACK_URL = 'https://cli-auth-api.contrastsecurity.com';
29
29
  const SARIF_FILE = 'SARIF';
30
30
  const SBOM_CYCLONE_DX_FILE = 'cyclonedx';
31
31
  const SBOM_SPDX_FILE = 'spdx';
32
- const CE_URL = 'https://ce.contrastsecurity.com/';
32
+ const CE_URL = 'https://ce.contrastsecurity.com';
33
33
  module.exports = {
34
34
  supportedLanguages: { NODE, DOTNET, JAVA, RUBY, PYTHON, GO, PHP, JAVASCRIPT },
35
35
  supportedLanguagesScan: { JAVASCRIPT, DOTNET, JAVA },
@@ -20,7 +20,7 @@ const en_locales = () => {
20
20
  unauthenticatedErrorHeader: '401 error - Unauthenticated',
21
21
  unauthenticatedErrorMessage: 'Please check the following keys are correct:\n--organization-id, --api-key or --authorization',
22
22
  badRequestErrorHeader: '400 error - Bad Request',
23
- badRequestErrorMessage: 'Please check the following key is correct: \n--application-id',
23
+ badRequestErrorMessage: 'Please check your parameters and try again',
24
24
  badRequestCatalogueErrorMessage: 'The application name already exists, please use a unique name',
25
25
  forbiddenRequestErrorHeader: '403 error - Forbidden',
26
26
  forbiddenRequestErrorMessage: 'You do not have permission to access this server.',
@@ -79,8 +79,9 @@ const en_locales = () => {
79
79
  constantsHostId: 'Provide the name of the host and optionally the port expressed as "<host>:<port>".',
80
80
  constantsApplicationName: 'The name of the application cataloged by Contrast UI',
81
81
  constantsCatalogueApplication: 'Provide this if you want to catalogue an application',
82
+ failOptionErrorMessage: ' FAIL - CVEs have been detected that match at least the cve_severity option specified.',
82
83
  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',
83
- constantsFilePath: `Path of the file you want to perform an SCA audit on. If no folder is specified, Contrast searches for dependency files in the working directory.`,
84
+ constantsFilePath: `Specify a directory or the file where dependencies are declared. (By default, CodeSec will search for project files in the current directory.)`,
84
85
  constantsSilent: 'Silences JSON output.',
85
86
  constantsAppGroups: 'Assign your application to one or more pre-existing groups when using the catalogue command. Group lists should be comma separated.',
86
87
  constantsVersion: 'Displays CLI Version you are currently on.',
@@ -93,7 +94,8 @@ const en_locales = () => {
93
94
  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.',
94
95
  constantsReport: 'Display vulnerability information for this application',
95
96
  constantsFail: 'Set the process to fail if this option is set in combination with --cve_severity.',
96
- failOptionErrorMessage: ' FAIL - CVEs have been detected that match at least the cve_severity or cve_threshold option specified.',
97
+ failThresholdOptionErrorMessage: 'More than 0 vulnerabilities found',
98
+ failSeverityOptionErrorMessage: ' FAIL - Results detected vulnerabilities over accepted severity level',
97
99
  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.',
98
100
  constantsCount: 'The number of CVEs that must be exceeded to fail a build',
99
101
  constantsHeader: 'CodeSec by Contrast Security',
@@ -211,7 +213,7 @@ const en_locales = () => {
211
213
  scanOptionsFileNameSummary: 'Path of the file you want to scan. If no file is specified, Contrast searches for a .jar, .war, .exe or .zip file in the working directory.',
212
214
  scanOptionsVerboseSummary: ' Returns extended information to the terminal.',
213
215
  authSuccessMessage: 'Authentication successful',
214
- runAuthSuccessMessage: "Now you can use CodeSec by Contrast \nRun: \n'contrast scan' on your file \n'contrast audit' on a file or directory,\n'contrast lambda' on an AWS function.\nor 'contrast help' to learn more about the capabilities.",
216
+ runAuthSuccessMessage: "Now you can use CodeSec by Contrast \nRun: \n'contrast scan' to run CodeSec’s industry leading SAST scanner \n'contrast audit' to find vulnerabilities in your open source dependencies \n'contrast lambda' to secure your AWS serverless functions\nor 'contrast help' to learn more about the capabilities.",
215
217
  authWaitingMessage: 'Waiting for auth...',
216
218
  authTimedOutMessage: 'Auth Timed out, try again',
217
219
  zipErrorScan: 'We only support zip files for JAVASCRIPT language, please set the flag --language JAVASCRIPT',
@@ -276,7 +278,8 @@ const en_locales = () => {
276
278
  constantsAuditPrerequisitesContentPHPMessage: `${chalk.bold('PHP:')} composer.json and composer.lock\n`,
277
279
  constantsAuditOptions: 'Audit Options',
278
280
  auditOptionsSaveDescription: 'Generate and save an SBOM (Software Bill of Materials)\n',
279
- auditOptionsSaveOptionsDescription: 'Valid options are: spdx, cyclonedx (cycloneDX is the default format)',
281
+ auditOptionsSaveOptionsDescription: 'Valid options are: --save spdx and --save cyclonedx (CycloneDX is the default format.)',
282
+ exceededFreeTier: `It looks like you are really loving CodeSec! \nYou have reached the monthly scan limit on the FREE tier. \nPlease contact sales@contrastsecurity.com to upgrade.`,
280
283
  scanNotCompleted: 'Scan not completed. Check for framework and language support here: %s',
281
284
  auditNotCompleted: 'audit not completed. Please try again',
282
285
  scanNoVulnerabilitiesFound: '🎉 No vulnerabilities found.',
@@ -292,6 +295,13 @@ const en_locales = () => {
292
295
  auditReportFailureMessage: 'Unable to generate library report',
293
296
  auditSCAAnalysisBegins: 'Contrast SCA audit started',
294
297
  auditSCAAnalysisComplete: 'Contrast audit complete',
298
+ commonHelpHeader: 'Need More Help?',
299
+ commonHelpCheckOutHeader: chalk.hex('#9DC184')('Check out:'),
300
+ commonHelpCheckOutText: ' https://support.contrastsecurity.com',
301
+ commonHelpLearnMoreHeader: chalk.hex('#9DC184')('Learn more at:'),
302
+ commonHelpLearnMoreText: ' https://developer.contrastsecurity.com',
303
+ commonHelpJoinDiscussionHeader: chalk.hex('#9DC184')('Join the discussion:'),
304
+ commonHelpJoinDiscussionText: ' https://dev.to/codesec',
295
305
  ...lambda
296
306
  };
297
307
  };
package/dist/constants.js CHANGED
@@ -2,6 +2,8 @@
2
2
  const commandLineUsage = require('command-line-usage');
3
3
  const i18n = require('i18n');
4
4
  const { en_locales } = require('./constants/locales.js');
5
+ const { parseSeverity } = require('./common/fail');
6
+ const { commonHelpLinks } = require('./common/commonHelp');
5
7
  i18n.configure({
6
8
  staticCatalog: {
7
9
  en: en_locales()
@@ -93,6 +95,22 @@ const scanOptionDefinitions = [
93
95
  '}: ' +
94
96
  i18n.__('constantsProxyServer')
95
97
  },
98
+ {
99
+ name: 'fail',
100
+ type: Boolean,
101
+ description: '{bold ' +
102
+ i18n.__('constantsOptional') +
103
+ '}: ' +
104
+ i18n.__('failOptionErrorMessage')
105
+ },
106
+ {
107
+ name: 'severity',
108
+ type: severity => parseSeverity(severity),
109
+ description: '{bold ' +
110
+ i18n.__('constantsOptional') +
111
+ '}: ' +
112
+ i18n.__('constantsSeverity')
113
+ },
96
114
  {
97
115
  name: 'ff',
98
116
  type: Boolean,
@@ -195,6 +213,22 @@ const auditOptionDefinitions = [
195
213
  '}: ' +
196
214
  i18n.__('constantsFilePath')
197
215
  },
216
+ {
217
+ name: 'fail',
218
+ type: Boolean,
219
+ description: '{bold ' +
220
+ i18n.__('constantsOptional') +
221
+ '}: ' +
222
+ i18n.__('failOptionErrorMessage')
223
+ },
224
+ {
225
+ name: 'severity',
226
+ type: severity => parseSeverity(severity),
227
+ description: '{bold ' +
228
+ i18n.__('constantsOptional') +
229
+ '}: ' +
230
+ i18n.__('constantsSeverity')
231
+ },
198
232
  {
199
233
  name: 'app-groups',
200
234
  description: '{bold ' +
@@ -227,6 +261,7 @@ const auditOptionDefinitions = [
227
261
  {
228
262
  name: 'ignore-dev',
229
263
  type: Boolean,
264
+ alias: 'i',
230
265
  description: '{bold ' +
231
266
  i18n.__('constantsOptional') +
232
267
  '}: ' +
@@ -259,7 +294,6 @@ const auditOptionDefinitions = [
259
294
  },
260
295
  {
261
296
  name: 'host',
262
- alias: 'h',
263
297
  description: '{bold ' +
264
298
  i18n.__('constantsRequired') +
265
299
  '}: ' +
@@ -302,6 +336,11 @@ const auditOptionDefinitions = [
302
336
  i18n.__('constantsOptional') +
303
337
  '}: ' +
304
338
  i18n.__('scanOptionsTimeoutSummary')
339
+ },
340
+ {
341
+ name: 'help',
342
+ alias: 'h',
343
+ type: Boolean
305
344
  }
306
345
  ];
307
346
  const mainUsageGuide = commandLineUsage([
@@ -328,15 +367,13 @@ const mainUsageGuide = commandLineUsage([
328
367
  { name: i18n.__('helpName'), summary: i18n.__('helpSummary') }
329
368
  ]
330
369
  },
331
- {
332
- content: '{underline https://developer.contrastsecurity.com/} \n For technical support head to {underline https://support.contrastsecurity.com}'
333
- },
334
370
  {
335
371
  header: i18n.__('configHeader2'),
336
372
  content: [
337
373
  { name: i18n.__('clearHeader'), summary: i18n.__('clearContent') }
338
374
  ]
339
- }
375
+ },
376
+ commonHelpLinks()
340
377
  ]);
341
378
  const mainDefinition = [{ name: 'command', defaultOption: true }];
342
379
  module.exports = {
package/dist/index.js CHANGED
@@ -15,6 +15,7 @@ const lambda_1 = require("./lambda/lambda");
15
15
  const getConfig_1 = require("./utils/getConfig");
16
16
  const versionChecker_1 = require("./common/versionChecker");
17
17
  const errorHandling_1 = require("./common/errorHandling");
18
+ const telemetry_1 = require("./telemetry/telemetry");
18
19
  const { commandLineDefinitions: { mainUsageGuide, mainDefinition } } = constants_1.default;
19
20
  const config = (0, getConfig_1.localConfig)(constants_2.APP_NAME, constants_2.APP_VERSION);
20
21
  const getMainOption = () => {
@@ -44,7 +45,7 @@ const start = async () => {
44
45
  return;
45
46
  }
46
47
  config.set('numOfRuns', config.get('numOfRuns') + 1);
47
- if (config.get('numOfRuns') >= 1) {
48
+ if (config.get('numOfRuns') >= 10) {
48
49
  await (0, versionChecker_1.findLatestCLIVersion)(config);
49
50
  config.set('numOfRuns', 0);
50
51
  }
@@ -58,10 +59,10 @@ const start = async () => {
58
59
  return await (0, lambda_1.processLambda)(argvMain);
59
60
  }
60
61
  if (command === 'scan') {
61
- return await (0, processScan_1.processScan)(argvMain);
62
+ return await (0, processScan_1.processScan)(config, argvMain);
62
63
  }
63
64
  if (command === 'audit') {
64
- return await (0, processAudit_1.processAudit)(argvMain);
65
+ return await (0, processAudit_1.processAudit)(config, argvMain);
65
66
  }
66
67
  if (command === 'help' ||
67
68
  argvMain.includes('--help') ||
@@ -73,9 +74,11 @@ const start = async () => {
73
74
  foundCommand
74
75
  ? console.log(`Unknown Command: Did you mean "${foundCommand}"? \nUse "${foundCommand} --help" for the full list of options`)
75
76
  : console.log(`Unknown Command: ${command} \nUse --help for the full list`);
77
+ await (0, telemetry_1.sendTelemetryConfigAsConfObj)(config, command, argvMain, 'FAILURE', 'undefined');
76
78
  }
77
79
  else {
78
80
  console.log(`Unknown Command: ${command} \nUse --help for the full list`);
81
+ await (0, telemetry_1.sendTelemetryConfigAsConfObj)(config, command, argvMain, 'FAILURE', 'undefined');
79
82
  }
80
83
  process.exit(9);
81
84
  }
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.lambdaUsageGuide = void 0;
7
7
  const command_line_usage_1 = __importDefault(require("command-line-usage"));
8
8
  const i18n_1 = __importDefault(require("i18n"));
9
+ const commonHelp_1 = require("../common/commonHelp");
9
10
  const lambdaUsageGuide = (0, command_line_usage_1.default)([
10
11
  {
11
12
  header: i18n_1.default.__('lambdaHeader'),
@@ -80,8 +81,6 @@ const lambdaUsageGuide = (0, command_line_usage_1.default)([
80
81
  { name: i18n_1.default.__('lambdaHelpOption'), summary: i18n_1.default.__('helpSummary') }
81
82
  ]
82
83
  },
83
- {
84
- content: '{underline https://www.contrastsecurity.com/developer/codesec}'
85
- }
84
+ (0, commonHelp_1.commonHelpLinks)()
86
85
  ]);
87
86
  exports.lambdaUsageGuide = lambdaUsageGuide;
@@ -23,6 +23,7 @@ const oraWrapper_1 = __importDefault(require("../utils/oraWrapper"));
23
23
  const analytics_1 = require("./analytics");
24
24
  const types_1 = require("./types");
25
25
  const constants_2 = require("../constants/constants");
26
+ const chalk_1 = __importDefault(require("chalk"));
26
27
  const failedStates = [
27
28
  'UNSUPPORTED',
28
29
  'EXCLUDED',
@@ -109,6 +110,7 @@ const processLambda = async (argv) => {
109
110
  }
110
111
  await (0, analytics_1.postAnalytics)(endCommandAnalytics).catch((error) => {
111
112
  });
113
+ postRunMessage();
112
114
  if (errorMsg) {
113
115
  process.exit(1);
114
116
  }
@@ -191,3 +193,8 @@ const handleLambdaHelp = () => {
191
193
  printHelpMessage();
192
194
  process.exit(0);
193
195
  };
196
+ const postRunMessage = () => {
197
+ console.log('\n' + chalk_1.default.underline.bold('Other Codesec Features:'));
198
+ console.log("'contrast scan' to run CodeSec’s industry leading SAST scanner");
199
+ console.log("'contrast audit' to find vulnerabilities in your open source dependencies\n");
200
+ };
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ const parseDependenciesForSCAServices = dependencyTreeObject => {
3
+ let parsedDependencyTree = {};
4
+ let subDeps;
5
+ for (let tree in dependencyTreeObject) {
6
+ let unParsedDependencyTree = dependencyTreeObject[tree];
7
+ for (let dependency in unParsedDependencyTree) {
8
+ subDeps = parseSubDependencies(unParsedDependencyTree[dependency].edges);
9
+ let parsedDependency = {
10
+ name: unParsedDependencyTree[dependency].artifactID,
11
+ group: unParsedDependencyTree[dependency].group,
12
+ version: unParsedDependencyTree[dependency].version,
13
+ directDependency: unParsedDependencyTree[dependency].type === 'direct',
14
+ isProduction: true,
15
+ dependencies: subDeps
16
+ };
17
+ parsedDependencyTree[dependency] = parsedDependency;
18
+ }
19
+ }
20
+ return parsedDependencyTree;
21
+ };
22
+ const parseSubDependencies = dependencies => {
23
+ let subDeps = [];
24
+ for (let x in dependencies) {
25
+ subDeps.push(dependencies[x]);
26
+ }
27
+ return subDeps;
28
+ };
29
+ module.exports = {
30
+ parseDependenciesForSCAServices,
31
+ parseSubDependencies
32
+ };
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ const commonApi = require('../../utils/commonApi');
3
+ const { APP_VERSION } = require('../../constants/constants');
4
+ const requestUtils = require('../../utils/requestUtils');
5
+ const scaTreeUpload = async (analysis, config) => {
6
+ const requestBody = {
7
+ applicationId: config.applicationId,
8
+ dependencyTree: analysis,
9
+ organizationId: config.organizationId,
10
+ language: 'NODE',
11
+ tool: {
12
+ name: 'Contrast Codesec',
13
+ version: APP_VERSION
14
+ }
15
+ };
16
+ const client = commonApi.getHttpClient(config);
17
+ const reportID = await client
18
+ .scaServiceIngest(requestBody, config)
19
+ .then(res => {
20
+ if (res.statusCode === 201) {
21
+ return res.body.libraryIngestJobId;
22
+ }
23
+ else {
24
+ throw new Error(res.statusCode + ` error ingesting dependencies`);
25
+ }
26
+ })
27
+ .catch(err => {
28
+ throw err;
29
+ });
30
+ let keepChecking = true;
31
+ while (keepChecking) {
32
+ keepChecking = await client
33
+ .scaServiceReportStatus(config, reportID)
34
+ .then(res => {
35
+ console.log(res.body);
36
+ if (res.body.status == 'COMPLETED') {
37
+ client.scaServiceReport(config, reportID).then(res => {
38
+ console.log(res.statusCode);
39
+ console.log(res.body);
40
+ });
41
+ return (keepChecking = false);
42
+ }
43
+ else {
44
+ return (keepChecking = true);
45
+ }
46
+ });
47
+ await requestUtils.sleep(5000);
48
+ }
49
+ };
50
+ module.exports = {
51
+ scaTreeUpload
52
+ };
@@ -2,11 +2,14 @@
2
2
  const commonApi = require('../../utils/commonApi');
3
3
  const { APP_VERSION } = require('../../constants/constants');
4
4
  const commonSendSnapShot = async (analysis, config) => {
5
- const requestBody = {
6
- appID: config.applicationId,
7
- cliVersion: APP_VERSION,
8
- snapshot: analysis
9
- };
5
+ let requestBody = {};
6
+ config.experimental === true
7
+ ? (requestBody = sendToSCAServices(config, analysis))
8
+ : (requestBody = {
9
+ appID: config.applicationId,
10
+ cliVersion: APP_VERSION,
11
+ snapshot: analysis
12
+ });
10
13
  const client = commonApi.getHttpClient(config);
11
14
  return client
12
15
  .sendSnapshot(requestBody, config)
@@ -22,6 +25,18 @@ const commonSendSnapShot = async (analysis, config) => {
22
25
  throw err;
23
26
  });
24
27
  };
28
+ const sendToSCAServices = (config, analysis) => {
29
+ return {
30
+ applicationId: config.applicationId,
31
+ dependencyTree: analysis,
32
+ organizationId: config.organizationId,
33
+ language: config.language,
34
+ tool: {
35
+ name: 'Contrast Codesec',
36
+ version: APP_VERSION
37
+ }
38
+ };
39
+ };
25
40
  module.exports = {
26
41
  commonSendSnapShot
27
42
  };
@@ -31,13 +31,25 @@ const readAndParseLockFile = lockFilePath => {
31
31
  }
32
32
  return lockFile;
33
33
  };
34
+ const checkForCorrectFiles = languageFiles => {
35
+ if (!languageFiles.includes('packages.lock.json')) {
36
+ throw new Error(i18n.__('languageAnalysisHasNoLockFile', '.NET'));
37
+ }
38
+ if (!languageFiles.some(i => i.includes('.csproj'))) {
39
+ throw new Error(i18n.__('languageAnalysisProjectFileError', '.NET'));
40
+ }
41
+ };
34
42
  const getDotNetDeps = (filePath, languageFiles) => {
35
- const projectFile = readAndParseProjectFile(filePath + `/${languageFiles[0]}`);
36
- const lockFile = readAndParseLockFile(filePath + `/${languageFiles[1]}`);
43
+ checkForCorrectFiles(languageFiles);
44
+ const projectFileName = languageFiles.find(fileName => fileName.includes('.csproj'));
45
+ const lockFileName = languageFiles.find(fileName => fileName.includes('.json'));
46
+ const projectFile = readAndParseProjectFile(filePath + `/${projectFileName}`);
47
+ const lockFile = readAndParseLockFile(filePath + `/${lockFileName}`);
37
48
  return { projectFile, lockFile };
38
49
  };
39
50
  module.exports = {
40
51
  getDotNetDeps,
41
52
  readAndParseProjectFile,
42
- readAndParseLockFile
53
+ readAndParseLockFile,
54
+ checkForCorrectFiles
43
55
  };
@@ -1,12 +1,18 @@
1
1
  "use strict";
2
2
  const { createGoTSMessage } = require('../common/formatMessage');
3
+ const { parseDependenciesForSCAServices } = require('../common/scaParserForGoAndJava');
3
4
  const goReadDepFile = require('./goReadDepFile');
4
5
  const goParseDeps = require('./goParseDeps');
5
- const goAnalysis = (config, languageFiles) => {
6
+ const goAnalysis = config => {
6
7
  try {
7
8
  const rawGoDependencies = goReadDepFile.getGoDependencies(config);
8
9
  const parsedGoDependencies = goParseDeps.parseGoDependencies(rawGoDependencies);
9
- return createGoTSMessage(parsedGoDependencies);
10
+ if (config.experimental) {
11
+ return parseDependenciesForSCAServices(parsedGoDependencies);
12
+ }
13
+ else {
14
+ return createGoTSMessage(parsedGoDependencies);
15
+ }
10
16
  }
11
17
  catch (e) {
12
18
  console.log(e.message.toString());
@@ -5,17 +5,20 @@ const i18n = require('i18n');
5
5
  const fs = require('fs');
6
6
  const MAVEN = 'maven';
7
7
  const GRADLE = 'gradle';
8
- const determineProjectTypeAndCwd = (files, file) => {
8
+ const determineProjectTypeAndCwd = (files, config) => {
9
9
  const projectData = {};
10
+ if (files.length > 1) {
11
+ files = files.filter(i => config.fileName.includes(i));
12
+ }
10
13
  if (files[0].includes('pom.xml')) {
11
14
  projectData.projectType = MAVEN;
12
15
  }
13
16
  else if (files[0].includes('build.gradle')) {
14
17
  projectData.projectType = GRADLE;
15
18
  }
16
- projectData.cwd = file
17
- ? file.replace('pom.xml', '').replace('build.gradle', '')
18
- : file;
19
+ projectData.cwd = config.file
20
+ ? config.file.replace('pom.xml', '').replace('build.gradle', '')
21
+ : config.file;
19
22
  return projectData;
20
23
  };
21
24
  const buildMaven = (config, projectData, timeout) => {
@@ -86,7 +89,7 @@ const getJavaBuildDeps = (config, files) => {
86
89
  projectType: undefined
87
90
  };
88
91
  try {
89
- const projectData = determineProjectTypeAndCwd(files, config.file);
92
+ const projectData = determineProjectTypeAndCwd(files, config);
90
93
  if (projectData.projectType === MAVEN) {
91
94
  output.mvnDependancyTreeOutput = buildMaven(config, projectData, timeout);
92
95
  }
@@ -101,5 +104,6 @@ const getJavaBuildDeps = (config, files) => {
101
104
  }
102
105
  };
103
106
  module.exports = {
104
- getJavaBuildDeps
107
+ getJavaBuildDeps,
108
+ determineProjectTypeAndCwd
105
109
  };
@@ -2,12 +2,18 @@
2
2
  const analysis = require('./analysis');
3
3
  const { parseBuildDeps } = require('./javaBuildDepsParser');
4
4
  const { createJavaTSMessage } = require('../common/formatMessage');
5
+ const { parseDependenciesForSCAServices } = require('../common/scaParserForGoAndJava');
5
6
  const javaAnalysis = (config, languageFiles) => {
6
7
  languageFiles.JAVA.forEach(file => {
7
8
  file.replace('build.gradle.kts', 'build.gradle');
8
9
  });
9
10
  const javaDeps = buildJavaTree(config, languageFiles.JAVA);
10
- return createJavaTSMessage(javaDeps);
11
+ if (config.experimental) {
12
+ return parseDependenciesForSCAServices(javaDeps);
13
+ }
14
+ else {
15
+ return createJavaTSMessage(javaDeps);
16
+ }
11
17
  };
12
18
  const buildJavaTree = (config, files) => {
13
19
  const javaBuildDeps = analysis.getJavaBuildDeps(config, files);
@@ -14,13 +14,12 @@ const parseBuildDeps = (config, input) => {
14
14
  const preParser = shavedOutput => {
15
15
  let obj = [];
16
16
  for (let dep in shavedOutput) {
17
+ shavedOutput[dep] = shaveDependencyType(shavedOutput[dep]);
17
18
  obj.push(shavedOutput[dep]
18
19
  .replace('+-', '+---')
19
20
  .replace('[INFO]', '')
20
21
  .replace('\\-', '\\---')
21
22
  .replace(':jar:', ':')
22
- .replace(':test', '')
23
- .replace(':compile', '')
24
23
  .replace(' +', '+')
25
24
  .replace(' |', '|')
26
25
  .replace(' \\', '\\')
@@ -50,6 +49,21 @@ const preParser = shavedOutput => {
50
49
  }
51
50
  return depTree;
52
51
  };
52
+ const shaveDependencyType = dep => {
53
+ if (dep.endsWith('\r')) {
54
+ dep = dep.slice(0, -1);
55
+ }
56
+ if (dep.endsWith(':test')) {
57
+ dep = dep.slice(0, -5);
58
+ }
59
+ if (dep.endsWith(':compile')) {
60
+ dep = dep.slice(0, -8);
61
+ }
62
+ if (dep.endsWith(':provided')) {
63
+ dep = dep.slice(0, -9);
64
+ }
65
+ return dep;
66
+ };
53
67
  const shaveOutput = (gradleDependencyTreeOutput, projectType) => {
54
68
  let shavedOutput = gradleDependencyTreeOutput.split('\n');
55
69
  if (projectType === 'maven') {
@@ -335,5 +349,7 @@ module.exports = {
335
349
  computeRelationToLastElement,
336
350
  addIndentation,
337
351
  computeLevel,
338
- computeIndentation
352
+ computeIndentation,
353
+ shaveDependencyType,
354
+ preParser
339
355
  };
@@ -2,6 +2,7 @@
2
2
  const analysis = require('./analysis');
3
3
  const i18n = require('i18n');
4
4
  const formatMessage = require('../common/formatMessage');
5
+ const scaServiceParser = require('./scaServiceParser');
5
6
  const jsAnalysis = async (config, languageFiles) => {
6
7
  checkForCorrectFiles(languageFiles);
7
8
  if (!config.file.endsWith('/')) {
@@ -12,6 +13,9 @@ const jsAnalysis = async (config, languageFiles) => {
12
13
  const buildNodeTree = async (config, files) => {
13
14
  let analysis = await readFiles(config, files);
14
15
  const rawNode = await parseFiles(config, files, analysis);
16
+ if (config.experimental) {
17
+ return scaServiceParser.parseJS(rawNode);
18
+ }
15
19
  return formatMessage.createJavaScriptTSMessage(rawNode);
16
20
  };
17
21
  const readFiles = async (config, files) => {