@contrast/contrast 1.0.18 → 1.0.20

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 (47) hide show
  1. package/dist/audit/report/commonReportingFunctions.js +3 -4
  2. package/dist/audit/report/models/reportListModel.js +2 -1
  3. package/dist/audit/report/reportingFeature.js +1 -1
  4. package/dist/audit/report/utils/reportUtils.js +30 -11
  5. package/dist/cliConstants.js +1 -0
  6. package/dist/commands/audit/auditConfig.js +1 -2
  7. package/dist/commands/auth/auth.js +43 -7
  8. package/dist/commands/scan/sca/scaAnalysis.js +4 -2
  9. package/dist/common/HTTPClient.js +4 -4
  10. package/dist/common/errorHandling.js +13 -1
  11. package/dist/constants/constants.js +1 -1
  12. package/dist/constants/locales.js +18 -2
  13. package/dist/scaAnalysis/common/auditReport.js +16 -60
  14. package/dist/scaAnalysis/common/commonReportingFunctionsSca.js +154 -0
  15. package/dist/scaAnalysis/common/models/ScaReportModel.js +45 -0
  16. package/dist/scaAnalysis/common/scaServicesUpload.js +4 -3
  17. package/dist/scaAnalysis/common/utils/reportUtilsSca.js +76 -0
  18. package/dist/scaAnalysis/java/analysis.js +1 -28
  19. package/dist/scaAnalysis/java/index.js +1 -13
  20. package/dist/scan/formatScanOutput.js +19 -13
  21. package/dist/utils/getConfig.js +1 -1
  22. package/dist/utils/paramsUtil/configStoreParams.js +1 -12
  23. package/dist/utils/paramsUtil/paramHandler.js +1 -7
  24. package/package.json +5 -1
  25. package/src/audit/report/commonReportingFunctions.js +7 -5
  26. package/src/audit/report/models/reportListModel.ts +12 -2
  27. package/src/audit/report/reportingFeature.ts +1 -1
  28. package/src/audit/report/utils/reportUtils.ts +4 -4
  29. package/src/cliConstants.js +1 -0
  30. package/src/commands/audit/auditConfig.js +1 -2
  31. package/src/commands/auth/auth.js +49 -7
  32. package/src/commands/scan/sca/scaAnalysis.js +7 -2
  33. package/src/common/HTTPClient.js +5 -4
  34. package/src/common/errorHandling.js +14 -1
  35. package/src/constants/constants.js +1 -1
  36. package/src/constants/locales.js +19 -2
  37. package/src/scaAnalysis/common/auditReport.js +25 -80
  38. package/src/scaAnalysis/common/commonReportingFunctionsSca.js +276 -0
  39. package/src/scaAnalysis/common/models/ScaReportModel.ts +81 -0
  40. package/src/scaAnalysis/common/scaServicesUpload.js +5 -3
  41. package/src/scaAnalysis/common/utils/reportUtilsSca.ts +123 -0
  42. package/src/scaAnalysis/java/analysis.js +1 -28
  43. package/src/scaAnalysis/java/index.js +1 -18
  44. package/src/scan/formatScanOutput.ts +28 -17
  45. package/src/utils/getConfig.ts +1 -2
  46. package/src/utils/paramsUtil/configStoreParams.js +1 -14
  47. package/src/utils/paramsUtil/paramHandler.js +1 -9
