@contrast/contrast 1.0.16 → 1.0.18

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 (61) hide show
  1. package/dist/audit/catalogueApplication/catalogueApplication.js +1 -1
  2. package/dist/cliConstants.js +91 -109
  3. package/dist/commands/audit/auditConfig.js +10 -12
  4. package/dist/commands/audit/auditController.js +12 -16
  5. package/dist/commands/audit/help.js +32 -26
  6. package/dist/commands/audit/processAudit.js +16 -22
  7. package/dist/commands/audit/saveFile.js +3 -9
  8. package/dist/commands/scan/processScan.js +5 -7
  9. package/dist/commands/scan/sca/scaAnalysis.js +105 -88
  10. package/dist/common/HTTPClient.js +1 -1
  11. package/dist/common/commonHelp.js +35 -17
  12. package/dist/common/errorHandling.js +38 -57
  13. package/dist/common/versionChecker.js +24 -27
  14. package/dist/constants/constants.js +1 -1
  15. package/dist/constants/locales.js +20 -91
  16. package/dist/lambda/help.js +2 -1
  17. package/dist/lambda/lambda.js +2 -7
  18. package/dist/scaAnalysis/java/analysis.js +40 -5
  19. package/dist/scaAnalysis/java/index.js +14 -2
  20. package/dist/scan/autoDetection.js +26 -3
  21. package/dist/scan/fileUtils.js +24 -1
  22. package/dist/scan/help.js +11 -4
  23. package/dist/scan/saveResults.js +1 -1
  24. package/dist/utils/commonApi.js +16 -1
  25. package/dist/utils/generalAPI.js +1 -2
  26. package/dist/utils/paramsUtil/configStoreParams.js +12 -1
  27. package/dist/utils/paramsUtil/paramHandler.js +7 -1
  28. package/dist/utils/saveFile.js +2 -1
  29. package/package.json +2 -1
  30. package/src/audit/catalogueApplication/catalogueApplication.js +1 -1
  31. package/src/cliConstants.js +96 -116
  32. package/src/commands/audit/auditConfig.js +19 -0
  33. package/src/commands/audit/{auditController.ts → auditController.js} +17 -12
  34. package/src/commands/audit/{help.ts → help.js} +19 -7
  35. package/src/commands/audit/processAudit.js +37 -0
  36. package/src/commands/audit/{saveFile.ts → saveFile.js} +2 -2
  37. package/src/commands/scan/processScan.js +4 -10
  38. package/src/commands/scan/sca/scaAnalysis.js +135 -115
  39. package/src/common/HTTPClient.js +1 -1
  40. package/src/common/commonHelp.js +43 -0
  41. package/src/common/{errorHandling.ts → errorHandling.js} +25 -32
  42. package/src/common/{versionChecker.ts → versionChecker.js} +15 -10
  43. package/src/constants/constants.js +1 -1
  44. package/src/constants/locales.js +23 -129
  45. package/src/lambda/help.ts +2 -1
  46. package/src/lambda/lambda.ts +2 -10
  47. package/src/scaAnalysis/java/analysis.js +43 -10
  48. package/src/scaAnalysis/java/index.js +19 -2
  49. package/src/scan/autoDetection.js +34 -3
  50. package/src/scan/fileUtils.js +29 -1
  51. package/src/scan/help.js +12 -4
  52. package/src/scan/saveResults.js +1 -1
  53. package/src/utils/commonApi.js +19 -1
  54. package/src/utils/generalAPI.js +1 -2
  55. package/src/utils/getConfig.ts +1 -0
  56. package/src/utils/paramsUtil/configStoreParams.js +14 -1
  57. package/src/utils/paramsUtil/paramHandler.js +9 -1
  58. package/src/utils/saveFile.js +2 -1
  59. package/src/commands/audit/auditConfig.ts +0 -21
  60. package/src/commands/audit/processAudit.ts +0 -40
  61. package/src/common/commonHelp.ts +0 -13
@@ -3,23 +3,13 @@ const chalk = require('chalk')
3
3
 
