@contrast/contrast 1.0.12 → 1.0.14

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 (55) hide show
  1. package/dist/audit/report/commonReportingFunctions.js +175 -116
  2. package/dist/audit/report/models/reportSeverityModel.js +3 -3
  3. package/dist/audit/report/reportingFeature.js +1 -10
  4. package/dist/audit/report/utils/reportUtils.js +4 -4
  5. package/dist/commands/audit/processAudit.js +10 -0
  6. package/dist/commands/scan/processScan.js +9 -0
  7. package/dist/commands/scan/sca/scaAnalysis.js +2 -0
  8. package/dist/common/HTTPClient.js +30 -2
  9. package/dist/common/errorHandling.js +1 -2
  10. package/dist/common/fail.js +7 -3
  11. package/dist/common/versionChecker.js +11 -5
  12. package/dist/constants/constants.js +1 -1
  13. package/dist/constants/locales.js +16 -8
  14. package/dist/constants.js +2 -2
  15. package/dist/index.js +5 -3
  16. package/dist/lambda/lambda.js +8 -1
  17. package/dist/scaAnalysis/common/auditReport.js +78 -0
  18. package/dist/scaAnalysis/common/scaServicesUpload.js +53 -0
  19. package/dist/scaAnalysis/javascript/index.js +4 -0
  20. package/dist/scaAnalysis/javascript/scaServiceParser.js +109 -0
  21. package/dist/scaAnalysis/ruby/analysis.js +106 -9
  22. package/dist/scaAnalysis/ruby/index.js +6 -1
  23. package/dist/scan/formatScanOutput.js +4 -29
  24. package/dist/scan/scanResults.js +1 -1
  25. package/dist/{audit/languageAnalysisEngine/util → utils}/capabilities.js +0 -0
  26. package/dist/{audit/languageAnalysisEngine/util → utils}/generalAPI.js +14 -5
  27. package/package.json +4 -1
  28. package/src/audit/report/commonReportingFunctions.js +432 -0
  29. package/src/audit/report/models/reportSeverityModel.ts +6 -6
  30. package/src/audit/report/reportingFeature.ts +2 -16
  31. package/src/audit/report/utils/reportUtils.ts +2 -8
  32. package/src/commands/audit/processAudit.ts +8 -0
  33. package/src/commands/scan/processScan.js +14 -0
  34. package/src/commands/scan/sca/scaAnalysis.js +9 -0
  35. package/src/common/HTTPClient.js +44 -2
  36. package/src/common/errorHandling.ts +1 -2
  37. package/src/common/fail.js +7 -3
  38. package/src/common/versionChecker.ts +16 -6
  39. package/src/constants/constants.js +1 -1
  40. package/src/constants/locales.js +17 -9
  41. package/src/constants.js +2 -2
  42. package/src/index.ts +5 -8
  43. package/src/lambda/lambda.ts +13 -1
  44. package/src/lambda/lambdaUtils.ts +1 -1
  45. package/src/scaAnalysis/common/auditReport.js +108 -0
  46. package/src/scaAnalysis/common/scaServicesUpload.js +56 -0
  47. package/src/scaAnalysis/javascript/index.js +4 -0
  48. package/src/scaAnalysis/javascript/scaServiceParser.js +145 -0
  49. package/src/scaAnalysis/ruby/analysis.js +137 -9
  50. package/src/scaAnalysis/ruby/index.js +6 -1
  51. package/src/scan/formatScanOutput.ts +5 -42
  52. package/src/scan/scanResults.js +1 -1
  53. package/src/{audit/languageAnalysisEngine/util → utils}/capabilities.js +0 -0
  54. package/src/{audit/languageAnalysisEngine/util → utils}/generalAPI.js +16 -6
  55. package/src/audit/report/commonReportingFunctions.ts +0 -355
@@ -1,6 +1,27 @@
1
1
  const fs = require('fs')
2
2
  const i18n = require('i18n')
3
3
 
