@contrast/contrast 1.0.9 → 1.0.12

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 (108) hide show
  1. package/README.md +2 -2
  2. package/dist/audit/languageAnalysisEngine/getProjectRootFilenames.js +17 -17
  3. package/dist/audit/{languageAnalysisEngine/report → report}/commonReportingFunctions.js +56 -35
  4. package/dist/audit/report/models/reportGuidanceModel.js +6 -0
  5. package/dist/audit/{languageAnalysisEngine/report → report}/models/reportLibraryModel.js +0 -0
  6. package/dist/audit/{languageAnalysisEngine/report → report}/models/reportListModel.js +0 -0
  7. package/dist/audit/{languageAnalysisEngine/report → report}/models/reportOutputModel.js +1 -2
  8. package/dist/audit/{languageAnalysisEngine/report → report}/models/reportSeverityModel.js +0 -0
  9. package/dist/audit/{languageAnalysisEngine/report → report}/models/severityCountModel.js +1 -0
  10. package/dist/audit/{languageAnalysisEngine/report → report}/reportingFeature.js +12 -8
  11. package/dist/audit/{languageAnalysisEngine/report → report}/utils/reportUtils.js +3 -4
  12. package/dist/commands/audit/auditConfig.js +3 -3
  13. package/dist/commands/audit/help.js +3 -1
  14. package/dist/commands/audit/processAudit.js +4 -2
  15. package/dist/commands/auth/auth.js +1 -1
  16. package/dist/commands/config/config.js +2 -2
  17. package/dist/commands/scan/processScan.js +11 -4
  18. package/dist/commands/scan/sca/scaAnalysis.js +20 -9
  19. package/dist/common/HTTPClient.js +9 -0
  20. package/dist/common/commonHelp.js +19 -0
  21. package/dist/common/errorHandling.js +2 -2
  22. package/dist/common/fail.js +66 -0
  23. package/dist/common/versionChecker.js +4 -2
  24. package/dist/constants/constants.js +2 -2
  25. package/dist/constants/locales.js +26 -11
  26. package/dist/constants.js +52 -5
  27. package/dist/index.js +5 -2
  28. package/dist/lambda/help.js +2 -3
  29. package/dist/scaAnalysis/common/scaParserForGoAndJava.js +32 -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 +3 -0
  37. package/dist/scaAnalysis/php/analysis.js +1 -1
  38. package/dist/scaAnalysis/php/index.js +12 -6
  39. package/dist/scaAnalysis/php/phpNewServicesMapper.js +62 -0
  40. package/dist/scaAnalysis/python/analysis.js +43 -5
  41. package/dist/scaAnalysis/python/index.js +7 -2
  42. package/dist/scaAnalysis/ruby/analysis.js +14 -4
  43. package/dist/scan/autoDetection.js +5 -13
  44. package/dist/scan/formatScanOutput.js +6 -5
  45. package/dist/scan/help.js +2 -3
  46. package/dist/scan/populateProjectIdAndProjectName.js +5 -0
  47. package/dist/scan/scan.js +4 -0
  48. package/dist/scan/scanConfig.js +4 -4
  49. package/dist/scan/scanResults.js +46 -3
  50. package/dist/telemetry/telemetry.js +137 -0
  51. package/dist/utils/commonApi.js +1 -1
  52. package/dist/utils/getConfig.js +2 -4
  53. package/dist/utils/parsedCLIOptions.js +3 -1
  54. package/dist/utils/requestUtils.js +7 -1
  55. package/package.json +4 -2
  56. package/src/audit/languageAnalysisEngine/getProjectRootFilenames.js +22 -29
  57. package/src/audit/{languageAnalysisEngine/report → report}/commonReportingFunctions.ts +80 -44
  58. package/src/audit/report/models/reportGuidanceModel.ts +5 -0
  59. package/src/audit/{languageAnalysisEngine/report → report}/models/reportLibraryModel.ts +0 -0
  60. package/src/audit/{languageAnalysisEngine/report → report}/models/reportListModel.ts +0 -0
  61. package/src/audit/{languageAnalysisEngine/report → report}/models/reportOutputModel.ts +1 -7
  62. package/src/audit/{languageAnalysisEngine/report → report}/models/reportSeverityModel.ts +0 -0
  63. package/src/audit/{languageAnalysisEngine/report → report}/models/severityCountModel.ts +2 -0
  64. package/src/audit/{languageAnalysisEngine/report → report}/reportingFeature.ts +16 -9
  65. package/src/audit/{languageAnalysisEngine/report → report}/utils/reportUtils.ts +4 -4
  66. package/src/commands/audit/auditConfig.ts +10 -3
  67. package/src/commands/audit/help.ts +3 -1
  68. package/src/commands/audit/processAudit.ts +16 -2
  69. package/src/commands/auth/auth.js +3 -1
  70. package/src/commands/config/config.js +4 -2
  71. package/src/commands/scan/processScan.js +18 -4
  72. package/src/commands/scan/sca/scaAnalysis.js +27 -10
  73. package/src/common/HTTPClient.js +15 -0
  74. package/src/common/commonHelp.ts +13 -0
  75. package/src/common/errorHandling.ts +2 -3
  76. package/src/common/fail.js +75 -0
  77. package/src/common/versionChecker.ts +4 -4
  78. package/src/constants/constants.js +2 -2
  79. package/src/constants/locales.js +35 -13
  80. package/src/constants.js +56 -6
  81. package/src/index.ts +17 -2
  82. package/src/lambda/help.ts +2 -3
  83. package/src/scaAnalysis/common/scaParserForGoAndJava.js +41 -0
  84. package/src/scaAnalysis/common/treeUpload.js +21 -5
  85. package/src/scaAnalysis/dotnet/analysis.js +21 -3
  86. package/src/scaAnalysis/go/goAnalysis.js +9 -2
  87. package/src/scaAnalysis/java/analysis.js +11 -6
  88. package/src/scaAnalysis/java/index.js +9 -1
  89. package/src/scaAnalysis/java/javaBuildDepsParser.js +25 -6
  90. package/src/scaAnalysis/javascript/index.js +3 -0
  91. package/src/scaAnalysis/php/analysis.js +1 -1
  92. package/src/scaAnalysis/php/index.js +12 -6
  93. package/src/scaAnalysis/php/phpNewServicesMapper.js +77 -0
  94. package/src/scaAnalysis/python/analysis.js +49 -5
  95. package/src/scaAnalysis/python/index.js +7 -2
  96. package/src/scaAnalysis/ruby/analysis.js +16 -4
  97. package/src/scan/autoDetection.js +6 -13
  98. package/src/scan/formatScanOutput.ts +7 -5
  99. package/src/scan/help.js +2 -3
  100. package/src/scan/populateProjectIdAndProjectName.js +5 -1
  101. package/src/scan/scan.ts +4 -0
  102. package/src/scan/scanConfig.js +6 -4
  103. package/src/scan/scanResults.js +52 -3
  104. package/src/telemetry/telemetry.ts +154 -0
  105. package/src/utils/commonApi.js +1 -1
  106. package/src/utils/getConfig.ts +2 -11
  107. package/src/utils/parsedCLIOptions.js +14 -1
  108. package/src/utils/requestUtils.js +8 -1