4
4
  const en_locales = () => {
5
5
  return {
6
- successHeader: 'SUCCESS',
7
- snapshotSuccessMessage:
8
- 'Please go to the Contrast UI to view your dependency tree.',
9
6
  snapshotFailureHeader: 'FAIL',
10
7
  snapshotFailureMessage: 'Library analysis failed',
11
- snapshotHostMessage:
12
- "No host supplied. Using default host 'app.contrastsecurity.com'. Please ensure this is correct.",
13
- vulnerabilitiesSuccessMessage: 'Vulnerability data successfully retrieved',
14
8
  vulnerabilitiesFailureMessage: 'Unable to retrieve library vulnerabilities',
15
- catchErrorMessage: 'Contrast UI error: ',
16
9
  dependenciesNote:
17
10
  'Please Note: We currently only support projects with one .csproj AND *.package.lock.json',
18
- languageAnalysisFailureMessage: 'SCA audit Failure',
19
- languageAnalysisFactoryFailureHeader: 'FAIL',
20
11
  libraryAnalysisError:
21
12
  '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',
22
- yamlMissingParametersHeader: 'Missing Parameters',
23
13
  genericErrorMessage:
24
14
  'An error has occur please check your command again. For more information use the --help commands.',
25
15
  unauthenticatedErrorHeader: '401 error - Unauthenticated',
@@ -35,21 +25,7 @@ const en_locales = () => {
35
25
  proxyErrorHeader: '407 error - Proxy Authentication Required',
36
26
  proxyErrorMessage:
37
27
  'Please provide valid authentication credentials for the proxy server.',
38
- catalogueSuccessCommand: 'Application Created',
39
- dotnetAnalysisFailure: '.NET analysis failed because: ',
40
- dotnetReadLockfile: 'Failed to read the lock file @ %s because: ',
41
- dotnetParseLockfile: "Failed to parse .NET lock file @ '%s' because: ",
42
- dotnetParseProjectFile:
43
- "Failed to parse MSBuild project file @ '%s' because: ",
44
- dotnetReadProjectFile: 'Failed to read the project file @ "%s" because: ',
45
- javaAnalysisError: 'JAVA analysis failed because: ',
46
28
  javaParseProjectFile: 'Failed to parse mvn output because: ',
47
- languageAnalysisMultipleLanguages1:
48
- 'Identified multiple languages for the project\n',
49
- languageAnalysisMultipleLanguages2:
50
- 'Please specify which project file you would like analyzed with the %s CLI option.',
51
- languageAnalysisProjectFiles:
52
- "Identified project language as '%s' but found multiple project files: %s. Please specify which project file you would like analyzed with the %s CLI option.",
53
29
  languageAnalysisHasNoLockFile:
54
30
  "Identified project language as '%s' but no project lock file was found.",
55
31
  languageAnalysisHasNoPackageJsonFile:
@@ -58,100 +34,56 @@ const en_locales = () => {
58
34
  "Identified project language as '%s' but multiple project lock files were found.",
59
35
  languageAnalysisProjectFileError:
60
36
  "Identified project language as '%s' but no project file was found.",
61
- languageAnalysisProjectRootFileNameReadError:
62
- 'Failed to read the contents of the directory @ %s because: ',
63
- languageAnalysisProjectRootFileNameMissingError:
64
- "%s isn't a file or directory",
65
37
  languageAnalysisProjectRootFileNameFailure:
66
38
  'Failed to get information about the file or directory @ %s because: ',
67
- languageAnalysisFailure: ' analysis failed because: ',
68
39
  languageAnalysisNoLanguage:
69
40
  'We cannot detect a project, use -f <path> to specify a file or folder to analyze.',
70
41
  languageAnalysisNoLanguageHelpLine: `${chalk.bold(
71
42
  'contrast audit --help'
72
43
  )} for more information.`,
73
- NodeAnalysisFailure: 'NODE analysis failed because: ',
74
- phpAnalysisFailure: 'PHP analysis failed because: ',
75
44
  NodeParseNPM: 'Failed to parse NODE package-lock.json file because: ',
76
45
  phpParseComposerLock:
77
46
  "Failed to parse PHP composer.lock file @ '%s' because: ",
78
- NodeReadNpmError:
79
- 'Failed to read the package-lock.json file @ "%s" because: ',
80
- phpReadError: 'Failed to read the composer.lock file @ "%s" because: ',
81
47
  NodeParseYarn: 'Failed to parse yarn.lock version %s because: ',
82
48
  NodeParseYarn2: "Failed to parse Node yarn.lock version 2 @ '%s' because: ",
83
- nodeReadProjectFileError:
84
- 'Failed to read the NODE project file @ "%s" because: ',
85
- phpReadProjectFileError:
86
- 'Failed to read the PHP project file @ "%s" because: ',
87
49
  nodeReadYarnLockFileError:
88
50
  'Failed to read the yarn.lock file @ "%s" because: ',
89
- pythonAnalysisEngineError: 'Python analysis failed because: ',
90
- pythonAnalysisEnginePipError:
91
- "Failed to parse python Pipfile.lock file @ '%s' because: ",
92
- pythonAnalysisParseProjectFileError:
93
- 'Failed to parse python output "%s" because: ',
94
- pythonAnalysisReadPipFileError:
95
- 'Failed to read the python Pipfile.lock file @ "%s" because: ',
96
- pythonAnalysisReadPythonProjectFileError:
97
- 'Failed to read the python pipfile @ "%s" because: ',
98
- rubyAnalysisEngineError: 'Ruby analysis failed because: ',
99
- rubyAnalysisEngineParsedGemFileError:
100
- 'Failed to parse ruby output "%s" because: ',
101
- rubyAnalysisEngineParsedGemLockFileError:
102
- 'Failed to parse ruby Gemfile.lock output because: ',
103
- rubyAnalysisEngineReadGemFileError:
104
- 'Failed to read the ruby project file @ "%s" because: ',
105
- rubyAnalysisEngineReadGemLockFileError:
106
- 'Failed to read the ruby Gemfile.lock @ "%s" because: ',
107
51
  constantsOptional: '(optional)',
108
- constantsOptionalForCatalogue: '(optional for catalogue)',
109
52
  constantsRequired: '(required)',
110
- constantsRequiredCatalogue: '(required for catalogue)',
53
+ constantsRequiredEnterprise: '(required for Contrast Enterprise)',
111
54
  constantsApiKey: 'An agent API key as provided by Contrast UI',
112
55
  constantsAuthorization:
113
- 'Authorization credentials as provided by Contrast UI',
114
- constantsOrganizationId: 'The ID of your organization',
56
+ 'An authorization header as provided by Contrast UI',
57
+ constantsOrganizationId:
58
+ 'The ID of your organization as provided by Contrast UI',
115
59
  constantsApplicationId:
116
- 'The ID of the application cataloged by Contrast UI',
117
- constantsHostId:
118
- 'Provide the name of the host and optionally the port expressed as "<host>:<port>".',
60
+ 'The ID of the application as provided by Contrast UI',
61
+ constantsHostId: 'host name e.g. https://app.contrastsecurity.com',
119
62
  constantsApplicationName:
120
- 'The name of the application cataloged by Contrast UI',
121
- constantsCatalogueApplication:
122
- 'Provide this if you want to catalogue an application',
63
+ 'The name of the application as provided by Contrast UI',
123
64
  failOptionErrorMessage:
124
65
  ' FAIL - CVEs have been detected that match at least the cve_severity option specified.',
125
66
  failOptionMessage:
126
67
  ' Use with contrast scan or contrast audit. Detects failures based on the severity level specified with the --severity command. For example, "contrast scan --fail --severity high". Returns all failures if no severity level is specified.',
127
- constantsLanguage:
128
- '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',
129
68
  constantsFilePath: `Specify a directory or the file where dependencies are declared. (By default, CodeSec will search for project files in the current directory.)`,
130
- constantsSilent: 'Silences JSON output.',
131
69
  constantsAppGroups:
132
- 'Assign your application to one or more pre-existing groups when using the catalogue command. Group lists should be comma separated.',
133
- constantsVersion: 'Displays CLI Version you are currently on.',
70
+ 'Assign your application to one or more pre-existing groups when on boarding an application. Group lists should be comma separated.',
134
71
  constantsProxyServer:
135
- 'Allows for connection via a proxy server. If authentication is required please provide the username and password with the protocol, host and port. For instance: "http://username:password@<host>:<port>".',
136
- constantsHelp: 'Display this usage guide.',
72
+ 'Allows for connection via a proxy server. If authentication is required please provide the username and password with the protocol, host and port. For instance: "https://username:password@<host>:<port>".',
137
73
  constantsGradleMultiProject:
138
74
  'Specify the sub project within your gradle application.',
139
- constantsScan: 'Upload java binaries to the static scan service',
140
- constantsDoNotWaitForScan: 'Do not wait for the result of the scan',
75
+ constantsDoNotWaitForScan:
76
+ 'Fire and forget. Do not wait for the result of the scan.',
141
77
  constantsProjectName:
142
78
  'Contrast project name. If not specified, Contrast uses contrast.settings to identify the project or creates a project.',
143
79
  constantsProjectId:
144
80
  '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.',
145
- constantsReport: 'Display vulnerability information for this application',
146
- constantsFail:
147
- 'Set the process to fail if this option is set in combination with --cve_severity.',
148
81
  failThresholdOptionErrorMessage: 'More than 0 vulnerabilities found',
149
82
  failSeverityOptionErrorMessage:
150
83
  ' FAIL - Results detected vulnerabilities over accepted severity level',
151
84
  constantsSeverity:
152
85
  'Use with "contrast scan --fail --severity high" or "contrast audit --fail --severity high". Set the severity level to detect vulnerabilities or dependencies. Severity levels are critical, high, medium, low or note.',
153
- constantsCount: 'The number of CVEs that must be exceeded to fail a build',
154
- constantsHeader: 'CodeSec by Contrast Security',
86
+ constantsHeader: 'Contrast CLI',
155
87
  configHeader2: 'Config options',
156
88
  clearHeader: '-c, --clear',
157
89
  clearContent: 'Removes stored credentials',
@@ -161,8 +93,6 @@ const en_locales = () => {
161
93
  'Use the ‘contrast’ command for fast and accurate security analysis of your applications, APIs, serverless functions, and libraries.',
162
94
  constantsContrastCategories:
163
95
  '\n Code: Java, .NET, .NET Core, JavaScript\n Serverless: AWS Lambda - Java, Python\n Libraries: Java, .NET, Node, Ruby, Python, Go, PHP\n',
164
- constantsUsageGuideContentRecommendation:
165
- '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.',
166
96
  constantsPrerequisitesHeader: 'Pre-requisites',
167
97
  constantsAuthUsageHeader: 'Usage',
168
98
  constantsAuthUsageContents: 'contrast auth',
@@ -180,47 +110,27 @@ const en_locales = () => {
180
110
  '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',
181
111
  constantsUsageCommandInfo24Hours:
182
112
  'Submitted files are encrypted during upload and deleted in 24 hours.',
183
- constantsAnd: 'AND',
184
- constantsJava:
185
- 'AND Maven build platform, including the dependency plugin. For a Gradle project, use build.gradle. A gradle-wrapper.properties file is also required. Kotlin is also supported requiring a build.gradle.kts file.',
186
- constantsJavaNote:
187
- 'Note: Running "mvn dependency:tree" or "./gradlew dependencies" in the project directory locally must be successful.',
188
- constantsJavaNoteGradle:
189
- 'We currently support v4.8 and upwards on Gradle projects',
190
- constantsDotNet:
191
- 'MSBuild 15.0 or greater and have a packages.lock.json file are supported.',
192
- constantsDotNetNote:
193
- 'Please Note: If the packages.lock.json file is not in place it can be generated by setting RestorePackagesWithLockFile to true within each *.csproj and running dotnet build',
194
- constantsNode: '%s AND a lock file either %s or %s',
195
- constantsRuby: 'gemfile AND gemfile.lock',
196
- constantsPython: 'pipfile AND pipfile.lock',
197
- constantsHowToRunHeader: 'How to run:',
198
- constantsHowToRunDev1:
199
- 'Begin with contrast auth to authenticate the CLI to perform actions',
200
- constantsHowToRunDev2:
201
- 'After successful auth try the following command: contrast scan -f "<file>"',
202
113
  constantsHowToRunDev3:
203
114
  'Allowable languages are java (.jar and .war) and javascript (.js or .zip), if the language is not autodetected please use --language to specify',
204
115
  constantsOptions: 'Options',
205
- constantsSpecialCharacterWarning:
206
- 'Please Note: Parameters may need to be quoted to avoid issues with special characters.',
207
116
  constantsProxyKey: 'Path to the Certificate Key',
208
117
  constantsProxyCert: 'Path to the Cert file',
209
118
  constantsProxyCaCert: 'Path to the CaCert file',
210
119
  goReadProjectFile: 'Failed to read the project file @ "%s" because: "%s"',
211
120
  mavenDependencyTreeNonZero:
212
- 'Building maven dependancy tree failed with a non 0 exit code',
121
+ 'Building maven dependency tree failed with a non 0 exit code',
213
122
  gradleWrapperUnavailable:
214
123
  'Gradle wrapper not found in root of project. Please ensure gradlew or gradlew.bat is in root of the project.',
215
124
  gradleDependencyTreeNonZero:
216
- "Building gradle dependancy tree failed with a non 0 exit code. \n Please check you have the correct version of Java installed to compile your project? \n If running against a muti module project ensure you are using the '--sub-project' flag",
125
+ "Building gradle dependency tree failed with a non 0 exit code. \n Please check you have the correct version of Java installed to compile your project? \n If running against a muti module project ensure you are using the '--sub-project' flag",
217
126
  constantsMetadata:
218
127
  'Define a set of key=value pairs (which conforms to RFC 2253) for specifying user-defined metadata associated with the application.',
219
128
  constantsTags:
220
129
  'Apply labels to an application. Labels must be formatted as a comma-delimited list. Example - label1,label2,label3',
221
130
  constantsCode:
222
131
  'Add the application code this application should use in the Contrast UI',
223
- constantsIgnoreCertErrors:
132
+ constantsMavenSettingsPath: 'Path to maven settings',
133
+ constantsCertSelfSigned:
224
134
  'For EOP users with a local Teamserver install, this will bypass the SSL certificate and recognise a self signed certificate.',
225
135
  constantsSave: 'Saves the Scan Results SARIF to file.',
226
136
  scanLabel:
@@ -229,7 +139,7 @@ const en_locales = () => {
229
139
  'Excludes developer dependencies from the results. All dependencies are included by default.',
230
140
  constantsCommands: 'Commands',
231
141
  constantsScanOptions: 'Scan Options',
232
- sbomRetrievalError: 'Unable to retrieve Software Bill of Materials (SBOM)',
142
+ constantsAdvancedOptions: 'Advanced',
233
143
  foundExistingProjectScan: 'Found existing project...',
234
144
  projectCreatedScan: 'Project created',
235
145
  uploadingScan: 'Uploading file to scan.',
@@ -268,10 +178,6 @@ const en_locales = () => {
268
178
  configName: 'config',
269
179
  helpName: 'help',
270
180
  scanOptionsLanguageSummary: 'Valid values are JAVA, JAVASCRIPT and DOTNET',
271
- scanOptionsLanguageSummaryOptional:
272
- 'Language of file to send for analysis. ',
273
- scanOptionsLanguageSummaryRequired:
274
- 'If you scan a .zip file or you use the --file option.',
275
181
  scanOptionsTimeoutSummary:
276
182
  'Time in seconds to wait for scan to complete. Default value is 300 seconds.',
277
183
  scanOptionsFileNameSummary:
@@ -295,14 +201,9 @@ const en_locales = () => {
295
201
  ' to learn more about the capabilities.',
296
202
  authWaitingMessage: 'Waiting for auth...',
297
203
  authTimedOutMessage: 'Auth Timed out, try again',
298
- zipErrorScan:
299
- 'We only support zip files for JAVASCRIPT language, please set the flag --language JAVASCRIPT',
300
- unknownFileErrorScan: 'Unsupported file selected for Scan.',
301
204
  foundScanFile: 'Found: %s',
302
205
  foundDetailedVulnerabilities:
303
206
  chalk.bold('%s') + ' | ' + chalk.bold('%s') + ' | %s | %s | %s ',
304
- requiredParams: 'All required parameters are not present.',
305
- timeoutScan: 'Timeout set to 5 minutes.',
306
207
  searchingScanFileDirectory: 'Searching for file to scan from %s...',
307
208
  searchingAuditFileDirectory:
308
209
  'Searching for package manager files from %s...',
@@ -312,13 +213,11 @@ const en_locales = () => {
312
213
  lambdaSummary:
313
214
  'Performs static security scan on an AWS Lambda Function.\nProduces CVE (Vulnerable Dependencies) and Least Privilege violations/remediation results.',
314
215
  lambdaUsage: 'contrast lambda --function-name <function> [options]',
315
- lambdaPrerequisitesContent: '',
316
216
  lambdaPrerequisitesContentLambdaLanguages:
317
217
  'Supported runtimes: Java & Python',
318
218
  lambdaPrerequisitesContentLambdaDescriptionTitle: 'AWS Requirements\n',
319
219
  lambdaPrerequisitesContentLambdaDescription:
320
220
  '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, ListFunctions\n - IAM: GetRolePolicy, GetPolicy, GetPolicyVersion, ListRolePolicies, ListAttachedRolePolicies',
321
- scanFileNameOption: '-f, --file',
322
221
  lambdaFunctionNameOption: '-f, --function-name',
323
222
  lambdaListFunctionsOption: '-l, --list-functions',
324
223
  lambdaEndpointOption: '-e, --endpoint-url',
@@ -341,13 +240,10 @@ const en_locales = () => {
341
240
  'Configuration details not found. Try authenticating by using ‘contrast auth’.',
342
241
  redirectAuth:
343
242
  '\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',
344
- scanZipError:
345
- 'A .zip archive can be used for Javascript Scan. Archive found %s does not contain .JS files for Scan.',
346
243
  fileNotExist: 'File specified does not exist, please check and try again.',
347
244
  scanFileIsEmpty: 'File specified is empty. Please choose another.',
348
245
  fileHasWhiteSpacesError:
349
246
  'File cannot have spaces, please rename or choose another file to Scan.',
350
- zipFileException: 'Error reading zip file',
351
247
  connectionError:
352
248
  'An error has occurred when trying to get the Project Id please check your internet connection or provide the Project Id manually',
353
249
  internalServerErrorHeader: '500 error - Internal server error',
@@ -400,25 +296,23 @@ const en_locales = () => {
400
296
  'Please specify file type to save results to, accepted value is SARIF',
401
297
  auditSBOMSaveSuccess:
402
298
  '\n Software Bill of Materials (SBOM) saved successfully',
403
- auditNoFiletypeSpecifiedForSave: `\n ${chalk.yellow.bold(
404
- 'No file type specified for --save option to save audit results to. Use audit --help to see valid --save options.'
405
- )}`,
406
299
  auditBadFiletypeSpecifiedForSave: `\n ${chalk.yellow.bold(
407
300
  'Bad file type specified for --save option. Use audit --help to see valid --save options.'
408
301
  )}`,
409
302
  auditServicesMessageForTS:
410
303
  'View your vulnerable library list or full dependency tree in Contrast:',
411
- auditReportWaiting: 'Waiting for report...',
412
- auditReportFail: 'Report Retrieval Failed, please try again',
413
- auditReportSuccessMessage: 'Report successfully retrieved',
414
304
  auditReportFailureMessage: 'Unable to generate library report',
415
305
  auditSCAAnalysisBegins: 'Contrast SCA audit started',
416
306
  auditSCAAnalysisComplete: 'Contrast audit complete',
417
- commonHelpHeader: 'Need More Help?',
307
+ commonHelpHeader: 'Need More Help? NEW users',
308
+ commonHelpEnterpriseHeader: 'Existing Contrast Licensed user?',
418
309
  commonHelpCheckOutHeader: chalk.hex('#9DC184')('Check out:'),
419
310
  commonHelpCheckOutText: ' https://support.contrastsecurity.com',
420
311
  commonHelpLearnMoreHeader: chalk.hex('#9DC184')('Learn more at:'),
421
- commonHelpLearnMoreText: ' https://developer.contrastsecurity.com',
312
+ commonHelpLearnMoreEnterpriseHeader: chalk.hex('#9DC184')('Read our docs:'),
313
+ commonHelpLearnMoreText: ' https://www.contrastsecurity.com/developer ',
314
+ commonHelpLearnMoreEnterpriseText:
315
+ ' https://docs.contrastsecurity.com/en/run-contrast-cli.html ',
422
316
  commonHelpJoinDiscussionHeader: chalk.hex('#9DC184')(
423
317
  'Join the discussion:'
424
318
  ),
@@ -81,7 +81,8 @@ const lambdaUsageGuide = commandLineUsage([
81
81
  { name: i18n.__('lambdaHelpOption'), summary: i18n.__('helpSummary') }
82
82
  ]
83
83
  },
84
- commonHelpLinks()
84
+ commonHelpLinks()[0],
85
+ commonHelpLinks()[1]
85
86
  ])
86
87
 
87
88
  export { lambdaUsageGuide }
@@ -17,7 +17,7 @@ import ora from '../utils/oraWrapper'
17
17
  import { postAnalytics } from './analytics'
18
18
  import { LambdaOptions, AnalyticsOption, StatusType, EventType } from './types'
19
19
  import { APP_VERSION } from '../constants/constants'
20
- import chalk from 'chalk'
20
+ import { postRunMessage } from '../common/commonHelp'
21
21
 
22
22
  type ApiParams = {
23
23
  organizationId: string
@@ -116,7 +116,7 @@ const processLambda = async (argv: string[]) => {
116
116
  /* ignore */
117
117
  })
118
118
 
119
- postRunMessage()
119
+ postRunMessage('lambda')
120
120
 
121
121
  if (errorMsg) {
122
122
  process.exit(1)
@@ -225,12 +225,4 @@ const handleLambdaHelp = () => {
225
225
  process.exit(0)
226
226
  }
227
227
 
228
- const postRunMessage = () => {
229
- console.log('\n' + chalk.underline.bold('Other Codesec Features:'))
230
- console.log("'contrast scan' to run CodeSec’s industry leading SAST scanner")
231
- console.log(
232
- "'contrast audit' to find vulnerabilities in your open source dependencies\n"
233
- )
234
- }
235
-
236
228
  export { processLambda, LambdaOptions, ApiParams, getAvailableFunctions }
@@ -1,7 +1,10 @@
1
1
  const child_process = require('child_process')
2
+ const spawn = require('cross-spawn')
2
3
  const path = require('path')
3
4
  const i18n = require('i18n')
4
5
  const fs = require('fs')
6
+ const readLine = require('readline')
7
+ const paramHandler = require('../../utils/paramsUtil/paramHandler')
5
8
 
6
9
  const MAVEN = 'maven'
7
10
  const GRADLE = 'gradle'
@@ -29,20 +32,23 @@ const determineProjectTypeAndCwd = (files, config) => {
29
32
 
30
33
  const buildMaven = (config, projectData, timeout) => {
31
34
  let cmdStdout
32
- let mvn_settings = ''
33
-
34
35
  try {
35
- // Allow users to provide a custom location for their settings.xml
36
+ let command = 'mvn'
37
+ let args = ['dependency:tree', '-B']
36
38
  if (config.mavenSettingsPath) {
37
- mvn_settings = ' -s ' + config.mavenSettingsPath
39
+ args.push('-s')
40
+ args.push(config.mavenSettingsPath)
38
41
  }
39
- cmdStdout = child_process.execSync(
40
- 'mvn dependency:tree -B' + mvn_settings,
41
- {
42
+ // Allow users to provide a custom location for their settings.xml
43
+
44
+ cmdStdout = spawn
45
+ .sync(command, args, {
46
+ env: process.env,
42
47
  cwd: projectData.cwd,
43
48
  timeout
44
- }
45
- )
49
+ })
50
+ .stdout.toString()
51
+
46
52
  return cmdStdout.toString()
47
53
  } catch (err) {
48
54
  throw new Error(
@@ -141,7 +147,34 @@ const getJavaBuildDeps = (config, files) => {
141
147
  }
142
148
  }
143
149
 
150
+ const agreementPrompt = async config => {
151
+ const rl = readLine.createInterface({
152
+ input: process.stdin,
153
+ output: process.stdout
154
+ })
155
+
156
+ return new Promise((resolve, reject) => {
157
+ rl.question('❔ Do you want to continue? Type Y or N', async input => {
158
+ if (input.toLowerCase() === 'yes' || input.toLowerCase() === 'y') {
159
+ config.javaAgreement = paramHandler.setAgreement(true)
160
+ rl.close()
161
+ resolve(config)
162
+ } else if (input.toLowerCase() === 'no' || input.toLowerCase() === 'n') {
163
+ rl.close()
164
+ resolve(process.exit(1))
165
+ } else {
166
+ rl.close()
167
+ console.log('Invalid Input: Exiting')
168
+ resolve(process.exit(1))
169
+ }
170
+ })
171
+ }).catch(e => {
172
+ throw e
173
+ })
174
+ }
175
+
144
176
  module.exports = {
145
177
  getJavaBuildDeps,
146
- determineProjectTypeAndCwd
178
+ determineProjectTypeAndCwd,
179
+ agreementPrompt
147
180
  }
@@ -4,12 +4,16 @@ const { createJavaTSMessage } = require('../common/formatMessage')
4
4
  const {
5
5
  parseDependenciesForSCAServices
6
6
  } = require('../common/scaParserForGoAndJava')
7
+ const chalk = require('chalk')
8
+ const _ = require('lodash')
7
9
 
8
- const javaAnalysis = (config, languageFiles) => {
10
+ const javaAnalysis = async (config, languageFiles) => {
9
11
  languageFiles.JAVA.forEach(file => {
10
12
  file.replace('build.gradle.kts', 'build.gradle')
11
13
  })
12
14
 
15
+ await getAgreement(config)
16
+
13
17
  const javaDeps = buildJavaTree(config, languageFiles.JAVA)
14
18
 
15
19
  if (config.experimental) {
@@ -19,11 +23,24 @@ const javaAnalysis = (config, languageFiles) => {
19
23
  }
20
24
  }
21
25
 
26
+ const getAgreement = async config => {
27
+ console.log(chalk.bold('Java project detected'))
28
+ console.log(
29
+ 'Java analysis uses maven / gradle which are potentially susceptible to command injection. Be sure that the code you are running Contrast CLI on is trusted before continuing.'
30
+ )
31
+
32
+ if (!process.env.CI && !config?.javaAgreement) {
33
+ return await analysis.agreementPrompt(config)
34
+ }
35
+ return config
36
+ }
37
+
22
38
  const buildJavaTree = (config, files) => {
23
39
  const javaBuildDeps = analysis.getJavaBuildDeps(config, files)
24
40
  return parseBuildDeps(config, javaBuildDeps)
25
41
  }
26
42
 
27
43
  module.exports = {
28
- javaAnalysis
44
+ javaAnalysis,
45
+ getAgreement
29
46
  }
@@ -1,7 +1,17 @@
1
1
  const i18n = require('i18n')
2
2
  const fileFinder = require('./fileUtils')
3
- const rootFile = require('../audit/languageAnalysisEngine/getProjectRootFilenames')
4
- const path = require('path')
3
+
4
+ const autoDetectFingerprintInfo = async filePath => {
5
+ let complexObj = await fileFinder.findAllFiles(filePath)
6
+ let result = []
7
+ let count = 0
8
+ complexObj.forEach(i => {
9
+ count++
10
+ result.push({ filePath: i, id: count.toString() })
11
+ })
12
+
13
+ return result
14
+ }
5
15
 
6
16
  const autoDetectFileAndLanguage = async configToUse => {
7
17
  const entries = await fileFinder.findFile()
@@ -53,6 +63,25 @@ const hasWhiteSpace = s => {
53
63
  return filename.indexOf(' ') >= 0
54
64
  }
55
65
 
66
+ const dealWithMultiJava = filesFound => {
67
+ let hasMultiJava =
68
+ filesFound.filter(data => {
69
+ return (
70
+ Object.keys(data)[0] === 'JAVA' &&
71
+ Object.values(data)[0].includes('build.gradle') &&
72
+ Object.values(data)[0].includes('pom.xml')
73
+ )
74
+ }).length > 0
75
+ if (hasMultiJava) {
76
+ console.log('Multiple Java language dependency files detected')
77
+ console.log(
78
+ 'Please use --file to audit one only. \nExample: contrast audit --file pom.xml'
79
+ )
80
+ process.exit(1)
81
+ }
82
+ return false
83
+ }
84
+
56
85
  const errorOnFileDetection = entries => {
57
86
  if (entries.length > 1) {
58
87
  console.log(i18n.__('searchingDirectoryScan'))
@@ -88,5 +117,7 @@ module.exports = {
88
117
  autoDetectFileAndLanguage,
89
118
  errorOnFileDetection,
90
119
  autoDetectAuditFilesAndLanguages,
91
- errorOnAuditFileDetection
120
+ errorOnAuditFileDetection,
121
+ autoDetectFingerprintInfo,
122
+ dealWithMultiJava
92
123
  }
@@ -11,6 +11,33 @@ const findFile = async () => {
11
11
  })
12
12
  }
13
13
 
14
+ const findAllFiles = async filePath => {
15
+ const result = await fg(
16
+ [
17
+ '**/pom.xml',
18
+ '**/build.gradle',
19
+ '**/build.gradle.kts',
20
+ '**/package.json',
21
+ '**/Pipfile',
22
+ '**/*.csproj',
23
+ '**/Gemfile',
24
+ '**/go.mod'
25
+ ],
26
+ {
27
+ dot: false,
28
+ deep: 2,
29
+ onlyFiles: true,
30
+ absolute: true,
31
+ cwd: filePath ? filePath : process.cwd()
32
+ }
33
+ )
34
+
35
+ if (result.length > 0) {
36
+ return result
37
+ }
38
+ return []
39
+ }
40
+
14
41
  const findFilesJava = async (languagesFound, filePath) => {
15
42
  const result = await fg(
16
43
  ['**/pom.xml', '**/build.gradle', '**/build.gradle.kts'],
@@ -159,5 +186,6 @@ module.exports = {
159
186
  findFilesPhp,
160
187
  findFilesRuby,
161
188
  findFilesDotNet,
162
- fileIsEmpty
189
+ fileIsEmpty,
190
+ findAllFiles
163
191
  }
package/src/scan/help.js CHANGED
@@ -29,14 +29,22 @@ const scanUsageGuide = commandLineUsage([
29
29
  'proxy',
30
30
  'help',
31
31
  'ff',
32
- 'ignore-cert-errors',
32
+ 'cert-self-signed',
33
+ 'key',
34
+ 'cacert',
35
+ 'cert',
33
36
  'verbose',
34
37
  'debug',
35
- 'experimental',
36
- 'application-name'
38
+ 'experimental'
37
39
  ]
38
40
  },
39
- commonHelpLinks()
41
+ {
42
+ header: i18n.__('constantsAdvancedOptions'),
43
+ optionList:
44
+ constants.commandLineDefinitions.scanAdvancedOptionDefinitionsForHelp
45
+ },
46
+ commonHelpLinks()[0],
47
+ commonHelpLinks()[1]
40
48
  ])
41
49
 
42
50
  module.exports = {
@@ -3,7 +3,7 @@ const fs = require('fs')
3
3
  const writeResultsToFile = async (responseBody, name = 'results.sarif') => {
4
4
  try {
5
5
  fs.writeFileSync(name, JSON.stringify(responseBody, null, 2))
6
- console.log(`Scan Results saved to ${name}`)
6
+ return name
7
7
  } catch (err) {
8
8
  console.log('Error writing Scan Results to file')
9
9
  }
@@ -5,7 +5,12 @@ const {
5
5
  forbiddenError,
6
6
  proxyError,
7
7
  genericError,
8
- maxAppError
8
+ maxAppError,
9
+ snapshotFailureError,
10
+ vulnerabilitiesFailureError,
11
+ reportFailureError,
12
+ parametersError,
13
+ invalidHostNameError
9
14
  } = require('../common/errorHandling')
10
15
 
11
16
  const handleResponseErrors = (res, api) => {
@@ -19,7 +24,20 @@ const handleResponseErrors = (res, api) => {
19
24
  proxyError()
20
25
  } else if (res.statusCode === 412) {
21
26
  maxAppError()
27
+ } else if (res.statusCode === 301) {
28
+ invalidHostNameError(res.statusCode)
29
+ } else if (res.statusCode === 302) {
30
+ parametersError(res.statusCode)
22
31
  } else {
32
+ if (api === 'snapshot' || api === 'catalogue') {
33
+ snapshotFailureError()
34
+ }
35
+ if (api === 'vulnerabilities') {
36
+ vulnerabilitiesFailureError()
37
+ }
38
+ if (api === 'report') {
39
+ reportFailureError()
40
+ }
23
41
  console.log(res.statusCode)
24
42
  genericError(res)
25
43
  }
@@ -1,6 +1,5 @@
1
1
  const { featuresTeamServer } = require('./capabilities')
2
2
  const semver = require('semver')
3
- const { handleResponseErrors } = require('../common/errorHandling')
4
3
  const commonApi = require('./commonApi')
5
4
  const { isNil } = require('lodash')
6
5
 
@@ -12,7 +11,7 @@ const getGlobalProperties = async config => {
12
11
  if (res.statusCode === 200) {
13
12
  return res.body
14
13
  } else {
15
- handleResponseErrors(res, 'globalProperties')
14
+ commonApi.handleResponseErrors(res, 'globalProperties')
16
15
  }
17
16
  })
18
17
  .catch(err => {