@@ -0,0 +1,123 @@
1
+ import { orderBy } from 'lodash'
2
+ import {
3
+ CRITICAL_COLOUR,
4
+ CRITICAL_PRIORITY,
5
+ HIGH_COLOUR,
6
+ HIGH_PRIORITY,
7
+ LOW_COLOUR,
8
+ LOW_PRIORITY,
9
+ MEDIUM_COLOUR,
10
+ MEDIUM_PRIORITY,
11
+ NOTE_COLOUR,
12
+ NOTE_PRIORITY
13
+ } from '../../../constants/constants'
14
+ import { ReportSeverityModel } from '../../../audit/report/models/reportSeverityModel'
15
+ import { SeverityCountModel } from '../../../audit/report/models/severityCountModel'
16
+ import {
17
+ ScaReportModel,
18
+ ScaReportVulnerabilityModel
19
+ } from '../models/ScaReportModel'
20
+
21
+ export function findHighestSeverityCVESca(
22
+ cveArray: ScaReportVulnerabilityModel[]
23
+ ) {
24
+ const mappedToReportSeverityModels = cveArray.map(cve =>
25
+ findCVESeveritySca(cve)
26
+ )
27
+
28
+ //order and get first
29
+ return orderBy(mappedToReportSeverityModels, cve => cve?.priority)[0]
30
+ }
31
+
32
+ export function orderByHighestPrioritySca(
33
+ reportSeverityModel: ReportSeverityModel[]
34
+ ) {
35
+ return orderBy(reportSeverityModel, ['priority'], ['asc'])
36
+ }
37
+
38
+ export function findCVESeveritySca(
39
+ vulnerabilityModel: ScaReportVulnerabilityModel
40
+ ) {
41
+ const { name } = vulnerabilityModel
42
+
43
+ if (
44
+ vulnerabilityModel.cvss3Severity === 'CRITICAL' ||
45
+ vulnerabilityModel.severity === 'CRITICAL'
46
+ ) {
47
+ return new ReportSeverityModel(
48
+ 'CRITICAL',
49
+ CRITICAL_PRIORITY,
50
+ CRITICAL_COLOUR,
51
+ name
52
+ )
53
+ } else if (
54
+ vulnerabilityModel.cvss3Severity === 'HIGH' ||
55
+ vulnerabilityModel.severity === 'HIGH'
56
+ ) {
57
+ return new ReportSeverityModel('HIGH', HIGH_PRIORITY, HIGH_COLOUR, name)
58
+ } else if (
59
+ vulnerabilityModel.cvss3Severity === 'MEDIUM' ||
60
+ vulnerabilityModel.severity === 'MEDIUM'
61
+ ) {
62
+ return new ReportSeverityModel(
63
+ 'MEDIUM',
64
+ MEDIUM_PRIORITY,
65
+ MEDIUM_COLOUR,
66
+ name
67
+ )
68
+ } else if (
69
+ vulnerabilityModel.cvss3Severity === 'LOW' ||
70
+ vulnerabilityModel.severity === 'LOW'
71
+ ) {
72
+ return new ReportSeverityModel('LOW', LOW_PRIORITY, LOW_COLOUR, name)
73
+ } else if (
74
+ vulnerabilityModel.cvss3Severity === 'NOTE' ||
75
+ vulnerabilityModel.severity === 'NOTE'
76
+ ) {
77
+ return new ReportSeverityModel('NOTE', NOTE_PRIORITY, NOTE_COLOUR, name)
78
+ }
79
+ }
80
+
81
+ export function convertGenericToTypedReportModelSca(reportArray: any) {
82
+ return reportArray.map((library: any) => {
83
+ return new ScaReportModel(library)
84
+ })
85
+ }
86
+
87
+ export function severityCountAllLibrariesSca(
88
+ vulnerableLibraries: ScaReportModel[],
89
+ severityCount: SeverityCountModel
90
+ ) {
91
+ vulnerableLibraries.forEach(lib =>
92
+ severityCountAllCVEsSca(lib.vulnerabilities, severityCount)
93
+ )
94
+ return severityCount
95
+ }
96
+
97
+ export function severityCountAllCVEsSca(
98
+ cveArray: ScaReportVulnerabilityModel[],
99
+ severityCount: SeverityCountModel
100
+ ) {
101
+ const severityCountInner = severityCount
102
+ cveArray.forEach(cve => severityCountSingleCVESca(cve, severityCountInner))
103
+ return severityCountInner
104
+ }
105
+
106
+ export function severityCountSingleCVESca(
107
+ cve: ScaReportVulnerabilityModel,
108
+ severityCount: SeverityCountModel
109
+ ) {
110
+ if (cve.cvss3Severity === 'CRITICAL' || cve.severity === 'CRITICAL') {
111
+ severityCount.critical += 1
112
+ } else if (cve.cvss3Severity === 'HIGH' || cve.severity === 'HIGH') {
113
+ severityCount.high += 1
114
+ } else if (cve.cvss3Severity === 'MEDIUM' || cve.severity === 'MEDIUM') {
115
+ severityCount.medium += 1
116
+ } else if (cve.cvss3Severity === 'LOW' || cve.severity === 'LOW') {
117
+ severityCount.low += 1
118
+ } else if (cve.cvss3Severity === 'NOTE' || cve.severity === 'NOTE') {
119
+ severityCount.note += 1
120
+ }
121
+
122
+ return severityCount
123
+ }
@@ -147,34 +147,7 @@ const getJavaBuildDeps = (config, files) => {
147
147
  }
148
148
  }
