@contrast/contrast 1.0.1 → 1.0.4

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 (94) hide show
  1. package/.prettierignore +2 -0
  2. package/README.md +103 -133
  3. package/dist/audit/languageAnalysisEngine/{langugageAnalysisFactory.js → languageAnalysisFactory.js} +26 -11
  4. package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +62 -234
  5. package/dist/audit/languageAnalysisEngine/report/models/reportLibraryModel.js +19 -0
  6. package/dist/audit/languageAnalysisEngine/report/models/reportListModel.js +24 -0
  7. package/dist/audit/languageAnalysisEngine/report/models/reportSeverityModel.js +10 -0
  8. package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +24 -129
  9. package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +85 -0
  10. package/dist/audit/languageAnalysisEngine/sendSnapshot.js +3 -1
  11. package/dist/commands/audit/auditController.js +6 -3
  12. package/dist/commands/audit/saveFile.js +11 -0
  13. package/dist/commands/auth/auth.js +19 -1
  14. package/dist/commands/config/config.js +19 -8
  15. package/dist/commands/scan/processScan.js +8 -25
  16. package/dist/common/HTTPClient.js +30 -26
  17. package/dist/common/errorHandling.js +17 -1
  18. package/dist/common/versionChecker.js +32 -0
  19. package/dist/constants/constants.js +4 -2
  20. package/dist/constants/lambda.js +3 -1
  21. package/dist/constants/locales.js +41 -18
  22. package/dist/constants.js +39 -3
  23. package/dist/index.js +49 -28
  24. package/dist/lambda/help.js +22 -14
  25. package/dist/lambda/lambda.js +6 -0
  26. package/dist/sbom/generateSbom.js +20 -0
  27. package/dist/scan/help.js +4 -2
  28. package/dist/scan/models/groupedResultsModel.js +10 -0
  29. package/dist/scan/models/resultContentModel.js +2 -0
  30. package/dist/scan/models/scanResultsModel.js +11 -0
  31. package/dist/scan/populateProjectIdAndProjectName.js +1 -0
  32. package/dist/scan/saveResults.js +9 -10
  33. package/dist/scan/scan.js +99 -74
  34. package/dist/scan/scanConfig.js +20 -1
  35. package/dist/scan/scanController.js +7 -2
  36. package/dist/scan/scanResults.js +6 -0
  37. package/dist/utils/getConfig.js +3 -0
  38. package/dist/utils/paramsUtil/commandlineParams.js +1 -1
  39. package/dist/utils/requestUtils.js +1 -1
  40. package/dist/utils/saveFile.js +19 -0
  41. package/package.json +2 -2
  42. package/src/audit/languageAnalysisEngine/{langugageAnalysisFactory.js → languageAnalysisFactory.js} +33 -15
  43. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +127 -0
  44. package/src/audit/languageAnalysisEngine/report/models/reportLibraryModel.ts +30 -0
  45. package/src/audit/languageAnalysisEngine/report/models/reportListModel.ts +32 -0
  46. package/src/audit/languageAnalysisEngine/report/models/reportSeverityModel.ts +9 -0
  47. package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +56 -0
  48. package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +110 -0
  49. package/src/audit/languageAnalysisEngine/sendSnapshot.js +3 -1
  50. package/src/commands/audit/auditController.ts +12 -3
  51. package/src/commands/audit/processAudit.ts +0 -1
  52. package/src/commands/audit/saveFile.ts +6 -0
  53. package/src/commands/auth/auth.js +25 -1
  54. package/src/commands/config/config.js +22 -8
  55. package/src/commands/scan/processScan.js +8 -29
  56. package/src/common/HTTPClient.js +42 -36
  57. package/src/common/errorHandling.ts +29 -2
  58. package/src/common/versionChecker.ts +41 -0
  59. package/src/constants/constants.js +5 -4
  60. package/src/constants/lambda.js +3 -1
  61. package/src/constants/locales.js +51 -19
  62. package/src/constants.js +44 -3
  63. package/src/index.ts +63 -31
  64. package/src/lambda/help.ts +22 -14
  65. package/src/lambda/lambda.ts +8 -0
  66. package/src/sbom/generateSbom.ts +17 -0
  67. package/src/scan/help.js +4 -2
  68. package/src/scan/models/groupedResultsModel.ts +18 -0
  69. package/src/scan/models/resultContentModel.ts +86 -0
  70. package/src/scan/models/scanResultsModel.ts +52 -0
  71. package/src/scan/populateProjectIdAndProjectName.js +1 -0
  72. package/src/scan/saveResults.js +8 -9
  73. package/src/scan/scan.ts +192 -0
  74. package/src/scan/scanConfig.js +26 -1
  75. package/src/scan/scanController.js +11 -2
  76. package/src/scan/scanResults.js +11 -0
  77. package/src/utils/getConfig.ts +12 -0
  78. package/src/utils/paramsUtil/commandlineParams.js +1 -1
  79. package/src/utils/requestUtils.js +1 -1
  80. package/src/utils/saveFile.js +19 -0
  81. package/dist/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +0 -17
  82. package/dist/audit/languageAnalysisEngine/report/newReportingFeature.js +0 -81
  83. package/dist/common/findLatestCLIVersion.js +0 -23
  84. package/dist/lambda/scanDetail.js +0 -30
  85. package/dist/scan/fileFinder.js +0 -15
  86. package/dist/utils/fileUtils.js +0 -31
  87. package/dist/utils/paramsUtil/genericCommandLineParams.js +0 -12
  88. package/dist/utils/paramsUtil/yamlParams.js +0 -6
  89. package/src/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +0 -27
  90. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.js +0 -303
  91. package/src/audit/languageAnalysisEngine/report/newReportingFeature.js +0 -124
  92. package/src/audit/languageAnalysisEngine/report/reportingFeature.js +0 -190
  93. package/src/common/findLatestCLIVersion.ts +0 -27
  94. package/src/scan/scan.js +0 -162
