@contrast/contrast 1.0.17 → 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.
@@ -21,8 +21,7 @@ const javaAnalysis = async (config, languageFiles) => {
21
21
  const getAgreement = async (config) => {
22
22
  console.log(chalk.bold('Java project detected'));
23
23
  console.log('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.');
24
- if (_.isNil(!process.env.CI) && _.isNil(!config.javaAgreement)) {
25
- console.log('should print');
24
+ if (!process.env.CI && !config?.javaAgreement) {
26
25
  return await analysis.agreementPrompt(config);
27
26
  }
28
27
  return config;
@@ -51,6 +51,19 @@ const hasWhiteSpace = s => {
51
51
  const filename = s.split('/').pop();
52
52
  return filename.indexOf(' ') >= 0;
53
53
  };
54
+ const dealWithMultiJava = filesFound => {
55
+ let hasMultiJava = filesFound.filter(data => {
56
+ return (Object.keys(data)[0] === 'JAVA' &&
57
+ Object.values(data)[0].includes('build.gradle') &&
58
+ Object.values(data)[0].includes('pom.xml'));
59
+ }).length > 0;
60
+ if (hasMultiJava) {
61
+ console.log('Multiple Java language dependency files detected');
62
+ console.log('Please use --file to audit one only. \nExample: contrast audit --file pom.xml');
63
+ process.exit(1);
64
+ }
65
+ return false;
66
+ };
54
67
  const errorOnFileDetection = entries => {
55
68
  if (entries.length > 1) {
56
69
  console.log(i18n.__('searchingDirectoryScan'));
@@ -87,5 +100,6 @@ module.exports = {
87
100
  errorOnFileDetection,
88
101
  autoDetectAuditFilesAndLanguages,
89
102
  errorOnAuditFileDetection,
90
- autoDetectFingerprintInfo
103
+ autoDetectFingerprintInfo,
104
+ dealWithMultiJava
91
105
  };
package/dist/scan/help.js CHANGED
@@ -29,13 +29,19 @@ 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
  },
41
+ {
42
+ header: i18n.__('constantsAdvancedOptions'),
43
+ optionList: constants.commandLineDefinitions.scanAdvancedOptionDefinitionsForHelp
44
+ },
39
45
  commonHelpLinks()[0],
40
46
  commonHelpLinks()[1]
41
47
  ]);
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  const HttpClient = require('./../common/HTTPClient');
3
- const { badRequestError, unauthenticatedError, forbiddenError, proxyError, genericError, maxAppError, snapshotFailureError, vulnerabilitiesFailureError, reportFailureError } = require('../common/errorHandling');
3
+ const { badRequestError, unauthenticatedError, forbiddenError, proxyError, genericError, maxAppError, snapshotFailureError, vulnerabilitiesFailureError, reportFailureError, parametersError, invalidHostNameError } = require('../common/errorHandling');
4
4
  const handleResponseErrors = (res, api) => {
5
5
  if (res.statusCode === 400) {
6
6
  api === 'catalogue' ? badRequestError(true) : badRequestError(false);
@@ -17,6 +17,12 @@ const handleResponseErrors = (res, api) => {
17
17
  else if (res.statusCode === 412) {
18
18
  maxAppError();
19
19
  }
20
+ else if (res.statusCode === 301) {
21
+ invalidHostNameError(res.statusCode);
22
+ }
23
+ else if (res.statusCode === 302) {
24
+ parametersError(res.statusCode);
25
+ }
20
26
  else {
21
27
  if (api === 'snapshot' || api === 'catalogue') {
22
28
  snapshotFailureError();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrast/contrast",
3
- "version": "1.0.17",
3
+ "version": "1.0.18",
4
4
  "description": "Contrast Security's command line tool",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -11,7 +11,7 @@ i18n.configure({
11
11
  defaultLocale: 'en'
12
12
  })
13
13
 
14
- const sharedOptionDefinitions = [
14
+ const sharedCertOptionDefinitions = [
15
15
  {
16
16
  name: 'proxy',
17
17
  description:
@@ -45,46 +45,55 @@ const sharedOptionDefinitions = [
45
45
  i18n.__('constantsProxyCert')
46
46
  },
47
47
  {
48
- name: 'ignore-cert-errors',
48
+ name: 'cert-self-signed',
49
49
  type: Boolean,
50
50
  description:
51
51
  '{bold ' +
52
52
  i18n.__('constantsOptional') +
53
53
  '}:' +
54
- i18n.__('constantsIgnoreCertErrors')
54
+ i18n.__('constantsCertSelfSigned')
55
55
  }
56
56
  ]
57
57
 
58
- // CLI options that we will allow and handle
59
- const scanOptionDefinitions = [
60
- ...sharedOptionDefinitions,
58
+ const sharedConnectionOptionDefinitions = [
61
59
  {
62
- name: 'name',
63
- alias: 'n',
60
+ name: 'organization-id',
61
+ alias: 'o',
64
62
  description:
65
63
  '{bold ' +
66
- i18n.__('constantsOptional') +
64
+ i18n.__('constantsRequiredEnterprise') +
67
65
  '}: ' +
68
- i18n.__('constantsProjectName')
66
+ i18n.__('constantsOrganizationId')
69
67
  },
70
68
  {
71
- name: 'language',
72
- alias: 'l',
69
+ name: 'api-key',
73
70
  description:
74
71
  '{bold ' +
75
- i18n.__('constantsOptional') +
72
+ i18n.__('constantsRequiredEnterprise') +
76
73
  '}: ' +
77
- i18n.__('scanOptionsLanguageSummary')
74
+ i18n.__('constantsApiKey')
78
75
  },
79
76
  {
80
- name: 'file',
81
- alias: 'f',
77
+ name: 'authorization',
82
78
  description:
83
79
  '{bold ' +
84
- i18n.__('constantsOptional') +
80
+ i18n.__('constantsRequiredEnterprise') +
85
81
  '}: ' +
86
- i18n.__('scanOptionsFileNameSummary')
82
+ i18n.__('constantsAuthorization')
87
83
  },
84
+ {
85
+ name: 'host',
86
+ description:
87
+ '{bold ' +
88
+ i18n.__('constantsRequiredEnterprise') +
89
+ '}: ' +
90
+ i18n.__('constantsHostId')
91
+ }
92
+ ]
93
+
94
+ const scanAdvancedOptionDefinitionsForHelp = [
95
+ ...sharedConnectionOptionDefinitions,
96
+ ...sharedCertOptionDefinitions,
88
97
  {
89
98
  name: 'project-id',
90
99
  alias: 'p',
@@ -95,55 +104,60 @@ const scanOptionDefinitions = [
95
104
  i18n.__('constantsProjectId')
96
105
  },
97
106
  {
98
- name: 'project-path',
107
+ name: 'language',
108
+ alias: 'l',
99
109
  description:
100
110
  '{bold ' +
101
111
  i18n.__('constantsOptional') +
102
112
  '}: ' +
103
- i18n.__('constantsProjectPath')
113
+ i18n.__('scanOptionsLanguageSummary')
104
114
  },
105
115
  {
106
- name: 'timeout',
107
- alias: 't',
108
- type: Number,
116
+ name: 'ff',
117
+ type: Boolean,
109
118
  description:
110
119
  '{bold ' +
111
120
  i18n.__('constantsOptional') +
112
121
  '}: ' +
113
- i18n.__('scanOptionsTimeoutSummary')
122
+ i18n.__('constantsDoNotWaitForScan')
114
123
  },
115
124
  {
116
- name: 'organization-id',
117
- alias: 'o',
125
+ name: 'label',
118
126
  description:
119
- '{bold ' +
120
- i18n.__('constantsRequired') +
121
- '}: ' +
122
- i18n.__('constantsOrganizationId')
123
- },
127
+ '{bold ' + i18n.__('constantsOptional') + '}:' + i18n.__('scanLabel')
128
+ }
129
+ ]
130
+
131
+ // CLI options that we will allow and handle
132
+ const scanOptionDefinitions = [
133
+ ...scanAdvancedOptionDefinitionsForHelp,
124
134
  {
125
- name: 'api-key',
135
+ name: 'name',
136
+ alias: 'n',
126
137
  description:
127
138
  '{bold ' +
128
- i18n.__('constantsRequired') +
139
+ i18n.__('constantsOptional') +
129
140
  '}: ' +
130
- i18n.__('constantsApiKey')
141
+ i18n.__('constantsProjectName')
131
142
  },
132
143
  {
133
- name: 'authorization',
144
+ name: 'file',
145
+ alias: 'f',
134
146
  description:
135
147
  '{bold ' +
136
- i18n.__('constantsRequired') +
148
+ i18n.__('constantsOptional') +
137
149
  '}: ' +
138
- i18n.__('constantsAuthorization')
150
+ i18n.__('scanOptionsFileNameSummary')
139
151
  },
140
152
  {
141
- name: 'host',
153
+ name: 'timeout',
154
+ alias: 't',
155
+ type: Number,
142
156
  description:
143
157
  '{bold ' +
144
- i18n.__('constantsRequired') +
158
+ i18n.__('constantsOptional') +
145
159
  '}: ' +
146
- i18n.__('constantsHostId')
160
+ i18n.__('scanOptionsTimeoutSummary')
147
161
  },
148
162
  {
149
163
  name: 'fail',
@@ -163,15 +177,6 @@ const scanOptionDefinitions = [
163
177
  '}: ' +
164
178
  i18n.__('constantsSeverity')
165
179
  },
166
- {
167
- name: 'ff',
168
- type: Boolean,
169
- description:
170
- '{bold ' +
171
- i18n.__('constantsOptional') +
172
- '}: ' +
173
- i18n.__('constantsDoNotWaitForScan')
174
- },
175
180
  {
176
181
  name: 'verbose',
177
182
  alias: 'v',
@@ -188,11 +193,6 @@ const scanOptionDefinitions = [
188
193
  description:
189
194
  '{bold ' + i18n.__('constantsOptional') + '}:' + i18n.__('constantsSave')
190
195
  },
191
- {
192
- name: 'label',
193
- description:
194
- '{bold ' + i18n.__('constantsOptional') + '}:' + i18n.__('scanLabel')
195
- },
196
196
  {
197
197
  name: 'help',
198
198
  alias: 'h',
@@ -207,14 +207,6 @@ const scanOptionDefinitions = [
207
207
  name: 'experimental',
208
208
  alias: 'e',
209
209
  type: Boolean
210
- },
211
- {
212
- name: 'application-name',
213
- description:
214
- '{bold ' +
215
- i18n.__('constantsOptional') +
216
- '}: ' +
217
- i18n.__('constantsApplicationName')
218
210
  }
219
211
  ]
220
212
 
@@ -241,8 +233,9 @@ const configOptionDefinitions = [
241
233
  }
242
234
  ]
243
235
 
244
- const auditOptionDefinitions = [
245
- ...sharedOptionDefinitions,
236
+ const auditAdvancedOptionDefinitionsForHelp = [
237
+ ...sharedConnectionOptionDefinitions,
238
+ ...sharedCertOptionDefinitions,
246
239
  {
247
240
  name: 'application-id',
248
241
  description:
@@ -259,39 +252,11 @@ const auditOptionDefinitions = [
259
252
  '}: ' +
260
253
  i18n.__('constantsApplicationName')
261
254
  },
262
- {
263
- name: 'file',
264
- alias: 'f',
265
- defaultValue: process.cwd().concat('/'),
266
- description:
267
- '{bold ' +
268
- i18n.__('constantsOptional') +
269
- '}: ' +
270
- i18n.__('constantsFilePath')
271
- },
272
- {
273
- name: 'fail',
274
- type: Boolean,
275
- description:
276
- '{bold ' +
277
- i18n.__('constantsOptional') +
278
- '}: ' +
279
- i18n.__('failOptionMessage')
280
- },
281
- {
282
- name: 'severity',
283
- type: severity => parseSeverity(severity),
284
- description:
285
- '{bold ' +
286
- i18n.__('constantsOptional') +
287
- '}: ' +
288
- i18n.__('constantsSeverity')
289
- },
290
255
  {
291
256
  name: 'app-groups',
292
257
  description:
293
258
  '{bold ' +
294
- i18n.__('constantsOptionalForCatalogue') +
259
+ i18n.__('constantsOptional') +
295
260
  '}: ' +
296
261
  i18n.__('constantsAppGroups')
297
262
  },
@@ -322,54 +287,58 @@ const auditOptionDefinitions = [
322
287
  '{bold ' + i18n.__('constantsOptional') + '}: ' + i18n.__('constantsCode')
323
288
  },
324
289
  {
325
- name: 'ignore-dev',
326
- type: Boolean,
327
- alias: 'i',
290
+ name: 'maven-settings-path',
328
291
  description:
329
292
  '{bold ' +
330
293
  i18n.__('constantsOptional') +
331
294
  '}: ' +
332
- i18n.__('constantsIgnoreDev')
333
- },
334
- {
335
- name: 'maven-settings-path'
336
- },
337
- {
338
- name: 'fingerprint',
339
- type: Boolean
340
- },
295
+ i18n.__('constantsMavenSettingsPath')
296
+ }
297
+ ]
298
+
299
+ const auditOptionDefinitions = [
300
+ ...auditAdvancedOptionDefinitionsForHelp,
341
301
  {
342
- name: 'organization-id',
343
- alias: 'o',
302
+ name: 'file',
303
+ alias: 'f',
304
+ defaultValue: process.cwd().concat('/'),
344
305
  description:
345
306
  '{bold ' +
346
- i18n.__('constantsRequired') +
307
+ i18n.__('constantsOptional') +
347
308
  '}: ' +
348
- i18n.__('constantsOrganizationId')
309
+ i18n.__('constantsFilePath')
349
310
  },
350
311
  {
351
- name: 'api-key',
312
+ name: 'fail',
313
+ type: Boolean,
352
314
  description:
353
315
  '{bold ' +
354
- i18n.__('constantsRequired') +
316
+ i18n.__('constantsOptional') +
355
317
  '}: ' +
356
- i18n.__('constantsApiKey')
318
+ i18n.__('failOptionMessage')
357
319
  },
358
320
  {
359
- name: 'authorization',
321
+ name: 'severity',
322
+ type: severity => parseSeverity(severity),
360
323
  description:
361
324
  '{bold ' +
362
- i18n.__('constantsRequired') +
325
+ i18n.__('constantsOptional') +
363
326
  '}: ' +
364
- i18n.__('constantsAuthorization')
327
+ i18n.__('constantsSeverity')
365
328
  },
366
329
  {
367
- name: 'host',
330
+ name: 'ignore-dev',
331
+ type: Boolean,
332
+ alias: 'i',
368
333
  description:
369
334
  '{bold ' +
370
- i18n.__('constantsRequired') +
335
+ i18n.__('constantsOptional') +
371
336
  '}: ' +
372
- i18n.__('constantsHostId')
337
+ i18n.__('constantsIgnoreDev')
338
+ },
339
+ {
340
+ name: 'fingerprint',
341
+ type: Boolean
373
342
  },
374
343
  {
375
344
  name: 'save',
@@ -459,6 +428,10 @@ const mainUsageGuide = commandLineUsage([
459
428
  { name: i18n.__('helpName'), summary: i18n.__('helpSummary') }
460
429
  ]
461
430
  },
431
+ {
432
+ header: i18n.__('constantsAdvancedOptions'),
433
+ optionList: sharedCertOptionDefinitions
434
+ },
462
435
  {
463
436
  header: i18n.__('configHeader2'),
464
437
  content: [
@@ -478,6 +451,8 @@ module.exports = {
478
451
  scanOptionDefinitions,
479
452
  auditOptionDefinitions,
480
453
  authOptionDefinitions,
481
- configOptionDefinitions
454
+ configOptionDefinitions,
455
+ scanAdvancedOptionDefinitionsForHelp,
456
+ auditAdvancedOptionDefinitionsForHelp
482
457
  }
483
458
  }
@@ -34,9 +34,12 @@ const auditUsageGuide = commandLineUsage([
34
34
  'authorization',
35
35
  'host',
36
36
  'proxy',
37
+ 'cert',
38
+ 'cacert',
39
+ 'key',
37
40
  'help',
38
41
  'ff',
39
- 'ignore-cert-errors',
42
+ 'cert-self-signed',
40
43
  'verbose',
41
44
  'debug',
42
45
  'experimental',
@@ -49,9 +52,15 @@ const auditUsageGuide = commandLineUsage([
49
52
  'app-groups',
50
53
  'metadata',
51
54
  'track',
52
- 'fingerprint'
55
+ 'fingerprint',
56
+ 'branch'
53
57
  ]
54
58
  },
59
+ {
60
+ header: i18n.__('constantsAdvancedOptions'),
61
+ optionList:
62
+ constants.commandLineDefinitions.auditAdvancedOptionDefinitionsForHelp
63
+ },
55
64
  commonHelpLinks()[0],
56
65
  commonHelpLinks()[1]
57
66
  ])
@@ -64,6 +64,8 @@ const processSca = async config => {
64
64
  config.file
65
65
  )
66
66
 
67
+ autoDetection.dealWithMultiJava(filesFound)
68
+
67
69
  if (filesFound.length > 1 && pathWithFile) {
68
70
  filesFound = filesFound.filter(i =>
69
71
  Object.values(i)[0].includes(path.basename(config.fileName))
@@ -6,7 +6,7 @@ const { AUTH_CALLBACK_URL } = require('../constants/constants')
6
6
  function HTTPClient(config) {
7
7
  const apiKey = config.apiKey
8
8
  const authToken = config.authorization
9
- this.rejectUnauthorized = !config.ignoreCertErrors
9
+ this.rejectUnauthorized = !config.certSelfSigned
10
10
 
11
11
  const superApiKey = config.superApiKey
12
12
  const superAuthToken = config.superAuthorization
@@ -48,6 +48,22 @@ const maxAppError = () => {
48
48
  process.exit(1)
49
49
  }
50
50
 
51
+ const parametersError = () => {
52
+ generalError(
53
+ `Values not recognised`,
54
+ 'Check your command & keys again for hidden characters.\nFor more information use contrast help.'
55
+ )
56
+ process.exit(1)
57
+ }
58
+
59
+ const invalidHostNameError = () => {
60
+ generalError(
61
+ `Invalid host`,
62
+ 'Check that the host parameter does not include a trailing "/".'
63
+ )
64
+ process.exit(1)
65
+ }
66
+
51
67
  const failOptionError = () => {
52
68
  console.log(
53
69
  '\n ******************************** ' +
@@ -122,5 +138,7 @@ module.exports = {
122
138
  snapshotFailureError,
123
139
  vulnerabilitiesFailureError,
124
140
  reportFailureError,
125
- maxAppError
141
+ maxAppError,
142
+ parametersError,
143
+ invalidHostNameError
126
144
  }
@@ -14,7 +14,7 @@ const HIGH = 'HIGH'
14
14
  const CRITICAL = 'CRITICAL'
15
15
  // App
16
16
  const APP_NAME = 'contrast'
17
- const APP_VERSION = '1.0.17'
17
+ const APP_VERSION = '1.0.18'
18
18
  const TIMEOUT = 120000
19
19
  const HIGH_COLOUR = '#ff9900'
20
20
  const CRITICAL_COLOUR = '#e35858'