4
+ const getRubyDeps = (config, languageFiles) => {
5
+ try {
6
+ checkForCorrectFiles(languageFiles)
7
+ const parsedGem = readAndParseGemfile(config.file)
8
+ const parsedLock = readAndParseGemLockFile(config.file)
9
+ if (config.experimental) {
10
+ const rubyArray = removeRedundantAndPopulateDefinedElements(
11
+ parsedLock.sources
12
+ )
13
+ let rubyTree = createRubyTree(rubyArray)
14
+ findChildrenDependencies(rubyTree)
15
+ processRootDependencies(parsedLock.dependencies, rubyTree)
16
+ return rubyTree
17
+ } else {
18
+ return { gemfilesDependanceies: parsedGem, gemfileLock: parsedLock }
19
+ }
20
+ } catch (err) {
21
+ throw err
22
+ }
23
+ }
24
+
4
25
  const readAndParseGemfile = file => {
5
26
  const gemFile = fs.readFileSync(file + '/Gemfile', 'utf8')
6
27
  const rubyArray = gemFile.split('\n')
@@ -242,16 +263,119 @@ const buildSourceDependencyWithVersion = (
242
263
  return dependencies
243
264
  }
244
265
 
245
- const getRubyDeps = (config, languageFiles) => {
246
- try {
247
- checkForCorrectFiles(languageFiles)
248
- const parsedGem = readAndParseGemfile(config.file)
249
- const parsedLock = readAndParseGemLockFile(config.file)
266
+ const processRootDependencies = (rootDependencies, rubyTree) => {
267
+ const getParentObjectByName = queryToken =>
268
+ Object.values(rubyTree).filter(({ name }) => name === queryToken)
250
269
 
251
- return { gemfilesDependanceies: parsedGem, gemfileLock: parsedLock }
252
- } catch (err) {
253
- throw err
270
+ for (let parent in rootDependencies) {
271
+ let parentObject = getParentObjectByName(parent)
272
+
273
+ // ignore root dependencies that don't have a resolved version
274
+ if (parentObject[0]) {
275
+ let gav =
276
+ parentObject[0].group +
277
+ '/' +
278
+ parentObject[0].name +
279
+ '@' +
280
+ parentObject[0].version
281
+
282
+ rubyTree[gav] = parentObject[0]
283
+ rubyTree[gav].directDependency = true
284
+ }
285
+ }
286
+ return rubyTree
287
+ }
288
+
289
+ const createRubyTree = rubyArray => {
290
+ let rubyTree = {}
291
+ for (let x in rubyArray) {
292
+ let version = rubyArray[x].resolved
293
+
294
+ let gav = rubyArray[x].group + '/' + rubyArray[x].name + '@' + version
295
+ rubyTree[gav] = rubyArray[x]
296
+ rubyTree[gav].directDependency = false
297
+ rubyTree[gav].version = version
298
+
299
+ // add dependency array if none exists
300
+ if (!rubyTree[gav].dependencies) {
301
+ rubyTree[gav].dependencies = []
302
+ }
303
+
304
+ delete rubyTree[gav].resolved
305
+ }
306
+ return rubyTree
307
+ }
308
+
309
+ const findChildrenDependencies = rubyTree => {
310
+ for (let dep in rubyTree) {
311
+ let unResolvedChildDepsKey = Object.keys(rubyTree[dep].dependencies)
312
+ rubyTree[dep].dependencies = resolveVersionOfChildDependencies(
313
+ unResolvedChildDepsKey,
314
+ rubyTree
315
+ )
316
+ }
317
+ }
318
+
319
+ const resolveVersionOfChildDependencies = (
320
+ unResolvedChildDepsKey,
321
+ rubyObject
322
+ ) => {
323
+ const getParentObjectByName = queryToken =>
324
+ Object.values(rubyObject).filter(({ name }) => name === queryToken)
325
+ let resolvedChildrenDependencies = []
326
+ for (let childDep in unResolvedChildDepsKey) {
327
+ let childDependencyName = unResolvedChildDepsKey[childDep]
328
+ let parent = getParentObjectByName(childDependencyName)
329
+ resolvedChildrenDependencies.push(
330
+ 'null/' + childDependencyName + '@' + parent[0].version
331
+ )
254
332
  }
333
+ return resolvedChildrenDependencies
334
+ }
335
+
336
+ const removeRedundantAndPopulateDefinedElements = deps => {
337
+ return deps.map(element => {
338
+ if (element.sourceType === 'GIT') {
339
+ delete element.sourceType
340
+ delete element.remote
341
+ delete element.platform
342
+
343
+ element.group = null
344
+ element.isProduction = true
345
+ }
346
+
347
+ if (element.sourceType === 'GEM') {
348
+ element.group = null
349
+ element.isProduction = true
350
+
351
+ delete element.sourceType
352
+ delete element.remote
353
+ delete element.platform
354
+ }
355
+
356
+ if (element.sourceType === 'PATH') {
357
+ element.group = null
358
+ element.isProduction = true
359
+
360
+ delete element.platform
361
+ delete element.sourceType
362
+ delete element.remote
363
+ }
364
+
365
+ if (element.sourceType === 'BUNDLED WITH') {
366
+ element.group = null
367
+ element.isProduction = true
368
+
369
+ delete element.sourceType
370
+ delete element.remote
371
+ delete element.branch
372
+ delete element.revision
373
+ delete element.depthLevel
374
+ delete element.specs
375
+ delete element.platform
376
+ }
377
+ return element
378
+ })
255
379
  }
256
380
 
257
381
  const checkForCorrectFiles = languageFiles => {
@@ -281,5 +405,9 @@ module.exports = {
281
405
  getPatchLevel,
282
406
  formatSourceArr,
283
407
  getSourceArray,
284
- checkForCorrectFiles
408
+ checkForCorrectFiles,
409
+ removeRedundantAndPopulateDefinedElements,
410
+ createRubyTree,
411
+ findChildrenDependencies,
412
+ processRootDependencies
285
413
  }
@@ -3,7 +3,12 @@ const { createRubyTSMessage } = require('../common/formatMessage')
3
3
 
4
4
  const rubyAnalysis = (config, languageFiles) => {
5
5
  const rubyDeps = analysis.getRubyDeps(config, languageFiles.RUBY)
6
- return createRubyTSMessage(rubyDeps)
6
+
7
+ if (config.experimental) {
8
+ return rubyDeps
9
+ } else {
10
+ return createRubyTSMessage(rubyDeps)
11
+ }
7
12
  }
8
13
 
9
14
  module.exports = {
@@ -15,11 +15,15 @@ import {
15
15
  MEDIUM_COLOUR,
16
16
  NOTE_COLOUR
17
17
  } from '../constants/constants'
18
+ import {
19
+ getSeverityCounts,
20
+ printVulnInfo
21
+ } from '../audit/report/commonReportingFunctions'
18
22
 
19
23
  export function formatScanOutput(scanResults: ScanResultsModel) {
20
24
  const { scanResultsInstances } = scanResults
21
25
 
22
- const projectOverview = getProjectOverview(scanResultsInstances)
26
+ const projectOverview = getSeverityCounts(scanResultsInstances.content)
23
27
  if (scanResultsInstances.content.length === 0) {
24
28
  console.log(i18n.__('scanNoVulnerabilitiesFound'))
25
29
  console.log(i18n.__('scanNoVulnerabilitiesFoundSecureCode'))
@@ -108,47 +112,6 @@ export function formatScanOutput(scanResults: ScanResultsModel) {
108
112
  return projectOverview
109
113
  }
110
114
 
111
- function printVulnInfo(projectOverview: any) {
112
- const totalVulnerabilities = projectOverview.total
113
-
114
- const vulMessage =
115
- totalVulnerabilities === 1 ? `vulnerability` : `vulnerabilities`
116
- console.log(chalk.bold(`Found ${totalVulnerabilities} ${vulMessage}`))
117
- console.log(
118
- i18n.__(
119
- 'foundDetailedVulnerabilities',
120
- String(projectOverview.critical),
121
- String(projectOverview.high),
122
- String(projectOverview.medium),
123
- String(projectOverview.low),
124
- String(projectOverview.note)
125
- )
126
- )
127
- }
128
-
129
- export function getProjectOverview(scanResultsInstances: ScanResultsInstances) {
130
- const acc: any = {
131
- critical: 0,
132
- high: 0,
133
- medium: 0,
134
- low: 0,
135
- note: 0,
136
- total: 0
137
- }
138
- if (
139
- scanResultsInstances?.content &&
140
- scanResultsInstances.content.length > 0
141
- ) {
142
- scanResultsInstances.content.forEach((i: ResultContent) => {
143
- acc[i.severity.toLowerCase()] += 1
144
- acc.total += 1
145
- return acc
146
- })
147
- }
148
-
149
- return acc
150
- }
151
-
152
115
  export function formatLinks(objName: string, entry: any[]) {
153
116
  const line = chalk.bold(objName + ' : ')
154
117
  if (entry.length === 1) {
@@ -94,7 +94,7 @@ const returnScanResults = async (
94
94
  )
95
95
 
96
96
  const isCI = process.env.CONTRAST_CODESEC_CI
97
- ? JSON.parse(process.env.CONTRAST_CODESEC_CI)
97
+ ? JSON.parse(process.env.CONTRAST_CODESEC_CI.toLowerCase())
98
98
  : false
99
99
  if (!isCI) {
100
100
  const retry = await retryScanPrompt()
@@ -1,13 +1,13 @@
1
1
  const { featuresTeamServer } = require('./capabilities')
2
2
  const semver = require('semver')
3
- const { handleResponseErrors } = require('../../../common/errorHandling')
4
- const { getHttpClient } = require('../../../utils/commonApi')
3
+ const { handleResponseErrors } = require('../common/errorHandling')
4
+ const commonApi = require('./commonApi')
5
+ const { isNil } = require('lodash')
5
6
 
6
7
  const getGlobalProperties = async config => {
7
- const client = getHttpClient(config)
8
-
8
+ const client = commonApi.getHttpClient(config)
9
9
  return client
10
- .getGlobalProperties(config)
10
+ .getGlobalProperties(config.host)
11
11
  .then(res => {
12
12
  if (res.statusCode === 200) {
13
13
  return res.body
@@ -20,6 +20,15 @@ const getGlobalProperties = async config => {
20
20
  })
21
21
  }
22
22
 
23
+ const getMode = async config => {
24
+ const features = await getGlobalProperties(config)
25
+
26
+ if (!isNil(features?.mode)) {
27
+ return features.mode
28
+ }
29
+ return ''
30
+ }
31
+
23
32
  const getFeatures = version => {
24
33
  const featuresEnabled = []
25
34
 
@@ -39,5 +48,6 @@ const isFeatureEnabled = (features, featureName) => {
39
48
  module.exports = {
40
49
  getGlobalProperties,
41
50
  getFeatures,
42
- isFeatureEnabled
51
+ isFeatureEnabled,
52
+ getMode
43
53
  }
@@ -1,355 +0,0 @@
1
- import { getHttpClient, handleResponseErrors } from '../../utils/commonApi'
2
- import {
3
- ReportCompositeKey,
4
- ReportList,
5
- ReportModelStructure
6
- } from './models/reportListModel'
7
- import { ReportSeverityModel } from './models/reportSeverityModel'
8
- import { orderBy } from 'lodash'
9
- import chalk from 'chalk'
10
- import { ReportCVEModel, ReportLibraryModel } from './models/reportLibraryModel'
11
- import {
12
- countVulnerableLibrariesBySeverity,
13
- findCVESeveritiesAndOrderByHighestPriority,
14
- findHighestSeverityCVE,
15
- findNameAndVersion,
16
- severityCountAllCVEs
17
- } from './utils/reportUtils'
18
- import { SeverityCountModel } from './models/severityCountModel'
19
- import {
20
- ReportOutputBodyModel,
21
- ReportOutputHeaderModel,
22
- ReportOutputModel
23
- } from './models/reportOutputModel'
24
- import {
25
- CE_URL,
26
- CRITICAL_COLOUR,
27
- HIGH_COLOUR,
28
- LOW_COLOUR,
29
- MEDIUM_COLOUR,
30
- NOTE_COLOUR
31
- } from '../../constants/constants'
32
- import Table from 'cli-table3'
33
- import { ReportGuidanceModel } from './models/reportGuidanceModel'
34
-
35
- export const createSummaryMessageTop = (
36
- numberOfVulnerableLibraries: number,
37
- numberOfCves: number
38
- ) => {
39
- numberOfVulnerableLibraries === 1
40
- ? console.log(`Found 1 vulnerable library containing ${numberOfCves} CVE`)
41
- : console.log(
42
- `Found ${numberOfVulnerableLibraries} vulnerable libraries containing ${numberOfCves} CVEs`
43
- )
44
- }
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
-
54
- export const getReport = async (config: any, reportId: string) => {
55
- const client = getHttpClient(config)
56
- return client
57
- .getReportById(config, reportId)
58
- .then((res: { statusCode: number; body: any }) => {
59
- if (res.statusCode === 200) {
60
- return res.body
61
- } else {
62
- console.log(JSON.stringify(res))
63
- handleResponseErrors(res, 'report')
64
- }
65
- })
66
- .catch((err: any) => {
67
- console.log(err)
68
- })
69
- }
70
-
71
- export const printVulnerabilityResponse = (
72
- config: any,
73
- vulnerableLibraries: ReportLibraryModel[],
74
- numberOfVulnerableLibraries: number,
75
- numberOfCves: number,
76
- guidance: any
77
- ) => {
78
- let hasSomeVulnerabilitiesReported = false
79
- printFormattedOutput(
80
- config,
81
- vulnerableLibraries,
82
- numberOfVulnerableLibraries,
83
- numberOfCves,
84
- guidance
85
- )
86
- if (Object.keys(vulnerableLibraries).length > 0) {
87
- hasSomeVulnerabilitiesReported = true
88
- }
89
- return hasSomeVulnerabilitiesReported
90
- }
91
-
92
- export const printFormattedOutput = (
93
- config: any,
94
- libraries: ReportLibraryModel[],
95
- numberOfVulnerableLibraries: number,
96
- numberOfCves: number,
97
- guidance: any
98
- ) => {
99
- createSummaryMessageTop(numberOfVulnerableLibraries, numberOfCves)
100
- console.log()
101
- const report = new ReportList()
102
-
103
- for (const library of libraries) {
104
- const { name, version } = findNameAndVersion(library, config)
105
-
106
- const newOutputModel = new ReportModelStructure(
107
- new ReportCompositeKey(
108
- name,
109
- version,
110
- findHighestSeverityCVE(library.cveArray) as ReportSeverityModel,
111
- severityCountAllCVEs(
112
- library.cveArray,
113
- new SeverityCountModel()
114
- ).getTotal
115
- ),
116
- library.cveArray
117
- )
118
- report.reportOutputList.push(newOutputModel)
119
- }
120
-
121
- const outputOrderedByLowestSeverityAndLowestNumOfCvesFirst = orderBy(
122
- report.reportOutputList,
123
- [
124
- (reportListItem: ReportModelStructure) => {
125
- return reportListItem.compositeKey.highestSeverity.priority
126
- },
127
- (reportListItem: ReportModelStructure) => {
128
- return reportListItem.compositeKey.numberOfSeverities
129
- }
130
- ],
131
- ['asc', 'desc']
132
- )
133
-
134
- let contrastHeaderNumCounter = 0
135
- for (const reportModel of outputOrderedByLowestSeverityAndLowestNumOfCvesFirst) {
136
- contrastHeaderNumCounter++
137
- const { libraryName, libraryVersion, highestSeverity } =
138
- reportModel.compositeKey
139
- const numOfCVEs = reportModel.cveArray.length
140
-
141
- const table = new Table({
142
- chars: {
143
- top: '',
144
- 'top-mid': '',
145
- 'top-left': '',
146
- 'top-right': '',
147
- bottom: '',
148
- 'bottom-mid': '',
149
- 'bottom-left': '',
150
- 'bottom-right': '',
151
- left: '',
152
- 'left-mid': '',
153
- mid: '',
154
- 'mid-mid': '',
155
- right: '',
156
- 'right-mid': '',
157
- middle: ' '
158
- },
159
- style: { 'padding-left': 0, 'padding-right': 0 },
160
- colAligns: ['right'],
161
- wordWrap: true,
162
- colWidths: [12, 1, 100]
163
- })
164
-
165
- const header = buildHeader(
166
- highestSeverity,
167
- contrastHeaderNumCounter,
168
- libraryName,
169
- libraryVersion,
170
- numOfCVEs
171
- )
172
-
173
- const advice = gatherRemediationAdvice(
174
- guidance,
175
- libraryName,
176
- libraryVersion
177
- )
178
-
179
- const body = buildBody(reportModel.cveArray, advice)
180
-
181
- const reportOutputModel = new ReportOutputModel(header, body)
182
-
183
- table.push(
184
- reportOutputModel.body.issueMessage,
185
- reportOutputModel.body.adviceMessage
186
- )
187
-
188
- console.log(
189
- reportOutputModel.header.vulnMessage,
190
- reportOutputModel.header.introducesMessage
191
- )
192
- console.log(table.toString() + '\n')
193
- }
194
-
195
- createSummaryMessageBottom(numberOfVulnerableLibraries)
196
- const {
197
- criticalMessage,
198
- highMessage,
199
- mediumMessage,
200
- lowMessage,
201
- noteMessage
202
- } = buildFooter(outputOrderedByLowestSeverityAndLowestNumOfCvesFirst)
203
- console.log(
204
- `${criticalMessage} | ${highMessage} | ${mediumMessage} | ${lowMessage} | ${noteMessage}`
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
- }
215
- }
216
-
217
- export function buildHeader(
218
- highestSeverity: ReportSeverityModel,
219
- contrastHeaderNum: number,
220
- libraryName: string,
221
- version: string,
222
- numOfCVEs: number
223
- ) {
224
- const vulnerabilityPluralised =
225
- numOfCVEs > 1 ? 'vulnerabilities' : 'vulnerability'
226
- const formattedHeaderNum = buildFormattedHeaderNum(contrastHeaderNum)
227
-
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}`
234
-
235
- const introducesMessage = `introduces ${numOfCVEs} ${vulnerabilityPluralised}`
236
-
237
- return new ReportOutputHeaderModel(vulnMessage, introducesMessage)
238
- }
239
-
240
- export function buildBody(
241
- cveArray: ReportCVEModel[],
242
- advice: ReportGuidanceModel
243
- ) {
244
- const cveMessages: string[] = []
245
-
246
- findCVESeveritiesAndOrderByHighestPriority(cveArray).forEach(
247
- reportSeverityModel => {
248
- // @ts-ignore
249
- const { outputColour, severity, cveName } = reportSeverityModel
250
-
251
- const severityShorthand = chalk
252
- .hex(outputColour)
253
- .bold(`[${severity.charAt(0).toUpperCase()}]`)
254
-
255
- const builtMessage = severityShorthand + cveName
256
- cveMessages.push(builtMessage)
257
- }
258
- )
259
-
260
- const numAndSeverityType = getNumOfAndSeverityType(cveArray)
261
-
262
- const issueMessage = [
263
- chalk.bold('Issue'),
264
- ':',
265
- `${numAndSeverityType} ${cveMessages.join(', ')}`
266
- ]
267
-
268
- //todo different advice based on remediationGuidance being available or now
269
- // console.log(advice)
270
-
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.'
275
-
276
- const adviceMessage = [chalk.bold('Advice'), ':', displayAdvice]
277
-
278
- return new ReportOutputBodyModel(issueMessage, adviceMessage)
279
- }
280
-
281
- export function gatherRemediationAdvice(
282
- guidance: any,
283
- libraryName: string,
284
- libraryVersion: string
285
- ) {
286
- const guidanceModel = new ReportGuidanceModel()
287
-
288
- const data = guidance[libraryName + '@' + libraryVersion]
289
-
290
- if (data) {
291
- guidanceModel.minimum = data.minUpgradeVersion
292
- guidanceModel.maximum = data.maxUpgradeVersion
293
- }
294
-
295
- return guidanceModel
296
- }
297
-
298
- export function buildFormattedHeaderNum(contrastHeaderNum: number) {
299
- return `CONTRAST-${contrastHeaderNum.toString().padStart(3, '0')}`
300
- }
301
-
302
- export function getNumOfAndSeverityType(cveArray: ReportCVEModel[]) {
303
- const { critical, high, medium, low, note } = severityCountAllCVEs(
304
- cveArray,
305
- new SeverityCountModel()
306
- )
307
-
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` : ''
329
-
330
- //removes/trims whitespace to single spaces
331
- return `${criticalMessage} ${highMessage} ${mediumMessage} ${lowMessage} ${noteMessage}`
332
- .replace(/\s+/g, ' ')
333
- .trim()
334
- }
335
-
336
- const buildFooter = (reportModelStructure: ReportModelStructure[]) => {
337
- const { critical, high, medium, low, note } =
338
- countVulnerableLibrariesBySeverity(reportModelStructure)
339
-
340
- const criticalMessage = chalk
341
- .hex(CRITICAL_COLOUR)
342
- .bold(`${critical} Critical`)
343
- const highMessage = chalk.hex(HIGH_COLOUR).bold(`${high} High`)
344
- const mediumMessage = chalk.hex(MEDIUM_COLOUR).bold(`${medium} Medium`)
345
- const lowMessage = chalk.hex(LOW_COLOUR).bold(`${low} Low`)
346
- const noteMessage = chalk.hex(NOTE_COLOUR).bold(`${note} Note`)
347
-
348
- return {
349
- criticalMessage,
350
- highMessage,
351
- mediumMessage,
352
- lowMessage,
353
- noteMessage
354
- }
355
- }