@@ -1,4 +1,5 @@
1
1
  const { lambda } = require('./lambda')
2
+ const chalk = require('chalk')
2
3
 
3
4
  const en_locales = () => {
4
5
  return {
@@ -13,8 +14,6 @@ const en_locales = () => {
13
14
  vulnerabilitiesSuccessMessage: ' Vulnerability data successfully retrieved',
14
15
  vulnerabilitiesFailureMessage:
15
16
  ' Unable to retrieve library vulnerabilities from Team Server.',
16
- reportSuccessMessage: ' Report successfully retrieved',
17
- reportFailureMessage: ' Unable to generate library report.',
18
17
  catchErrorMessage: 'Contrast UI error: ',
19
18
  dependenciesNote:
20
19
  'Please Note: We currently only support projects with one .csproj AND *.package.lock.json',
@@ -171,13 +170,19 @@ const en_locales = () => {
171
170
  constantsSeverity:
172
171
  '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.',
173
172
  constantsCount: "The number of CVE's that must be exceeded to fail a build",
174
- constantsHeader: 'Contrast CLI',
173
+ constantsHeader: 'CodeSec by Contrast Security',
175
174
  constantsPrerequisitesContentScanLanguages: 'Java & JavaScript supported',
176
175
  constantsContrastContent:
177
- 'Use the Contrast CLI, the fastest and most accurate code scan, to help find and eliminate security bugs in your code.',
176
+ '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.',
178
177
  constantsUsageGuideContentRecommendation:
179
178
  '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.',
180
179
  constantsPrerequisitesHeader: 'Pre-requisites',
180
+ constantsAuthUsageHeader: 'Usage',
181
+ constantsAuthUsageContents: 'contrast auth',
182
+ constantsAuthHeaderContents:
183
+ 'Authorize with external identity provider to perform scans on code',
184
+ configHeader: 'Config',
185
+ constantsConfigUsageContents: 'view / clear the configuration',
181
186
  constantsPrerequisitesContent:
182
187
  'To scan a Java project you will need a .jar or .war file for analysis\n' +
183
188
  'To scan a Javascript project you will need a .js or.zip file for analysis\n' +
@@ -185,7 +190,7 @@ const en_locales = () => {
185
190
  constantsUsage: 'Usage',
186
191
  constantsUsageCommandExample: 'contrast [command] [options]',
187
192
  constantsUsageCommandInfo:
188
- 'The file argument is optional. If no file is given, Contrast will search for a .jar, .war, .js, .exe or .zip file in the working directory.\n',
193
+ 'The file argument is optional. If no file is given, Contrast will search for a .jar, .war, .exe or .zip file in the working directory.\n',
189
194
  constantsUsageCommandInfo24Hours:
190
195
  'Submitted files are encrypted during upload and deleted in 24 hours.',
191
196
  constantsAnd: 'AND',
@@ -267,7 +272,9 @@ const en_locales = () => {
267
272
  'Add the application code this application should use in the Contrast UI',
268
273
  constantsIgnoreCertErrors:
269
274
  ' For EOP users with a local Teamserver install, this will bypass the SSL certificate and recognise a self signed certificate.',
270
- constantsSave: ' Saves the Scan Results JSON to file.',
275
+ constantsSave: ' Saves the Scan Results SARIF to file.',
276
+ scanLabel:
277
+ "adds a label to the scan - defaults to 'Started by CLI tool at current date'",
271
278
  constantsIgnoreDev:
272
279
  'Combined with the --report command excludes developer dependencies from the vulnerabilities report. By default all dependencies are included in a report.',
273
280
  constantsCommands: 'Commands',
@@ -277,7 +284,7 @@ const en_locales = () => {
277
284
  ignoreDevDep: 'No private libraries that are not scoped detected',
278
285
  foundExistingProjectScan: 'Found existing project...',
279
286
  projectCreatedScan: 'Project created',
280
- uploadingScan: 'Uploading...',
287
+ uploadingScan: 'Uploading file to scan.',
281
288
  uploadingScanSuccessful: 'Uploaded file successfully.',
282
289
  uploadingScanFail: 'Unable to upload the file.',
283
290
  waitingTimedOut: 'Timed out.',
@@ -288,14 +295,15 @@ const en_locales = () => {
288
295
  specifyFileScanError:
289
296
  'Java Scan requires a .war or .jar file. Javascript Scan requires a .js or .zip file.\nTo start a Scan enter "contrast scan -f <path-to-file>"',
290
297
  populateProjectIdMessage: 'project ID is %s',
298
+ genericServiceError: 'returned with status code %s',
299
+ projectIdError: 'Your project ID is %s please check this is correct',
291
300
  permissionsError:
292
301
  'You do not have the correct permissions here. \n Contact support@contrastsecurity.com to get this fixed.',
293
302
  scanErrorFileMessage:
294
303
  'We only accept the following file types: \nJava - .jar, .war \nJavaScript - .js or .zip files',
295
304
  helpAuthSummary:
296
305
  'Authenticate Contrast using your Github or Google account',
297
- helpScanSummary:
298
- 'Searches for a .jar, .war, .js or .zip file in the working directory, uploads for analysis and returns the results',
306
+ helpScanSummary: 'Perform static analysis on binaries / code artifacts',
299
307
  helpLambdaSummary: 'Perform scan on AWS Lambda functions',
300
308
  helpVersionSummary: 'Displays version of Contrast CLI',
301
309
  helpConfigSummary: 'Displays stored credentials',
@@ -306,6 +314,7 @@ const en_locales = () => {
306
314
  versionName: 'version',
307
315
  configName: 'config',
308
316
  helpName: 'help',
317
+ scanOptionsLanguageSummary: 'Valid values are JAVA, JAVASCRIPT and DOTNET',
309
318
  scanOptionsLanguageSummaryOptional:
310
319
  'Language of file to send for analysis. ',
311
320
  scanOptionsLanguageSummaryRequired:
@@ -313,30 +322,41 @@ const en_locales = () => {
313
322
  scanOptionsTimeoutSummary:
314
323
  'Time in seconds to wait for scan to complete. Default value is 300 seconds.',
315
324
  scanOptionsFileNameSummary:
316
- 'Path of the file you want to scan. If no file is specified, Contrast searches for a .jar, .war, .js, .exe or .zip file in the working directory.',
325
+ '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.',
317
326
  scanOptionsVerboseSummary: ' Returns extended information to the terminal.',
318
327
  authSuccessMessage: 'Authentication successful',
319
- runAuthSuccessMessage: 'Now you can use Contrast CLI',
328
+ runAuthSuccessMessage:
329
+ "Now you can use Contrast CLI \nRun 'contrast scan' on your file \n" +
330
+ "or 'contrast help' to learn more about the capabilities.",
320
331
  authWaitingMessage: 'Waiting for auth...',
321
332
  authTimedOutMessage: 'Auth Timed out, try again',
322
333
  zipErrorScan:
323
334
  'We only support zip files for JAVASCRIPT language, please set the flag --language JAVASCRIPT',
324
335
  unknownFileErrorScan: 'Unsupported file selected for Scan.',
325
- foundScanFile: 'found: %s',
336
+ foundScanFile: 'Found: %s',
326
337
  foundDetailedVulnerabilities:
327
- '%s Critical %s High %s Medium %s Low %s Note',
338
+ chalk.bold('%s Critical') +
339
+ ' | ' +
340
+ chalk.bold('%s High') +
341
+ ' | %s Medium | %s Low | %s Note',
328
342
  requiredParams: 'All required parameters are not present.',
329
343
  timeoutScan: 'Timeout set to 5 minutes.',
330
344
  searchingScanFileDirectory: 'Searching for file to scan from %s...',
331
345
  scanHeader: 'Contrast Scan CLI',
332
- lambdaHeader: 'Contrast lambda help',
346
+ authHeader: 'Auth',
347
+ lambdaHeader: 'Contrast Lambda CLI',
333
348
  lambdaSummary:
334
349
  'Performs static security scan on an AWS Lambda Function.\nProduces CVE (Vulnerable Dependencies) and Least Privilege violations/remediation results.',
335
350
  lambdaUsage: 'contrast lambda --function-name <function> [options]',
336
- lambdaPrerequisitesContent: 'contrast cli',
337
- scanFileNameOption: ' -f, --file',
338
- lambdaFunctionNameOption: ' -f, --function-name',
339
- lambdaListFunctionsOption: ' -l, --list-functions',
351
+ lambdaPrerequisitesContent: '',
352
+ lambdaPrerequisitesContentLambdaLanguages:
353
+ 'Supported runtimes: Java & Python',
354
+ lambdaPrerequisitesContentLambdaDescriptionTitle: 'AWS Requirements\n',
355
+ lambdaPrerequisitesContentLambdaDescription:
356
+ 'Make sure you have the AWS credentials configured on your local environment. \nYou need the following AWS permissions configured on your IAM user:\n - Lambda: GetFunction, GetLayerVersionֿ\n - IAM: GetRolePolicy, GetPolicy, GetPolicyVersion, ListRolePolicies, ListAttachedRolePolicies',
357
+ scanFileNameOption: '-f, --file',
358
+ lambdaFunctionNameOption: '-f, --function-name',
359
+ lambdaListFunctionsOption: '-l, --list-functions',
340
360
  lambdaEndpointOption: '-e, --endpoint-url',
341
361
  lambdaRegionOption: '-r, --region',
342
362
  lambdaProfileOption: '-p, --profile',
@@ -399,7 +419,19 @@ const en_locales = () => {
399
419
  'saves the output in specified format Txt text, sbom',
400
420
  scanNoVulnerabilitiesFound: '👏 No vulnerabilities found',
401
421
  scanNoFiletypeSpecifiedForSave:
402
- 'Please specify file type to save results to',
422
+ 'Please specify file type to save results to, accepted value is SARIF',
423
+ auditSBOMSaveSuccess:
424
+ '\n Software Bill of Materials (SBOM) saved successfully',
425
+ auditNoFiletypeSpecifiedForSave: `\n ${chalk.yellow.bold(
426
+ 'No file type specified for --save option to save audit results to. Use audit --help to see valid --save options.'
427
+ )}`,
428
+ auditBadFiletypeSpecifiedForSave: `\n ${chalk.yellow.bold(
429
+ 'Bad file type specified for --save option. Use audit --help to see valid --save options.'
430
+ )}`,
431
+ auditReportWaiting: 'Waiting for report...',
432
+ auditReportFail: 'Report Retrieval Failed, please try again',
433
+ auditReportSuccessMessage: ' Report successfully retrieved',
434
+ auditReportFailureMessage: ' Unable to generate library report.',
403
435
  ...lambda
404
436
  }
405
437
  }
package/src/constants.js CHANGED
@@ -20,6 +20,15 @@ const scanOptionDefinitions = [
20
20
  '}: ' +
21
21
  i18n.__('constantsProjectName')
22
22
  },
23
+ {
24
+ name: 'language',
25
+ alias: 'l',
26
+ description:
27
+ '{bold ' +
28
+ i18n.__('constantsOptional') +
29
+ '}: ' +
30
+ i18n.__('scanOptionsLanguageSummary')
31
+ },
23
32
  {
24
33
  name: 'file',
25
34
  alias: 'f',
@@ -75,7 +84,6 @@ const scanOptionDefinitions = [
75
84
  },
76
85
  {
77
86
  name: 'host',
78
- alias: 'h',
79
87
  description:
80
88
  '{bold ' +
81
89
  i18n.__('constantsRequired') +
@@ -124,8 +132,14 @@ const scanOptionDefinitions = [
124
132
  description:
125
133
  '{bold ' + i18n.__('constantsOptional') + '}:' + i18n.__('constantsSave')
126
134
  },
135
+ {
136
+ name: 'label',
137
+ description:
138
+ '{bold ' + i18n.__('constantsOptional') + '}:' + i18n.__('scanLabel')
139
+ },
127
140
  {
128
141
  name: 'help',
142
+ alias: 'h',
129
143
  type: Boolean
130
144
  },
131
145
  {
@@ -135,6 +149,29 @@ const scanOptionDefinitions = [
135
149
  }
136
150
  ]
137
151
 
152
+ const authOptionDefinitions = [
153
+ {
154
+ name: 'help',
155
+ alias: 'h',
156
+ type: Boolean
157
+ }
158
+ ]
159
+
160
+ const configOptionDefinitions = [
161
+ {
162
+ name: 'help',
163
+ alias: 'h',
164
+ type: Boolean,
165
+ description: 'Help text'
166
+ },
167
+ {
168
+ name: 'clear',
169
+ alias: 'c',
170
+ type: Boolean,
171
+ description: 'Clear the currently stored config'
172
+ }
173
+ ]
174
+
138
175
  const auditOptionDefinitions = [
139
176
  {
140
177
  name: 'application-id',
@@ -291,6 +328,7 @@ const mainUsageGuide = commandLineUsage([
291
328
  header: i18n.__('constantsCommands'),
292
329
  content: [
293
330
  { name: i18n.__('authName'), summary: i18n.__('helpAuthSummary') },
331
+ { name: i18n.__('scanName'), summary: i18n.__('helpScanSummary') },
294
332
  { name: i18n.__('lambdaName'), summary: i18n.__('helpLambdaSummary') },
295
333
  { name: i18n.__('versionName'), summary: i18n.__('helpVersionSummary') },
296
334
  { name: i18n.__('configName'), summary: i18n.__('helpConfigSummary') },
@@ -298,7 +336,8 @@ const mainUsageGuide = commandLineUsage([
298
336
  ]
299
337
  },
300
338
  {
301
- content: '{underline https://www.contrastsecurity.com}'
339
+ content:
340
+ '{underline https://developer.contrastsecurity.com/} \n For technical support head to {underline https://support.contrastsecurity.com}'
302
341
  }
303
342
  ])
304
343
 
@@ -309,6 +348,8 @@ module.exports = {
309
348
  mainUsageGuide,
310
349
  mainDefinition,
311
350
  scanOptionDefinitions,
312
- auditOptionDefinitions
351
+ auditOptionDefinitions,
352
+ authOptionDefinitions,
353
+ configOptionDefinitions
313
354
  }
314
355
  }
package/src/index.ts CHANGED
@@ -7,7 +7,11 @@ import constants from './constants'
7
7
  import { APP_NAME, APP_VERSION } from './constants/constants'
8
8
  import { processLambda } from './lambda/lambda'
9
9
  import { localConfig } from './utils/getConfig'
10
- import findLatestCLIVersion from './common/findLatestCLIVersion'
10
+ import {
11
+ findLatestCLIVersion,
12
+ isCorrectNodeVersion
13
+ } from './common/versionChecker'
14
+ import { findCommandOnError } from './common/errorHandling'
11
15
 
12
16
  const {
13
17
  commandLineDefinitions: { mainUsageGuide, mainDefinition }
@@ -30,46 +34,74 @@ const getMainOption = () => {
30
34
  }
31
35
 
32
36
  const start = async () => {
33
- const { mainOptions, argv: argvMain } = getMainOption()
34
- const command =
35
- mainOptions.command != undefined ? mainOptions.command.toLowerCase() : ''
36
- if (command === 'version') {
37
- console.log(APP_VERSION)
38
- return
39
- }
37
+ if (await isCorrectNodeVersion(process.version)) {
38
+ const { mainOptions, argv: argvMain } = getMainOption()
39
+ const command =
40
+ mainOptions.command != undefined ? mainOptions.command.toLowerCase() : ''
41
+ if (
42
+ command === 'version' ||
43
+ argvMain.includes('--v') ||
44
+ argvMain.includes('--version')
45
+ ) {
46
+ console.log(APP_VERSION)
47
+ await findLatestCLIVersion(config.get('updateMessageHidden') as boolean)
48
+ return
49
+ }
40
50
 
41
- await findLatestCLIVersion()
51
+ // @ts-ignore
52
+ config.set('numOfRuns', config.get('numOfRuns') + 1)
42
53
 
43
- if (command === 'config') {
44
- return processConfig(argvMain, config)
45
- }
54
+ // @ts-ignore
55
+ if (config.get('numOfRuns') >= 5) {
56
+ await findLatestCLIVersion(config.get('updateMessageHidden') as boolean)
57
+ config.set('numOfRuns', 0)
58
+ }
46
59
 
47
- if (command === 'auth') {
48
- return await processAuth(config)
49
- }
60
+ if (command === 'config') {
61
+ return processConfig(argvMain, config)
62
+ }
50
63
 
51
- if (command === 'lambda') {
52
- return await processLambda(argvMain)
53
- }
64
+ if (command === 'auth') {
65
+ return await processAuth(argvMain, config)
66
+ }
54
67
 
55
- if (command === 'scan') {
56
- return await processScan(argvMain)
57
- }
68
+ if (command === 'lambda') {
69
+ return await processLambda(argvMain)
70
+ }
58
71
 
59
- if (command === 'audit') {
60
- return await processAudit(argvMain)
61
- }
72
+ if (command === 'scan') {
73
+ return await processScan(argvMain)
74
+ }
75
+
76
+ if (command === 'audit') {
77
+ return await processAudit(argvMain)
78
+ }
79
+
80
+ if (
81
+ command === 'help' ||
82
+ argvMain.includes('--help') ||
83
+ Object.keys(mainOptions).length === 0
84
+ ) {
85
+ console.log(mainUsageGuide)
86
+ } else if (mainOptions._unknown !== undefined) {
87
+ const foundCommand = findCommandOnError(mainOptions._unknown)
62
88
 
63
- if (
64
- command === 'help' ||
65
- argvMain.includes('--help') ||
66
- Object.keys(mainOptions).length === 0
67
- ) {
68
- console.log(mainUsageGuide)
89
+ foundCommand
90
+ ? console.log(
91
+ `Unknown Command: Did you mean "${foundCommand}"? \nUse "${foundCommand} --help" for the full list of options`
92
+ )
93
+ : console.log(
94
+ `Unknown Command: ${command} \nUse --help for the full list`
95
+ )
96
+ } else {
97
+ console.log(`Unknown Command: ${command} \nUse --help for the full list`)
98
+ }
99
+ process.exit(9)
69
100
  } else {
70
101
  console.log(
71
- 'Unknown Command: ' + command + ' \nUse --help for the full list'
102
+ 'Contrast supports Node versions >=16.13.2 <17. Please use one of those versions.'
72
103
  )
104
+ process.exit(9)
73
105
  }
74
106
  }
75
107
 
@@ -8,7 +8,15 @@ const lambdaUsageGuide = commandLineUsage([
8
8
  },
9
9
  {
10
10
  header: i18n.__('constantsPrerequisitesHeader'),
11
- content: [i18n.__('lambdaPrerequisitesContent')]
11
+ content: [
12
+ '{bold ' +
13
+ i18n.__('lambdaPrerequisitesContentLambdaLanguages') +
14
+ '}\n\n' +
15
+ '{bold ' +
16
+ i18n.__('lambdaPrerequisitesContentLambdaDescriptionTitle') +
17
+ '}' +
18
+ i18n.__('lambdaPrerequisitesContentLambdaDescription')
19
+ ]
12
20
  },
13
21
  {
14
22
  header: i18n.__('constantsUsage'),
@@ -18,49 +26,49 @@ const lambdaUsageGuide = commandLineUsage([
18
26
  header: i18n.__('constantsOptions'),
19
27
  content: [
20
28
  {
21
- name: i18n.__('lambdaFunctionNameOption'),
29
+ name: '{bold ' + i18n.__('lambdaFunctionNameOption') + '}',
22
30
  summary: i18n.__('lambdaFunctionNameSummery')
23
31
  },
24
32
  {
25
- name: i18n.__('lambdaListFunctionsOption'),
33
+ name: '{bold ' + i18n.__('lambdaListFunctionsOption') + '}',
26
34
  summary: i18n.__('lambdaListFunctionsSummery')
27
35
  },
28
36
  {
29
- name: i18n.__('lambdaEndpointOption'),
37
+ name: '{bold ' + i18n.__('lambdaEndpointOption') + '}',
30
38
  summary:
31
- '{italic ' +
39
+ '{bold ' +
32
40
  i18n.__('constantsOptional') +
33
41
  '}: ' +
34
42
  i18n.__('lambdaEndpointSummery')
35
43
  },
36
44
  {
37
- name: i18n.__('lambdaRegionOption'),
45
+ name: '{bold ' + i18n.__('lambdaRegionOption') + '}',
38
46
  summary:
39
- '{italic ' +
47
+ '{bold ' +
40
48
  i18n.__('constantsOptional') +
41
49
  '}: ' +
42
50
  i18n.__('lambdaRegionSummery')
43
51
  },
44
52
  {
45
- name: i18n.__('lambdaProfileOption'),
53
+ name: '{bold ' + i18n.__('lambdaProfileOption') + '}',
46
54
  summary:
47
- '{italic ' +
55
+ '{bold ' +
48
56
  i18n.__('constantsOptional') +
49
57
  '}: ' +
50
58
  i18n.__('lambdaProfileSummery')
51
59
  },
52
60
  {
53
- name: i18n.__('lambdaJsonOption'),
61
+ name: '{bold ' + i18n.__('lambdaJsonOption') + '}',
54
62
  summary:
55
- '{italic ' +
63
+ '{bold ' +
56
64
  i18n.__('constantsOptional') +
57
65
  '}: ' +
58
66
  i18n.__('lambdaJsonSummery')
59
67
  },
60
68
  {
61
- name: i18n.__('lambdaVerboseOption'),
69
+ name: '{bold ' + i18n.__('lambdaVerboseOption') + '}',
62
70
  summary:
63
- '{italic ' +
71
+ '{bold ' +
64
72
  i18n.__('constantsOptional') +
65
73
  '}: ' +
66
74
  i18n.__('lambdaVerbosSummery')
@@ -73,7 +81,7 @@ const lambdaUsageGuide = commandLineUsage([
73
81
  ]
74
82
  },
75
83
  {
76
- content: '{underline https://www.contrastsecurity.com}'
84
+ content: '{underline https://www.contrastsecurity.com/developer/codesec}'
77
85
  }
78
86
  ])
79
87
 
@@ -12,6 +12,8 @@ import { requestScanFunctionPost } from './scanRequest'
12
12
  import { getScanResults } from './scanResults'
13
13
  import { printResults } from './utils'
14
14
  import { getAllLambdas, printAvailableLambdas } from './lambdaUtils'
15
+ import { sleep } from '../utils/requestUtils'
16
+ import ora from '../utils/oraWrapper'
15
17
 
16
18
  type LambdaOptions = {
17
19
  functionName?: string
@@ -123,6 +125,12 @@ const actualProcessLambda = async (lambdaOptions: LambdaOptions) => {
123
125
  })
124
126
  }
125
127
 
128
+ // Wait to make sure we will have all the results
129
+ const startGetherResultsSpinner = ora.returnOra(i18n.__('gatherResults'))
130
+ ora.startSpinner(startGetherResultsSpinner)
131
+ await sleep(15 * 1000)
132
+ ora.succeedSpinner(startGetherResultsSpinner, 'Done gathering results')
133
+
126
134
  const resultsResponse = await getScanResults(
127
135
  auth,
128
136
  params,
@@ -0,0 +1,17 @@
1
+ import { getHttpClient } from '../utils/commonApi'
2
+
3
+ export default function generateSbom(config: any) {
4
+ const client = getHttpClient(config)
5
+ return client
6
+ .getSbom(config)
7
+ .then((res: { statusCode: number; body: any }) => {
8
+ if (res.statusCode === 200) {
9
+ return res.body
10
+ } else {
11
+ console.log('Unable to retrieve Software Bill of Materials (SBOM)')
12
+ }
13
+ })
14
+ .catch((err: any) => {
15
+ console.log(err)
16
+ })
17
+ }
package/src/scan/help.js CHANGED
@@ -21,14 +21,16 @@ const scanUsageGuide = commandLineUsage([
21
21
  optionList: constants.commandLineDefinitions.scanOptionDefinitions,
22
22
  hide: [
23
23
  'project-id',
24
- 'language',
25
24
  'organization-id',
26
25
  'api-key',
27
26
  'authorization',
28
27
  'host',
29
28
  'proxy',
29
+ 'help',
30
30
  'ff',
31
- 'ignore-cert-errors'
31
+ 'ignore-cert-errors',
32
+ 'verbose',
33
+ 'debug'
32
34
  ]
33
35
  },
34
36
  {
@@ -0,0 +1,18 @@
1
+ export class GroupedResultsModel {
2
+ ruleId: string
3
+ lineInfoSet: Set<string>
4
+ cwe?: string[]
5
+ owasp?: string[]
6
+ reference?: string[]
7
+ recommendation?: string
8
+ severity?: string
9
+ advice?: string
10
+ learn?: string[]
11
+ issue?: string
12
+ message?: string
13
+
14
+ constructor(ruleId: string) {
15
+ this.ruleId = ruleId
16
+ this.lineInfoSet = new Set<string>
17
+ }
18
+ }
@@ -0,0 +1,86 @@
1
+ type Importance = 'important' | 'essential'
2
+
3
+ interface ArtifactLocation {
4
+ uri: string
5
+ }
6
+
7
+ interface Region {
8
+ startLine: number
9
+ snippet: Snippet
10
+ }
11
+
12
+ interface Snippet {
13
+ text: string
14
+ rendered: Rendered
15
+ }
16
+
17
+ interface Rendered {
18
+ text: string
19
+ }
20
+
21
+ interface PhysicalLocation {
22
+ artifactLocation: ArtifactLocation
23
+ region: Region
24
+ }
25
+
26
+ interface LogicalLocation {
27
+ fullyQualifiedName: string
28
+ name: string
29
+ }
30
+
31
+ export interface Location {
32
+ physicalLocation: PhysicalLocation
33
+ logicalLocations?: LogicalLocation[]
34
+ }
35
+
36
+ export interface ThreadFlowLocation {
37
+ importance: Importance
38
+ location: Location
39
+ }
40
+
41
+ interface ThreadFlow {
42
+ locations: ThreadFlowLocation[]
43
+ }
44
+
45
+ interface Message {
46
+ text: string
47
+ }
48
+
49
+ export interface CodeFlow {
50
+ message: Message
51
+ threadFlows: ThreadFlow[]
52
+ }
53
+
54
+ export interface ResultContent {
55
+ message: {text: string};
56
+ id: string
57
+ organizationId: string
58
+ projectId: string
59
+ firstCreatedTime: string
60
+ ruleId: string
61
+ codeFlows: CodeFlow[]
62
+ lastSeenTime: string
63
+ locations: Location[]
64
+ name: string
65
+ description: string
66
+ recommendation: string | null
67
+ risk: string | null
68
+ category: string
69
+ confidence: string
70
+ standards: { [key: string]: string[] }
71
+ cwe: string[]
72
+ owasp: string[]
73
+ reference: string[]
74
+ sink: string
75
+ detailsTrigger: string
76
+ type: RuleType
77
+ source: string
78
+ severity: Severity
79
+ advice: string
80
+ learn: string[]
81
+ issue: string
82
+ }
83
+
84
+ export type Severity = 'critical' | 'high' | 'medium' | 'low' | 'note'
85
+
86
+ export type RuleType = 'DATA_FLOW' | 'CRYPTO' | 'CONFIG' | 'DEFAULT'
@@ -0,0 +1,52 @@
1
+ import { ResultContent } from './resultContentModel'
2
+
3
+ export class ScanResultsModel {
4
+ projectOverview: ProjectOverview
5
+ scanDetail: ScanDetail
6
+ scanResultsInstances: ScanResultsInstances
7
+
8
+ constructor(scan: any) {
9
+ this.projectOverview = scan.projectOverview as ProjectOverview
10
+ this.scanDetail = scan.scanDetail as ScanDetail
11
+ this.scanResultsInstances = scan.scanResultsInstances as ScanResultsInstances
12
+ }
13
+ }
14
+
15
+ export interface ProjectOverview {
16
+ id: string
17
+ organizationId: string
18
+ name: string
19
+ archived: boolean
20
+ language: string
21
+ critical: number
22
+ high: number
23
+ medium: number
24
+ low: number
25
+ note: number
26
+ lastScanTime: string
27
+ completedScans: number
28
+ lastScanId: string
29
+ }
30
+
31
+ export interface ScanDetail {
32
+ critical: number
33
+ high: number
34
+ medium: number
35
+ low: number
36
+ note: number
37
+ id: string
38
+ organizationId: string
39
+ projectId: string
40
+ codeArtifactId: string
41
+ status: string
42
+ createdTime: string
43
+ startedTime: string
44
+ completedTime: string
45
+ language: string
46
+ label: string
47
+ errorMessage: string
48
+ }
49
+
50
+ export interface ScanResultsInstances {
51
+ content: ResultContent[]
52
+ }