149
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
-
176
150
  module.exports = {
177
151
  getJavaBuildDeps,
178
- determineProjectTypeAndCwd,
179
- agreementPrompt
152
+ determineProjectTypeAndCwd
180
153
  }
@@ -4,16 +4,12 @@ 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')
9
7
 
10
8
  const javaAnalysis = async (config, languageFiles) => {
11
9
  languageFiles.JAVA.forEach(file => {
12
10
  file.replace('build.gradle.kts', 'build.gradle')
13
11
  })
14
12
 
15
- await getAgreement(config)
16
-
17
13
  const javaDeps = buildJavaTree(config, languageFiles.JAVA)
18
14
 
19
15
  if (config.experimental) {
@@ -23,24 +19,11 @@ const javaAnalysis = async (config, languageFiles) => {
23
19
  }
24
20
  }
25
21
 
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
-
38
22
  const buildJavaTree = (config, files) => {
39
23
  const javaBuildDeps = analysis.getJavaBuildDeps(config, files)
40
24
  return parseBuildDeps(config, javaBuildDeps)
41
25
  }
42
26
 
43
27
  module.exports = {
44
- javaAnalysis,
45
- getAgreement
28
+ javaAnalysis
46
29
  }
@@ -1,7 +1,4 @@
1
- import {
2
- ScanResultsInstances,
3
- ScanResultsModel
4
- } from './models/scanResultsModel'
1
+ import { ScanResultsModel } from './models/scanResultsModel'
5
2
  import i18n from 'i18n'
6
3
  import chalk from 'chalk'
7
4
  import { ResultContent } from './models/resultContentModel'
@@ -13,7 +10,8 @@ import {
13
10
  HIGH_COLOUR,
14
11
  LOW_COLOUR,
15
12
  MEDIUM_COLOUR,
16
- NOTE_COLOUR
13
+ NOTE_COLOUR,
14
+ supportedLanguagesScan
17
15
  } from '../constants/constants'
18
16
  import {
19
17
  getSeverityCounts,
@@ -21,27 +19,28 @@ import {
21
19
  } from '../audit/report/commonReportingFunctions'
22
20
 
23
21
  export function formatScanOutput(scanResults: ScanResultsModel) {
24
- const { scanResultsInstances } = scanResults
22
+ const { content } = scanResults.scanResultsInstances
23
+ const { language } = scanResults.scanDetail
25
24
 
26
- const projectOverview = getSeverityCounts(scanResultsInstances.content)
27
- if (scanResultsInstances.content.length === 0) {
25
+ const severityCounts = getSeverityCounts(content)
26
+ if (content.length === 0) {
28
27
  console.log(i18n.__('scanNoVulnerabilitiesFound'))
29
28
  console.log(i18n.__('scanNoVulnerabilitiesFoundSecureCode'))
30
29
  console.log(i18n.__('scanNoVulnerabilitiesFoundGoodWork'))
31
30
  } else {
32
31
  const message =
33
- projectOverview.critical || projectOverview.high
32
+ severityCounts.critical || severityCounts.high
34
33
  ? 'Here are your top priorities to fix'
35
34
  : "No major issues, here's what we found"
36
35
  console.log(chalk.bold(message))
37
36
  console.log()
38
37
 
39
- let defaultView = getDefaultView(scanResultsInstances.content)
38
+ const defaultView = getDefaultView(content, language)
40
39
 
41
40
  let count = 0
42
41
  defaultView.forEach(entry => {
43
42
  count++
44
- let table = new Table({
43
+ const table = new Table({
45
44
  chars: {
46
45
  top: '',
47
46
  'top-mid': '',
@@ -64,6 +63,7 @@ export function formatScanOutput(scanResults: ScanResultsModel) {
64
63
  wordWrap: true,
65
64
  colWidths: [12, 1, 100]
66
65
  })
66
+
67
67
  let learnRow: string[] = []
68
68
  let adviceRow = []
69
69
  const headerColour = chalk.hex(entry.colour)
@@ -107,9 +107,9 @@ export function formatScanOutput(scanResults: ScanResultsModel) {
107
107
  console.log()
108
108
  })
109
109
  }
110
- printVulnInfo(projectOverview)
110
+ printVulnInfo(severityCounts)
111
111
 
112
- return projectOverview
112
+ return severityCounts
113
113
  }
114
114
 
115
115
  export function formatLinks(objName: string, entry: any[]) {
@@ -124,7 +124,7 @@ export function formatLinks(objName: string, entry: any[]) {
124
124
  }
125
125
  }
126
126
 
127
- export function getDefaultView(content: ResultContent[]) {
127
+ export function getDefaultView(content: ResultContent[], language: string) {
128
128
  const groupTypeResults = [] as GroupedResultsModel[]
129
129
 
130
130
  content.forEach(resultEntry => {
@@ -136,8 +136,7 @@ export function getDefaultView(content: ResultContent[]) {
136
136
  groupResultsObj.learn = resultEntry.learn
137
137
  groupResultsObj.message = resultEntry.message?.text
138
138
  ? editVulName(resultEntry.message.text) +
139
- ':' +
140
- getSourceLineNumber(resultEntry)
139
+ doAddSourceLineNumber(resultEntry, language)
141
140
  : ''
142
141
  groupResultsObj.codePath = getLocationsSyncInfo(resultEntry)
143
142
  groupTypeResults.push(groupResultsObj)
@@ -146,9 +145,21 @@ export function getDefaultView(content: ResultContent[]) {
146
145
 
147
146
  return sortBy(groupTypeResults, ['priority'])
148
147
  }
148
+
149
+ export function doAddSourceLineNumber(
150
+ resultEntry: ResultContent,
151
+ language: string
152
+ ) {
153
+ //only add source line num if not JS
154
+ return language !== supportedLanguagesScan.JAVASCRIPT
155
+ ? ':' + getSourceLineNumber(resultEntry)
156
+ : ''
157
+ }
158
+
149
159
  export function editVulName(message: string) {
150
160
  return message.substring(message.indexOf(' in '))
151
161
  }
162
+
152
163
  export function getLocationsSyncInfo(resultEntry: ResultContent) {
153
164
  const locationsMessage =
154
165
  resultEntry.locations[0]?.physicalLocation?.artifactLocation?.uri || ''
@@ -165,7 +176,7 @@ export function getLocationsSyncInfo(resultEntry: ResultContent) {
165
176
  export function getSourceLineNumber(resultEntry: ResultContent) {
166
177
  const locationsLineNumber =
167
178
  resultEntry.locations[0]?.physicalLocation?.region?.startLine || ''
168
- let codeFlowLineNumber = getCodeFlowInfo(resultEntry)
179
+ const codeFlowLineNumber = getCodeFlowInfo(resultEntry)
169
180
 
170
181
  return codeFlowLineNumber ? codeFlowLineNumber : locationsLineNumber
171
182
  }
@@ -8,7 +8,6 @@ type ContrastConfOptions = Partial<{
8
8
  orgId: string
9
9
  authHeader: string
10
10
  numOfRuns: number
11
- javaAgreement: boolean
12
11
  }>
13
12
 
14
13
  type ContrastConf = Conf<ContrastConfOptions>
@@ -29,7 +28,7 @@ const setConfigValues = (config: ContrastConf, values: ContrastConfOptions) => {
29
28
  config.set('apiKey', values.apiKey)
30
29
  config.set('organizationId', values.orgId)
31
30
  config.set('authorization', values.authHeader)
32
- values.host ? config.set('host', values.host) : null
31
+ values.host ? config.set('host', values.host) : config.set('host', CE_URL)
33
32
  }
34
33
 
35
34
  export { localConfig, setConfigValues, ContrastConf, ContrastConfOptions }
@@ -16,17 +16,4 @@ const getAuth = () => {
16
16
  return ContrastConfToUse
17
17
  }
18
18
 
19
- const getAgreement = () => {
20
- const ContrastConf = config.localConfig(APP_NAME, APP_VERSION)
21
- let ContrastConfToUse = {}
22
- ContrastConfToUse.javaAgreement = ContrastConf.get('javaAgreement')
23
- return ContrastConfToUse
24
- }
25
-
26
- const setAgreement = agreement => {
27
- const ContrastConf = config.localConfig(APP_NAME, APP_VERSION)
28
- ContrastConf.set('javaAgreement', agreement)
29
- return agreement
30
- }
31
-
32
- module.exports = { getAuth, getAgreement, setAgreement }
19
+ module.exports = { getAuth }
@@ -21,12 +21,4 @@ const getAuth = params => {
21
21
  }
22
22
  }
23
23
 
24
- const getAgreement = () => {
25
- return configStoreParams.getAgreement()
26
- }
27
-
28
- const setAgreement = answer => {
29
- return configStoreParams.setAgreement(answer)
30
- }
31
-
32
- module.exports = { getAuth, getAgreement, setAgreement }
24
+ module.exports = { getAuth }