@@ -1,4 +1,4 @@
1
- import { getHttpClient, handleResponseErrors } from '../../../utils/commonApi'
1
+ import { getHttpClient, handleResponseErrors } from '../../utils/commonApi'
2
2
  import {
3
3
  ReportCompositeKey,
4
4
  ReportList,
@@ -22,15 +22,17 @@ import {
22
22
  ReportOutputModel
23
23
  } from './models/reportOutputModel'
24
24
  import {
25
+ CE_URL,
25
26
  CRITICAL_COLOUR,
26
27
  HIGH_COLOUR,
27
28
  LOW_COLOUR,
28
29
  MEDIUM_COLOUR,
29
30
  NOTE_COLOUR
30
- } from '../../../constants/constants'
31
+ } from '../../constants/constants'
31
32
  import Table from 'cli-table3'
33
+ import { ReportGuidanceModel } from './models/reportGuidanceModel'
32
34
 
33
- export const createSummaryMessage = (
35
+ export const createSummaryMessageTop = (
34
36
  numberOfVulnerableLibraries: number,
35
37
  numberOfCves: number
36
38
  ) => {
@@ -41,6 +43,14 @@ export const createSummaryMessage = (
41
43
  )
42
44
  }
43
45
 
46
+ export const createSummaryMessageBottom = (
47
+ numberOfVulnerableLibraries: number
48
+ ) => {
49
+ numberOfVulnerableLibraries === 1
50
+ ? console.log(`Found 1 vulnerable library`)
51
+ : console.log(`Found ${numberOfVulnerableLibraries} vulnerable libraries`)
52
+ }
53
+
44
54
  export const getReport = async (config: any, reportId: string) => {
45
55
  const client = getHttpClient(config)
46
56
  return client
@@ -86,7 +96,7 @@ export const printFormattedOutput = (
86
96
  numberOfCves: number,
87
97
  guidance: any
88
98
  ) => {
89
- createSummaryMessage(numberOfVulnerableLibraries, numberOfCves)
99
+ createSummaryMessageTop(numberOfVulnerableLibraries, numberOfCves)
90
100
  console.log()
91
101
  const report = new ReportList()
92
102
 
@@ -160,7 +170,11 @@ export const printFormattedOutput = (
160
170
  numOfCVEs
161
171
  )
162
172
 
163
- const advice = gatherRemediationAdvice(guidance, reportModel)
173
+ const advice = gatherRemediationAdvice(
174
+ guidance,
175
+ libraryName,
176
+ libraryVersion
177
+ )
164
178
 
165
179
  const body = buildBody(reportModel.cveArray, advice)
166
180
 
@@ -168,7 +182,6 @@ export const printFormattedOutput = (
168
182
 
169
183
  table.push(
170
184
  reportOutputModel.body.issueMessage,
171
- reportOutputModel.body.issueMessageCves,
172
185
  reportOutputModel.body.adviceMessage
173
186
  )
174
187
 
@@ -179,7 +192,7 @@ export const printFormattedOutput = (
179
192
  console.log(table.toString() + '\n')
180
193
  }
181
194
 
182
- createSummaryMessage(numberOfVulnerableLibraries, numberOfCves)
195
+ createSummaryMessageBottom(numberOfVulnerableLibraries)
183
196
  const {
184
197
  criticalMessage,
185
198
  highMessage,
@@ -190,6 +203,15 @@ export const printFormattedOutput = (
190
203
  console.log(
191
204
  `${criticalMessage} | ${highMessage} | ${mediumMessage} | ${lowMessage} | ${noteMessage}`
192
205
  )
206
+
207
+ if (config.host !== CE_URL) {
208
+ console.log(
209
+ '\n' + chalk.bold('View your full dependency tree in Contrast:')
210
+ )
211
+ console.log(
212
+ `${config.host}/Contrast/static/ng/index.html#/${config.organizationId}/applications/${config.applicationId}/libs/dependency-tree`
213
+ )
214
+ }
193
215
  }
194
216
 
195
217
  export function buildHeader(
@@ -203,18 +225,22 @@ export function buildHeader(
203
225
  numOfCVEs > 1 ? 'vulnerabilities' : 'vulnerability'
204
226
  const formattedHeaderNum = buildFormattedHeaderNum(contrastHeaderNum)
205
227
 
206
- const vulnMessage = chalk
207
- .hex(highestSeverity.outputColour)
208
- .bold(
209
- `${formattedHeaderNum} - [${highestSeverity.severity}] ${libraryName}-${version}`
210
- )
228
+ const headerColour = chalk.hex(highestSeverity.outputColour)
229
+ const headerNumAndSeverity = headerColour(
230
+ `${formattedHeaderNum} - [${highestSeverity.severity}]`
231
+ )
232
+ const libraryNameAndVersion = headerColour.bold(`${libraryName}-${version}`)
233
+ const vulnMessage = `${headerNumAndSeverity} ${libraryNameAndVersion}`
211
234
 
212
235
  const introducesMessage = `introduces ${numOfCVEs} ${vulnerabilityPluralised}`
213
236
 
214
237
  return new ReportOutputHeaderModel(vulnMessage, introducesMessage)
215
238
  }
216
239
 
217
- export function buildBody(cveArray: ReportCVEModel[], advice: any) {
240
+ export function buildBody(
241
+ cveArray: ReportCVEModel[],
242
+ advice: ReportGuidanceModel
243
+ ) {
218
244
  const cveMessages: string[] = []
219
245
 
220
246
  findCVESeveritiesAndOrderByHighestPriority(cveArray).forEach(
@@ -233,46 +259,40 @@ export function buildBody(cveArray: ReportCVEModel[], advice: any) {
233
259
 
234
260
  const numAndSeverityType = getNumOfAndSeverityType(cveArray)
235
261
 
236
- const issueMessage = [chalk.bold('Issue'), ':', `${numAndSeverityType}`]
237
-
238
- const issueMessageCves = ['', '', cveMessages.join(', ')]
262
+ const issueMessage = [
263
+ chalk.bold('Issue'),
264
+ ':',
265
+ `${numAndSeverityType} ${cveMessages.join(', ')}`
266
+ ]
239
267
 
240
268
  //todo different advice based on remediationGuidance being available or now
241
269
  // console.log(advice)
242
270
 
243
- const displayAdvice = advice?.minimum
244
- ? `Update to version ${chalk.bold(advice.minimum)}`
245
- : `Update to latest version`
271
+ const minOrMax = advice.maximum ? advice.maximum : advice.minimum
272
+ const displayAdvice = minOrMax
273
+ ? `Change to version ${chalk.bold(minOrMax)}`
274
+ : 'No recommendation is available according to our data. Upgrade to the latest stable is the best advice we can give.'
246
275
 
247
276
  const adviceMessage = [chalk.bold('Advice'), ':', displayAdvice]
248
277
 
249
- return new ReportOutputBodyModel(
250
- issueMessage,
251
- issueMessageCves,
252
- adviceMessage
253
- )
278
+ return new ReportOutputBodyModel(issueMessage, adviceMessage)
254
279
  }
255
280
 
256
- export function gatherRemediationAdvice(guidance: any, reportModel: any) {
257
- const guidanceData = {
258
- minimum: undefined,
259
- maximum: undefined,
260
- latest: undefined
261
- }
281
+ export function gatherRemediationAdvice(
282
+ guidance: any,
283
+ libraryName: string,
284
+ libraryVersion: string
285
+ ) {
286
+ const guidanceModel = new ReportGuidanceModel()
262
287
 
263
- const data =
264
- guidance[
265
- reportModel.compositeKey.libraryName +
266
- '@' +
267
- reportModel.compositeKey.libraryVersion
268
- ]
288
+ const data = guidance[libraryName + '@' + libraryVersion]
269
289
 
270
290
  if (data) {
271
- guidanceData.minimum = data.minUpgradeVersion
272
- guidanceData.maximum = data.maxUpgradeVersion
291
+ guidanceModel.minimum = data.minUpgradeVersion
292
+ guidanceModel.maximum = data.maxUpgradeVersion
273
293
  }
274
294
 
275
- return guidanceData
295
+ return guidanceModel
276
296
  }
277
297
 
278
298
  export function buildFormattedHeaderNum(contrastHeaderNum: number) {
@@ -285,11 +305,27 @@ export function getNumOfAndSeverityType(cveArray: ReportCVEModel[]) {
285
305
  new SeverityCountModel()
286
306
  )
287
307
 
288
- const criticalMessage = critical > 0 ? `${critical} Critical` : ''
289
- const highMessage = high > 0 ? `${high} High` : ''
290
- const mediumMessage = medium > 0 ? `${medium} Medium` : ''
291
- const lowMessage = low > 0 ? `${low} Low` : ''
292
- const noteMessage = note > 0 ? `${note} Note` : ''
308
+ const criticalNumCheck = critical > 0
309
+
310
+ const highNumCheck = high > 0
311
+ const highDivider = highNumCheck ? '|' : ''
312
+
313
+ const mediumNumCheck = medium > 0
314
+ const mediumDivider = mediumNumCheck ? '|' : ''
315
+
316
+ const lowNumCheck = low > 0
317
+ const lowDivider = lowNumCheck ? '|' : ''
318
+
319
+ const noteNumCheck = low > 0
320
+ const noteDivider = noteNumCheck ? '|' : ''
321
+
322
+ const criticalMessage = criticalNumCheck
323
+ ? `${critical} Critical ${highDivider}`
324
+ : ''
325
+ const highMessage = highNumCheck ? `${high} High ${mediumDivider}` : ''
326
+ const mediumMessage = mediumNumCheck ? `${medium} Medium ${lowDivider}` : ''
327
+ const lowMessage = lowNumCheck ? `${low} Low ${noteDivider}` : ''
328
+ const noteMessage = noteNumCheck ? `${note} Note` : ''
293
329
 
294
330
  //removes/trims whitespace to single spaces
295
331
  return `${criticalMessage} ${highMessage} ${mediumMessage} ${lowMessage} ${noteMessage}`
@@ -0,0 +1,5 @@
1
+ export class ReportGuidanceModel {
2
+ minimum?: string
3
+ maximum?: string
4
+ latest?: string
5
+ }
@@ -20,16 +20,10 @@ export class ReportOutputHeaderModel {
20
20
 
21
21
  export class ReportOutputBodyModel {
22
22
  issueMessage: string[]
23
- issueMessageCves: string[]
24
23
  adviceMessage: string[]
25
24
 
26
- constructor(
27
- issueMessage: string[],
28
- issueMessageCves: string[],
29
- adviceMessage: string[]
30
- ) {
25
+ constructor(issueMessage: string[], adviceMessage: string[]) {
31
26
  this.issueMessage = issueMessage
32
- this.issueMessageCves = issueMessageCves
33
27
  this.adviceMessage = adviceMessage
34
28
  }
35
29
  }
@@ -4,6 +4,7 @@ export class SeverityCountModel {
4
4
  medium!: number
5
5
  low!: number
6
6
  note!: number
7
+ total!: number
7
8
 
8
9
  //needed as default to stop NaN when new object constructed
9
10
  constructor() {
@@ -12,6 +13,7 @@ export class SeverityCountModel {
12
13
  this.medium = 0
13
14
  this.low = 0
14
15
  this.note = 0
16
+ this.total = 0
15
17
  }
16
18
 
17
19
  get getTotal(): number {
@@ -8,7 +8,9 @@ import {
8
8
  } from './utils/reportUtils'
9
9
  import i18n from 'i18n'
10
10
  import chalk from 'chalk'
11
- import * as constants from '../../../constants/constants'
11
+ import * as constants from '../../constants/constants'
12
+ import { SeverityCountModel } from './models/severityCountModel'
13
+ import * as common from '../../common/fail'
12
14
 
13
15
  export function convertKeysToStandardFormat(config: any, guidance: any) {
14
16
  let convertedGuidance = guidance
@@ -72,6 +74,7 @@ export function formatVulnerabilityOutput(
72
74
  String(0)
73
75
  )
74
76
  )
77
+ return [false, 0, [new SeverityCountModel()]]
75
78
  } else {
76
79
  let numberOfCves = 0
77
80
  vulnerableLibraries.forEach(lib => (numberOfCves += lib.cveArray.length))
@@ -83,12 +86,13 @@ export function formatVulnerabilityOutput(
83
86
  numberOfCves,
84
87
  guidance
85
88
  )
86
-
87
- return [
88
- hasSomeVulnerabilitiesReported,
89
- numberOfCves,
90
- severityCountAllLibraries(vulnerableLibraries)
91
- ]
89
+ let severityCount = new SeverityCountModel()
90
+ severityCount = severityCountAllLibraries(
91
+ vulnerableLibraries,
92
+ severityCount
93
+ )
94
+ severityCount.total = severityCount.getTotal
95
+ return [hasSomeVulnerabilitiesReported, numberOfCves, severityCount]
92
96
  }
93
97
  }
94
98
 
@@ -97,8 +101,7 @@ export async function vulnerabilityReportV2(config: any, reportId: string) {
97
101
  const reportResponse = await getReport(config, reportId)
98
102
 
99
103
  if (reportResponse !== undefined) {
100
- const name = config.applicationName
101
- formatVulnerabilityOutput(
104
+ let output = formatVulnerabilityOutput(
102
105
  reportResponse.vulnerabilities,
103
106
  config.applicationId,
104
107
  config,
@@ -106,5 +109,9 @@ export async function vulnerabilityReportV2(config: any, reportId: string) {
106
109
  ? reportResponse.remediationGuidance
107
110
  : {}
108
111
  )
112
+
113
+ if (config.fail) {
114
+ common.processFail(config, output[2])
115
+ }
109
116
  }
110
117
  }
@@ -3,7 +3,7 @@ import {
3
3
  ReportLibraryModel
4
4
  } from '../models/reportLibraryModel'
5
5
  import { ReportSeverityModel } from '../models/reportSeverityModel'
6
- import languageAnalysisEngine from './../../../../constants/constants'
6
+ import languageAnalysisEngine from '../../../constants/constants'
7
7
  import {
8
8
  CRITICAL_COLOUR,
9
9
  CRITICAL_PRIORITY,
@@ -15,7 +15,7 @@ import {
15
15
  MEDIUM_PRIORITY,
16
16
  NOTE_COLOUR,
17
17
  NOTE_PRIORITY
18
- } from '../../../../constants/constants'
18
+ } from '../../../constants/constants'
19
19
  import { orderBy } from 'lodash'
20
20
  import { SeverityCountModel } from '../models/severityCountModel'
21
21
  import { ReportModelStructure } from '../models/reportListModel'
@@ -75,9 +75,9 @@ export function convertGenericToTypedLibraryVulns(libraries: any) {
75
75
  }
76
76
 
77
77
  export function severityCountAllLibraries(
78
- vulnerableLibraries: ReportLibraryModel[]
78
+ vulnerableLibraries: ReportLibraryModel[],
79
+ severityCount: SeverityCountModel
79
80
  ) {
80
- const severityCount = new SeverityCountModel()
81
81
  vulnerableLibraries.forEach(lib =>
82
82
  severityCountAllCVEs(lib.cveArray, severityCount)
83
83
  )
@@ -1,9 +1,16 @@
1
1
  import paramHandler from '../../utils/paramsUtil/paramHandler'
2
2
  import constants from '../../constants'
3
- import cliOptions from '../../utils/parsedCLIOptions'
3
+ import { getCommandLineArgsCustom } from '../../utils/parsedCLIOptions'
4
+ import { ContrastConf } from '../../utils/getConfig'
4
5
 
5
- export const getAuditConfig = (argv: string[]): { [key: string]: string } => {
6
- const auditParameters = cliOptions.getCommandLineArgsCustom(
6
+ export const getAuditConfig = async (
7
+ contrastConf: ContrastConf,
8
+ command: string,
9
+ argv: string[]
10
+ ): Promise<{ [key: string]: string }> => {
11
+ const auditParameters = await getCommandLineArgsCustom(
12
+ contrastConf,
13
+ command,
7
14
  argv,
8
15
  constants.commandLineDefinitions.auditOptionDefinitions
9
16
  )
@@ -1,6 +1,7 @@
1
1
  import commandLineUsage from 'command-line-usage'
2
2
  import i18n from 'i18n'
3
3
  import constants from '../../constants'
4
+ import { commonHelpLinks } from '../../common/commonHelp'
4
5
 
5
6
  const auditUsageGuide = commandLineUsage([
6
7
  {
@@ -48,7 +49,8 @@ const auditUsageGuide = commandLineUsage([
48
49
  'app-groups',
49
50
  'metadata'
50
51
  ]
51
- }
52
+ },
53
+ commonHelpLinks()
52
54
  ])
53
55
 
54
56
  export { auditUsageGuide }
@@ -1,16 +1,30 @@
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'
4
6
 
5
7
  export type parameterInput = string[]
6
8
 
7
- export const processAudit = async (argv: parameterInput) => {
9
+ export const processAudit = async (
10
+ contrastConf: ContrastConf,
11
+ argv: parameterInput
12
+ ) => {
8
13
  if (argv.indexOf('--help') != -1) {
9
14
  printHelpMessage()
10
15
  process.exit(0)
11
16
  }
12
- const config = getAuditConfig(argv)
17
+
18
+ const config = await getAuditConfig(contrastConf, 'audit', argv)
13
19
  await processSca(config)
20
+ await sendTelemetryConfigAsObject(
21
+ config,
22
+ 'audit',
23
+ argv,
24
+ 'SUCCESS',
25
+ // @ts-ignore
26
+ config.language
27
+ )
14
28
  }
15
29
 
16
30
  const printHelpMessage = () => {
@@ -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,37 @@ 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')
7
9
 
8
- const processScan = async argvMain => {
9
- let config = scanConfig.getScanConfig(argvMain)
10
+ const processScan = async (contrastConf, argv) => {
11
+ let config = await scanConfig.getScanConfig(contrastConf, 'scan', argv)
12
+ let output = undefined
10
13
  //try SCA analysis first
11
14
  if (config.experimental) {
12
- await processSca(config)
15
+ await processSca(config, argv)
13
16
  }
14
17
 
15
18
  let scanResults = new ScanResultsModel(await startScan(config))
19
+ await sendTelemetryConfigAsObject(
20
+ config,
21
+ 'scan',
22
+ argv,
23
+ 'SUCCESS',
24
+ scanResults.scanDetail.language
25
+ )
16
26
 
17
27
  if (scanResults.scanResultsInstances !== undefined) {
18
- formatScanOutput(scanResults)
28
+ output = formatScanOutput(scanResults)
19
29
  }
20
30
 
21
31
  if (config.save !== undefined) {
22
32
  await saveScanFile(config, scanResults)
23
33
  }
34
+
35
+ if (config.fail) {
36
+ common.processFail(config, output)
37
+ }
24
38
  }
25
39
 
26
40
  module.exports = {
@@ -21,20 +21,35 @@ const {
21
21
  const i18n = require('i18n')
22
22
  const {
23
23
  vulnerabilityReportV2
24
- } = require('../../../audit/languageAnalysisEngine/report/reportingFeature')
24
+ } = require('../../../audit/report/reportingFeature')
25
25
  const auditSave = require('../../../audit/save')
26
26
  const { dotNetAnalysis } = require('../../../scaAnalysis/dotnet')
27
+ const { auditUsageGuide } = require('../../audit/help')
28
+ const rootFile = require('../../../audit/languageAnalysisEngine/getProjectRootFilenames')
29
+ const path = require('path')
27
30
  const processSca = async config => {
28
31
  const startTime = performance.now()
29
32
  let filesFound
30
- if (config.file) {
31
- config.file = config.file.concat('/')
32
- filesFound = await autoDetection.autoDetectAuditFilesAndLanguages(
33
- config.file
33
+
34
+ if (config.help) {
35
+ console.log(auditUsageGuide)
36
+ process.exit(0)
37
+ }
38
+
39
+ const projectStats = await rootFile.getProjectStats(config.file)
40
+ let pathWithFile = projectStats.isFile()
41
+
42
+ config.fileName = config.file
43
+ config.file = pathWithFile
44
+ ? rootFile.getDirectoryFromPathGiven(config.file).concat('/')
45
+ : config.file
46
+
47
+ filesFound = await autoDetection.autoDetectAuditFilesAndLanguages(config.file)
48
+
49
+ if (filesFound.length > 1 && pathWithFile) {
50
+ filesFound = filesFound.filter(i =>
51
+ Object.values(i)[0].includes(path.basename(config.fileName))
34
52
  )
35
- } else {
36
- filesFound = await autoDetection.autoDetectAuditFilesAndLanguages(undefined)
37
- config.file = process.cwd().concat('/')
38
53
  }
39
54
 
40
55
  // files found looks like [ { javascript: [ Array ] } ]
@@ -62,7 +77,7 @@ const processSca = async config => {
62
77
  messageToSend = rubyAnalysis(config, filesFound[0])
63
78
  config.language = RUBY
64
79
  break
65
- case 'PHP':
80
+ case PHP:
66
81
  messageToSend = phpAnalysis.phpAnalysis(config, filesFound[0])
67
82
  config.language = PHP
68
83
  break
@@ -118,7 +133,9 @@ const processSca = async config => {
118
133
  throw new Error()
119
134
  } else {
120
135
  throw new Error(
121
- 'multiple language files detected, please use --file to specify a directory or the file where dependencies are declared'
136
+ `multiple language files detected \n` +
137
+ JSON.stringify(filesFound) +
138
+ `\nplease use --file to audit one language only. Example: contrast audit --file package-lock.json`
122
139
  )
123
140
  }
124
141
  }
@@ -212,6 +212,7 @@ 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
 
@@ -346,6 +347,16 @@ HTTPClient.prototype.getLatestVersion = function getLatestVersion() {
346
347
  return requestUtils.sendRequest({ method: 'get', options })
347
348
  }
348
349
 
350
+ HTTPClient.prototype.postTelemetry = function postTelemetry(
351
+ config,
352
+ requestBody
353
+ ) {
354
+ const options = _.cloneDeep(this.requestOptions)
355
+ options.url = createTelemetryEventUrl(config)
356
+ options.body = requestBody
357
+ return requestUtils.sendRequest({ method: 'post', options })
358
+ }
359
+
349
360
  // analytics
350
361
 
351
362
  HTTPClient.prototype.postAnalyticsFunction = function (config, provider, body) {
@@ -439,6 +450,10 @@ function createSbomUrl(config, type) {
439
450
  return `${config.host}/Contrast/api/ng/${config.organizationId}/applications/${config.applicationId}/libraries/sbom/${type}`
440
451
  }
441
452
 
453
+ function createTelemetryEventUrl(config) {
454
+ return `${config.host}/Contrast/api/sast/organizations/${config.organizationId}/cli`
455
+ }
456
+
442
457
  module.exports = HTTPClient
443
458
  module.exports.pollForAuthUrl = pollForAuthUrl
444
459
  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
+ }
@@ -39,9 +39,8 @@ const reportFailureError = () => {
39
39
  }
40
40
 
41
41
  const genericError = (missingCliOption: string) => {
42
- // prettier-ignore
43
- console.log(`*************************** ${i18n.__('yamlMissingParametersHeader')} ***************************\n${missingCliOption}`)
44
- console.error(i18n.__('yamlMissingParametersMessage'))
42
+ console.log(missingCliOption)
43
+ console.error(i18n.__('genericErrorMessage'))
45
44
  process.exit(1)
46
45
  }
47
46