@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
@@ -1,18 +1,40 @@
1
1
  import { getAuditConfig } from './auditConfig'
2
2
  import { auditUsageGuide } from './help'
3
3
  import { processSca } from '../scan/sca/scaAnalysis'
4
+ import { sendTelemetryConfigAsObject } from '../../telemetry/telemetry'
5
+ import { ContrastConf } from '../../utils/getConfig'
6
+ import chalk from 'chalk'
4
7
 
5
8
  export type parameterInput = string[]
6
9
 
7
- export const processAudit = async (argv: parameterInput) => {
10
+ export const processAudit = async (
11
+ contrastConf: ContrastConf,
12
+ argv: parameterInput
13
+ ) => {
8
14
  if (argv.indexOf('--help') != -1) {
9
15
  printHelpMessage()
10
16
  process.exit(0)
11
17
  }
12
- const config = getAuditConfig(argv)
18
+
19
+ const config = await getAuditConfig(contrastConf, 'audit', argv)
13
20
  await processSca(config)
21
+ postRunMessage()
22
+ await sendTelemetryConfigAsObject(
23
+ config,
24
+ 'audit',
25
+ argv,
26
+ 'SUCCESS',
27
+ // @ts-ignore
28
+ config.language
29
+ )
14
30
  }
15
31
 
16
32
  const printHelpMessage = () => {
17
33
  console.log(auditUsageGuide)
18
34
  }
35
+
36
+ const postRunMessage = () => {
37
+ console.log('\n' + chalk.underline.bold('Other Codesec Features:'))
38
+ console.log("'contrast scan' to run CodeSec’s industry leading SAST scanner")
39
+ console.log("'contrast lambda' to secure your AWS serverless functions\n")
40
+ }
@@ -16,7 +16,9 @@ const constants = require('../../constants')
16
16
  const commandLineUsage = require('command-line-usage')
17
17
 
18
18
  const processAuth = async (argv, config) => {
19
- let authParams = parsedCLIOptions.getCommandLineArgsCustom(
19
+ let authParams = await parsedCLIOptions.getCommandLineArgsCustom(
20
+ config,
21
+ 'auth',
20
22
  argv,
21
23
  constants.commandLineDefinitions.authOptionDefinitions
22
24
  )
@@ -3,9 +3,11 @@ const constants = require('../../constants')
3
3
  const commandLineUsage = require('command-line-usage')
4
4
  const i18n = require('i18n')
5
5
 
6
- const processConfig = (argv, config) => {
6
+ const processConfig = async (argv, config) => {
7
7
  try {
8
- let configParams = parsedCLIOptions.getCommandLineArgsCustom(
8
+ let configParams = await parsedCLIOptions.getCommandLineArgsCustom(
9
+ config,
10
+ 'config',
9
11
  argv,
10
12
  constants.commandLineDefinitions.configOptionDefinitions
11
13
  )
@@ -4,23 +4,51 @@ const { saveScanFile } = require('../../utils/saveFile')
4
4
  const { ScanResultsModel } = require('../../scan/models/scanResultsModel')
5
5
  const { formatScanOutput } = require('../../scan/formatScanOutput')
6
6
  const { processSca } = require('./sca/scaAnalysis')
7
+ const common = require('../../common/fail')
8
+ const { sendTelemetryConfigAsObject } = require('../../telemetry/telemetry')
9
+ const chalk = require('chalk')
10
+ const generalAPI = require('../../utils/generalAPI')
11
+
12
+ const processScan = async (contrastConf, argv) => {
13
+ let config = await scanConfig.getScanConfig(contrastConf, 'scan', argv)
14
+ let output = undefined
15
+ config.mode = await generalAPI.getMode(config)
7
16
 
8
- const processScan = async argvMain => {
9
- let config = scanConfig.getScanConfig(argvMain)
10
17
  //try SCA analysis first
11
18
  if (config.experimental) {
12
- await processSca(config)
19
+ await processSca(config, argv)
13
20
  }
14
21
 
15
22
  let scanResults = new ScanResultsModel(await startScan(config))
23
+ await sendTelemetryConfigAsObject(
24
+ config,
25
+ 'scan',
26
+ argv,
27
+ 'SUCCESS',
28
+ scanResults.scanDetail.language
29
+ )
16
30
 
17
31
  if (scanResults.scanResultsInstances !== undefined) {
18
- formatScanOutput(scanResults)
32
+ output = formatScanOutput(scanResults)
19
33
  }
20
34
 
21
35
  if (config.save !== undefined) {
22
36
  await saveScanFile(config, scanResults)
23
37
  }
38
+
39
+ if (config.fail) {
40
+ common.processFail(config, output)
41
+ }
42
+
43
+ postRunMessage()
44
+ }
45
+
46
+ const postRunMessage = () => {
47
+ console.log('\n' + chalk.underline.bold('Other Codesec Features:'))
48
+ console.log(
49
+ "'contrast audit' to find vulnerabilities in your open source dependencies"
50
+ )
51
+ console.log("'contrast lambda' to secure your AWS serverless functions\n")
24
52
  }
25
53
 
26
54
  module.exports = {
@@ -1,6 +1,7 @@
1
1
  const autoDetection = require('../../../scan/autoDetection')
2
2
  const javaAnalysis = require('../../../scaAnalysis/java')
3
3
  const treeUpload = require('../../../scaAnalysis/common/treeUpload')
4
+ const scaUpload = require('../../../scaAnalysis/common/scaServicesUpload')
4
5
  const auditController = require('../../audit/auditController')
5
6
  const {
6
7
  supportedLanguages: { JAVA, GO, PYTHON, RUBY, JAVASCRIPT, NODE, PHP, DOTNET }
@@ -21,19 +22,29 @@ const {
21
22
  const i18n = require('i18n')
22
23
  const {
23
24
  vulnerabilityReportV2
24
- } = require('../../../audit/languageAnalysisEngine/report/reportingFeature')
25
+ } = require('../../../audit/report/reportingFeature')
25
26
  const auditSave = require('../../../audit/save')
26
27
  const { dotNetAnalysis } = require('../../../scaAnalysis/dotnet')
28
+ const { auditUsageGuide } = require('../../audit/help')
27
29
  const rootFile = require('../../../audit/languageAnalysisEngine/getProjectRootFilenames')
28
30
  const path = require('path')
31
+ const generalAPI = require('../../../utils/generalAPI')
32
+
29
33
  const processSca = async config => {
34
+ config.mode = await generalAPI.getMode(config)
35
+
30
36
  const startTime = performance.now()
31
37
  let filesFound
32
38
 
39
+ if (config.help) {
40
+ console.log(auditUsageGuide)
41
+ process.exit(0)
42
+ }
43
+
33
44
  const projectStats = await rootFile.getProjectStats(config.file)
34
45
  let pathWithFile = projectStats.isFile()
35
46
 
36
- let fileName = config.file
47
+ config.fileName = config.file
37
48
  config.file = pathWithFile
38
49
  ? rootFile.getDirectoryFromPathGiven(config.file).concat('/')
39
50
  : config.file
@@ -42,7 +53,7 @@ const processSca = async config => {
42
53
 
43
54
  if (filesFound.length > 1 && pathWithFile) {
44
55
  filesFound = filesFound.filter(i =>
45
- Object.values(i)[0].includes(path.basename(fileName))
56
+ Object.values(i)[0].includes(path.basename(config.fileName))
46
57
  )
47
58
  }
48
59
 
@@ -71,7 +82,7 @@ const processSca = async config => {
71
82
  messageToSend = rubyAnalysis(config, filesFound[0])
72
83
  config.language = RUBY
73
84
  break
74
- case 'PHP':
85
+ case PHP:
75
86
  messageToSend = phpAnalysis.phpAnalysis(config, filesFound[0])
76
87
  config.language = PHP
77
88
  break
@@ -93,6 +104,10 @@ const processSca = async config => {
93
104
  config.applicationId = await auditController.dealWithNoAppId(config)
94
105
  }
95
106
 
107
+ // if (config.experimental) {
108
+ // await scaUpload.scaTreeUpload(messageToSend, config)
109
+ // } else
110
+ // {
96
111
  console.log('') //empty log for space before spinner
97
112
  //send message to TS
98
113
  const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'))
@@ -120,6 +135,7 @@ const processSca = async config => {
120
135
  console.log(
121
136
  `----- completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`
122
137
  )
138
+ // }
123
139
  } else {
124
140
  if (filesFound.length === 0) {
125
141
  console.log(i18n.__('languageAnalysisNoLanguage'))
@@ -127,7 +143,9 @@ const processSca = async config => {
127
143
  throw new Error()
128
144
  } else {
129
145
  throw new Error(
130
- 'multiple language files detected, please use --file to specify a directory or the file where dependencies are declared'
146
+ `multiple language files detected \n` +
147
+ JSON.stringify(filesFound) +
148
+ `\nplease use --file to audit one language only. Example: contrast audit --file package-lock.json`
131
149
  )
132
150
  }
133
151
  }
@@ -171,9 +171,9 @@ HTTPClient.prototype.getScanProjectById = function getScanProjectById(config) {
171
171
  return requestUtils.sendRequest({ method: 'get', options })
172
172
  }
173
173
 
174
- HTTPClient.prototype.getGlobalProperties = function getGlobalProperties() {
174
+ HTTPClient.prototype.getGlobalProperties = function getGlobalProperties(host) {
175
175
  const options = _.cloneDeep(this.requestOptions)
176
- let url = createGlobalPropertiesUrl(options.uri)
176
+ let url = createGlobalPropertiesUrl(host)
177
177
  options.url = url
178
178
  return requestUtils.sendRequest({ method: 'get', options })
179
179
  }
@@ -212,9 +212,40 @@ HTTPClient.prototype.sendSnapshot = function sendSnapshot(requestBody, config) {
212
212
  let url = createSnapshotURL(config)
213
213
  options.url = url
214
214
  options.body = requestBody
215
+
215
216
  return requestUtils.sendRequest({ method: 'post', options })
216
217
  }
217
218
 
219
+ HTTPClient.prototype.scaServiceIngest = function scaServiceIngest(
220
+ requestBody,
221
+ config
222
+ ) {
223
+ const options = _.cloneDeep(this.requestOptions)
224
+ let url = createScaServiceIngestURL(config)
225
+ options.url = url
226
+ options.body = requestBody
227
+ return requestUtils.sendRequest({ method: 'post', options })
228
+ }
229
+ HTTPClient.prototype.scaServiceReport = function scaServiceReport(
230
+ config,
231
+ reportId
232
+ ) {
233
+ const options = _.cloneDeep(this.requestOptions)
234
+ let url = createScaServiceReportURL(config, reportId)
235
+ options.url = url
236
+ return requestUtils.sendRequest({ method: 'get', options })
237
+ }
238
+
239
+ HTTPClient.prototype.scaServiceReportStatus = function scaServiceReport(
240
+ config,
241
+ reportId
242
+ ) {
243
+ const options = _.cloneDeep(this.requestOptions)
244
+ let url = createScaServiceReportStatusURL(config, reportId)
245
+ options.url = url
246
+ return requestUtils.sendRequest({ method: 'get', options })
247
+ }
248
+
218
249
  HTTPClient.prototype.getReportById = function getReportById(config, reportId) {
219
250
  const options = _.cloneDeep(this.requestOptions)
220
251
  if (config.ignoreDev) {
@@ -346,6 +377,16 @@ HTTPClient.prototype.getLatestVersion = function getLatestVersion() {
346
377
  return requestUtils.sendRequest({ method: 'get', options })
347
378
  }
348
379
 
380
+ HTTPClient.prototype.postTelemetry = function postTelemetry(
381
+ config,
382
+ requestBody
383
+ ) {
384
+ const options = _.cloneDeep(this.requestOptions)
385
+ options.url = createTelemetryEventUrl(config)
386
+ options.body = requestBody
387
+ return requestUtils.sendRequest({ method: 'post', options })
388
+ }
389
+
349
390
  // analytics
350
391
 
351
392
  HTTPClient.prototype.postAnalyticsFunction = function (config, provider, body) {
@@ -405,6 +446,18 @@ function createSnapshotURL(config) {
405
446
  return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/${config.applicationId}/snapshots`
406
447
  }
407
448
 
449
+ function createScaServiceReportURL(config, reportId) {
450
+ return ``
451
+ }
452
+
453
+ function createScaServiceReportStatusURL(config, reportId) {
454
+ return ``
455
+ }
456
+
457
+ function createScaServiceIngestURL(config) {
458
+ return ``
459
+ }
460
+
408
461
  const createAppCreateURL = config => {
409
462
  return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/create`
410
463
  }
@@ -439,6 +492,10 @@ function createSbomUrl(config, type) {
439
492
  return `${config.host}/Contrast/api/ng/${config.organizationId}/applications/${config.applicationId}/libraries/sbom/${type}`
440
493
  }
441
494
 
495
+ function createTelemetryEventUrl(config) {
496
+ return `${config.host}/Contrast/api/sast/organizations/${config.organizationId}/cli`
497
+ }
498
+
442
499
  module.exports = HTTPClient
443
500
  module.exports.pollForAuthUrl = pollForAuthUrl
444
501
  module.exports.getServerlessHost = getServerlessHost
@@ -0,0 +1,13 @@
1
+ import i18n from 'i18n'
2
+
3
+ export function commonHelpLinks() {
4
+ return {
5
+ header: i18n.__('commonHelpHeader'),
6
+ content: [
7
+ i18n.__('commonHelpCheckOutHeader') + i18n.__('commonHelpCheckOutText'),
8
+ i18n.__('commonHelpLearnMoreHeader') + i18n.__('commonHelpLearnMoreText'),
9
+ i18n.__('commonHelpJoinDiscussionHeader') +
10
+ i18n.__('commonHelpJoinDiscussionText')
11
+ ]
12
+ }
13
+ }
@@ -0,0 +1,79 @@
1
+ const i18n = require('i18n')
2
+
3
+ const processFail = (config, reportResults) => {
4
+ if (config.severity !== undefined) {
5
+ if (
6
+ reportResults[config.severity] !== undefined &&
7
+ isSeverityViolation(config.severity, reportResults)
8
+ ) {
9
+ failPipeline('failSeverityOptionErrorMessage')
10
+ }
11
+ }
12
+
13
+ if (config.severity === undefined && reportResults.total > 0) {
14
+ failPipeline('failThresholdOptionErrorMessage')
15
+ }
16
+ }
17
+
18
+ const isSeverityViolation = (severity, reportResults) => {
19
+ let count = 0
20
+ switch (severity) {
21
+ case 'critical':
22
+ count += reportResults.critical
23
+ break
24
+ case 'high':
25
+ count += reportResults.high + reportResults.critical
26
+ break
27
+ case 'medium':
28
+ count +=
29
+ reportResults.medium + reportResults.high + reportResults.critical
30
+ break
31
+ case 'low':
32
+ count +=
33
+ reportResults.high +
34
+ reportResults.critical +
35
+ reportResults.medium +
36
+ reportResults.low
37
+ break
38
+ case 'note':
39
+ if (reportResults.note == reportResults.total) {
40
+ count = 0
41
+ } else {
42
+ count = reportResults.total
43
+ }
44
+ break
45
+ default:
46
+ count = 0
47
+ }
48
+ return count > 0
49
+ }
50
+
51
+ const failPipeline = (message = '') => {
52
+ console.log(
53
+ '\n ******************************** ' +
54
+ i18n.__('snapshotFailureHeader') +
55
+ ' *********************************\n' +
56
+ i18n.__(message)
57
+ )
58
+ process.exit(2)
59
+ }
60
+
61
+ const parseSeverity = severity => {
62
+ const severities = ['NOTE', 'LOW', 'MEDIUM', 'HIGH', 'CRITICAL']
63
+ if (severities.includes(severity.toUpperCase())) {
64
+ return severity.toLowerCase()
65
+ } else {
66
+ console.log(
67
+ severity +
68
+ ' Not recognised as a severity type please use LOW, MEDIUM, HIGH, CRITICAL, NOTE'
69
+ )
70
+ return undefined
71
+ }
72
+ }
73
+
74
+ module.exports = {
75
+ failPipeline,
76
+ processFail,
77
+ isSeverityViolation,
78
+ parseSeverity
79
+ }
@@ -6,7 +6,7 @@ import commonApi from '../utils/commonApi'
6
6
  import { constants } from 'http2'
7
7
  import { ContrastConf } from '../utils/getConfig'
8
8
 
9
- const getLatestVersion = async (config: any) => {
9
+ export const getLatestVersion = async (config: ContrastConf) => {
10
10
  const client = commonApi.getHttpClient(config)
11
11
  try {
12
12
  const res = await client.getLatestVersion()
@@ -14,18 +14,28 @@ const getLatestVersion = async (config: any) => {
14
14
  return res.body
15
15
  }
16
16
  } catch (e) {
17
- return
17
+ return undefined
18
18
  }
19
19
  }
20
20
 
21
- // @ts-ignore
22
21
  export async function findLatestCLIVersion(config: ContrastConf) {
23
- const messageHidden = config.get('updateMessageHidden') as boolean
22
+ const isCI = process.env.CONTRAST_CODESEC_CI
23
+ ? JSON.parse(process.env.CONTRAST_CODESEC_CI.toLowerCase())
24
+ : false
24
25
 
25
- if (!messageHidden) {
26
- let latestCLIVersion: string = await getLatestVersion(config)
27
- //strip key
28
- latestCLIVersion = latestCLIVersion.substring(8)
26
+ if (!isCI) {
27
+ let latestCLIVersion = await getLatestVersion(config)
28
+
29
+ if (latestCLIVersion === undefined) {
30
+ config.set('numOfRuns', 0)
31
+ console.log(
32
+ 'Failed to retrieve latest version info. Continuing execution.'
33
+ )
34
+ return
35
+ }
36
+
37
+ //strip key and remove new lines
38
+ latestCLIVersion = latestCLIVersion.substring(8).replace('\n', '')
29
39
 
30
40
  if (semver.lt(APP_VERSION, latestCLIVersion)) {
31
41
  const updateAvailableMessage = `Update available ${chalk.yellow(
@@ -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.10'
17
+ const APP_VERSION = '1.0.13'
18
18
  const TIMEOUT = 120000
19
19
  const HIGH_COLOUR = '#ff9900'
20
20
  const CRITICAL_COLOUR = '#e35858'
@@ -32,7 +32,7 @@ const AUTH_CALLBACK_URL = 'https://cli-auth-api.contrastsecurity.com'
32
32
  const SARIF_FILE = 'SARIF'
33
33
  const SBOM_CYCLONE_DX_FILE = 'cyclonedx'
34
34
  const SBOM_SPDX_FILE = 'spdx'
35
- const CE_URL = 'https://ce.contrastsecurity.com/'
35
+ const CE_URL = 'https://ce.contrastsecurity.com'
36
36
 
37
37
  module.exports = {
38
38
  supportedLanguages: { NODE, DOTNET, JAVA, RUBY, PYTHON, GO, PHP, JAVASCRIPT },
@@ -26,8 +26,7 @@ const en_locales = () => {
26
26
  unauthenticatedErrorMessage:
27
27
  'Please check the following keys are correct:\n--organization-id, --api-key or --authorization',
28
28
  badRequestErrorHeader: '400 error - Bad Request',
29
- badRequestErrorMessage:
30
- 'Please check the following key is correct: \n--application-id',
29
+ badRequestErrorMessage: 'Please check your parameters and try again',
31
30
  badRequestCatalogueErrorMessage:
32
31
  'The application name already exists, please use a unique name',
33
32
  forbiddenRequestErrorHeader: '403 error - Forbidden',
@@ -121,9 +120,11 @@ const en_locales = () => {
121
120
  'The name of the application cataloged by Contrast UI',
122
121
  constantsCatalogueApplication:
123
122
  'Provide this if you want to catalogue an application',
123
+ failOptionErrorMessage:
124
+ ' FAIL - CVEs have been detected that match at least the cve_severity option specified.',
124
125
  constantsLanguage:
125
126
  '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',
126
- 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.`,
127
+ constantsFilePath: `Specify a directory or the file where dependencies are declared. (By default, CodeSec will search for project files in the current directory.)`,
127
128
  constantsSilent: 'Silences JSON output.',
128
129
  constantsAppGroups:
129
130
  'Assign your application to one or more pre-existing groups when using the catalogue command. Group lists should be comma separated.',
@@ -142,8 +143,9 @@ const en_locales = () => {
142
143
  constantsReport: 'Display vulnerability information for this application',
143
144
  constantsFail:
144
145
  'Set the process to fail if this option is set in combination with --cve_severity.',
145
- failOptionErrorMessage:
146
- ' FAIL - CVEs have been detected that match at least the cve_severity or cve_threshold option specified.',
146
+ failThresholdOptionErrorMessage: 'More than 0 vulnerabilities found',
147
+ failSeverityOptionErrorMessage:
148
+ ' FAIL - Results detected vulnerabilities over accepted severity level',
147
149
  constantsSeverity:
148
150
  '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.',
149
151
  constantsCount: 'The number of CVEs that must be exceeded to fail a build',
@@ -315,7 +317,7 @@ const en_locales = () => {
315
317
  scanOptionsVerboseSummary: ' Returns extended information to the terminal.',
316
318
  authSuccessMessage: 'Authentication successful',
317
319
  runAuthSuccessMessage:
318
- "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.",
320
+ "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.",
319
321
  authWaitingMessage: 'Waiting for auth...',
320
322
  authTimedOutMessage: 'Auth Timed out, try again',
321
323
  zipErrorScan:
@@ -414,7 +416,8 @@ const en_locales = () => {
414
416
  auditOptionsSaveDescription:
415
417
  'Generate and save an SBOM (Software Bill of Materials)\n',
416
418
  auditOptionsSaveOptionsDescription:
417
- 'Valid options are: spdx, cyclonedx (cycloneDX is the default format)',
419
+ 'Valid options are: --save spdx and --save cyclonedx (CycloneDX is the default format.)',
420
+ 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.`,
418
421
  scanNotCompleted:
419
422
  'Scan not completed. Check for framework and language support here: %s',
420
423
  auditNotCompleted: 'audit not completed. Please try again',
@@ -437,6 +440,15 @@ const en_locales = () => {
437
440
  auditReportFailureMessage: 'Unable to generate library report',
438
441
  auditSCAAnalysisBegins: 'Contrast SCA audit started',
439
442
  auditSCAAnalysisComplete: 'Contrast audit complete',
443
+ commonHelpHeader: 'Need More Help?',
444
+ commonHelpCheckOutHeader: chalk.hex('#9DC184')('Check out:'),
445
+ commonHelpCheckOutText: ' https://support.contrastsecurity.com',
446
+ commonHelpLearnMoreHeader: chalk.hex('#9DC184')('Learn more at:'),
447
+ commonHelpLearnMoreText: ' https://developer.contrastsecurity.com',
448
+ commonHelpJoinDiscussionHeader: chalk.hex('#9DC184')(
449
+ 'Join the discussion:'
450
+ ),
451
+ commonHelpJoinDiscussionText: ' https://dev.to/codesec',
440
452
  ...lambda
441
453
  }
442
454
  }
package/src/constants.js CHANGED
@@ -1,6 +1,8 @@
1
1
  const commandLineUsage = require('command-line-usage')
2
2
  const i18n = require('i18n')
3
3
  const { en_locales } = require('./constants/locales.js')
4
+ const { parseSeverity } = require('./common/fail')
5
+ const { commonHelpLinks } = require('./common/commonHelp')
4
6
 
5
7
  i18n.configure({
6
8
  staticCatalog: {
@@ -106,6 +108,24 @@ const scanOptionDefinitions = [
106
108
  '}: ' +
107
109
  i18n.__('constantsProxyServer')
108
110
  },
111
+ {
112
+ name: 'fail',
113
+ type: Boolean,
114
+ description:
115
+ '{bold ' +
116
+ i18n.__('constantsOptional') +
117
+ '}: ' +
118
+ i18n.__('failOptionErrorMessage')
119
+ },
120
+ {
121
+ name: 'severity',
122
+ type: severity => parseSeverity(severity),
123
+ description:
124
+ '{bold ' +
125
+ i18n.__('constantsOptional') +
126
+ '}: ' +
127
+ i18n.__('constantsSeverity')
128
+ },
109
129
  {
110
130
  name: 'ff',
111
131
  type: Boolean,
@@ -220,6 +240,24 @@ const auditOptionDefinitions = [
220
240
  '}: ' +
221
241
  i18n.__('constantsFilePath')
222
242
  },
243
+ {
244
+ name: 'fail',
245
+ type: Boolean,
246
+ description:
247
+ '{bold ' +
248
+ i18n.__('constantsOptional') +
249
+ '}: ' +
250
+ i18n.__('failOptionErrorMessage')
251
+ },
252
+ {
253
+ name: 'severity',
254
+ type: severity => parseSeverity(severity),
255
+ description:
256
+ '{bold ' +
257
+ i18n.__('constantsOptional') +
258
+ '}: ' +
259
+ i18n.__('constantsSeverity')
260
+ },
223
261
  {
224
262
  name: 'app-groups',
225
263
  description:
@@ -257,6 +295,7 @@ const auditOptionDefinitions = [
257
295
  {
258
296
  name: 'ignore-dev',
259
297
  type: Boolean,
298
+ alias: 'i',
260
299
  description:
261
300
  '{bold ' +
262
301
  i18n.__('constantsOptional') +
@@ -293,7 +332,6 @@ const auditOptionDefinitions = [
293
332
  },
294
333
  {
295
334
  name: 'host',
296
- alias: 'h',
297
335
  description:
298
336
  '{bold ' +
299
337
  i18n.__('constantsRequired') +
@@ -341,6 +379,11 @@ const auditOptionDefinitions = [
341
379
  i18n.__('constantsOptional') +
342
380
  '}: ' +
343
381
  i18n.__('scanOptionsTimeoutSummary')
382
+ },
383
+ {
384
+ name: 'help',
385
+ alias: 'h',
386
+ type: Boolean
344
387
  }
345
388
  ]
346
389
 
@@ -368,16 +411,13 @@ const mainUsageGuide = commandLineUsage([
368
411
  { name: i18n.__('helpName'), summary: i18n.__('helpSummary') }
369
412
  ]
370
413
  },
371
- {
372
- content:
373
- '{underline https://developer.contrastsecurity.com/} \n For technical support head to {underline https://support.contrastsecurity.com}'
374
- },
375
414
  {
376
415
  header: i18n.__('configHeader2'),
377
416
  content: [
378
417
  { name: i18n.__('clearHeader'), summary: i18n.__('clearContent') }
379
418
  ]
380
- }
419
+ },
420
+ commonHelpLinks()
381
421
  ])
382
422
 
383
423
  const mainDefinition = [{ name: 'command', defaultOption: true }]