@contrast/contrast 1.0.19 → 1.0.21
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.
- package/dist/audit/report/commonReportingFunctions.js +3 -4
- package/dist/audit/report/models/reportListModel.js +2 -1
- package/dist/audit/report/reportingFeature.js +1 -1
- package/dist/audit/report/utils/reportUtils.js +30 -11
- package/dist/cliConstants.js +13 -6
- package/dist/commands/audit/auditConfig.js +1 -2
- package/dist/commands/audit/help.js +2 -1
- package/dist/commands/audit/processAudit.js +1 -1
- package/dist/commands/fingerprint/fingerprintConfig.js +12 -0
- package/dist/commands/fingerprint/processFingerprint.js +14 -0
- package/dist/commands/learn/learn.js +9 -0
- package/dist/commands/learn/processLearn.js +10 -0
- package/dist/common/commonHelp.js +8 -1
- package/dist/constants/constants.js +1 -1
- package/dist/constants/locales.js +14 -3
- package/dist/index.js +8 -0
- package/dist/lambda/help.js +2 -1
- package/dist/scaAnalysis/common/auditReport.js +16 -60
- package/dist/scaAnalysis/common/commonReportingFunctionsSca.js +154 -0
- package/dist/scaAnalysis/common/models/ScaReportModel.js +45 -0
- package/dist/scaAnalysis/common/scaServicesUpload.js +4 -3
- package/dist/scaAnalysis/common/utils/reportUtilsSca.js +76 -0
- package/dist/scaAnalysis/java/analysis.js +1 -28
- package/dist/scaAnalysis/java/index.js +1 -13
- package/dist/scaAnalysis/scaAnalysis.js +155 -0
- package/dist/scan/autoDetection.js +2 -2
- package/dist/scan/fileUtils.js +2 -2
- package/dist/scan/formatScanOutput.js +19 -13
- package/dist/scan/help.js +2 -1
- package/dist/utils/paramsUtil/configStoreParams.js +1 -12
- package/dist/utils/paramsUtil/paramHandler.js +1 -7
- package/package.json +5 -1
- package/src/audit/report/commonReportingFunctions.js +7 -5
- package/src/audit/report/models/reportListModel.ts +12 -2
- package/src/audit/report/reportingFeature.ts +1 -1
- package/src/audit/report/utils/reportUtils.ts +4 -4
- package/src/cliConstants.js +15 -6
- package/src/commands/audit/auditConfig.js +1 -2
- package/src/commands/audit/help.js +2 -1
- package/src/commands/audit/processAudit.js +1 -1
- package/src/commands/fingerprint/fingerprintConfig.js +19 -0
- package/src/commands/fingerprint/processFingerprint.js +21 -0
- package/src/commands/learn/learn.js +10 -0
- package/src/commands/learn/processLearn.js +13 -0
- package/src/common/commonHelp.js +11 -1
- package/src/constants/constants.js +1 -1
- package/src/constants/locales.js +22 -3
- package/src/index.ts +11 -0
- package/src/lambda/help.ts +2 -1
- package/src/scaAnalysis/common/auditReport.js +25 -80
- package/src/scaAnalysis/common/commonReportingFunctionsSca.js +276 -0
- package/src/scaAnalysis/common/models/ScaReportModel.ts +81 -0
- package/src/scaAnalysis/common/scaServicesUpload.js +5 -3
- package/src/scaAnalysis/common/utils/reportUtilsSca.ts +123 -0
- package/src/scaAnalysis/java/analysis.js +1 -28
- package/src/scaAnalysis/java/index.js +1 -18
- package/src/scaAnalysis/scaAnalysis.js +206 -0
- package/src/scan/autoDetection.js +2 -2
- package/src/scan/fileUtils.js +2 -2
- package/src/scan/formatScanOutput.ts +28 -17
- package/src/scan/help.js +2 -1
- package/src/utils/getConfig.ts +0 -1
- package/src/utils/paramsUtil/configStoreParams.js +1 -14
- package/src/utils/paramsUtil/paramHandler.js +1 -9
- package/dist/commands/scan/sca/scaAnalysis.js +0 -155
- package/src/commands/scan/sca/scaAnalysis.js +0 -206
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
const {
|
|
2
|
+
ReportList,
|
|
3
|
+
ReportModelStructure,
|
|
4
|
+
ReportCompositeKey
|
|
5
|
+
} = require('../../audit/report/models/reportListModel')
|
|
6
|
+
const {
|
|
7
|
+
countVulnerableLibrariesBySeverity
|
|
8
|
+
} = require('../../audit/report/utils/reportUtils')
|
|
9
|
+
const {
|
|
10
|
+
SeverityCountModel
|
|
11
|
+
} = require('../../audit/report/models/severityCountModel')
|
|
12
|
+
const { orderBy } = require('lodash')
|
|
13
|
+
const {
|
|
14
|
+
ReportOutputModel,
|
|
15
|
+
ReportOutputHeaderModel,
|
|
16
|
+
ReportOutputBodyModel
|
|
17
|
+
} = require('../../audit/report/models/reportOutputModel')
|
|
18
|
+
const {
|
|
19
|
+
CE_URL,
|
|
20
|
+
CRITICAL_COLOUR,
|
|
21
|
+
HIGH_COLOUR,
|
|
22
|
+
MEDIUM_COLOUR,
|
|
23
|
+
LOW_COLOUR,
|
|
24
|
+
NOTE_COLOUR
|
|
25
|
+
} = require('../../constants/constants')
|
|
26
|
+
const chalk = require('chalk')
|
|
27
|
+
const Table = require('cli-table3')
|
|
28
|
+
const {
|
|
29
|
+
findHighestSeverityCVESca,
|
|
30
|
+
severityCountAllCVEsSca,
|
|
31
|
+
findCVESeveritySca,
|
|
32
|
+
orderByHighestPrioritySca
|
|
33
|
+
} = require('./utils/reportUtilsSca')
|
|
34
|
+
const {
|
|
35
|
+
buildFormattedHeaderNum
|
|
36
|
+
} = require('../../audit/report/commonReportingFunctions')
|
|
37
|
+
|
|
38
|
+
const createSummaryMessageTop = (numberOfVulnerableLibraries, numberOfCves) => {
|
|
39
|
+
numberOfVulnerableLibraries === 1
|
|
40
|
+
? console.log(
|
|
41
|
+
`\n\nFound 1 vulnerable library containing ${numberOfCves} CVE`
|
|
42
|
+
)
|
|
43
|
+
: console.log(
|
|
44
|
+
`\n\nFound ${numberOfVulnerableLibraries} vulnerable libraries containing ${numberOfCves} CVEs`
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const createSummaryMessageBottom = numberOfVulnerableLibraries => {
|
|
49
|
+
numberOfVulnerableLibraries === 1
|
|
50
|
+
? console.log(`Found 1 vulnerability`)
|
|
51
|
+
: console.log(`Found ${numberOfVulnerableLibraries} vulnerabilities`)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const printFormattedOutputSca = (
|
|
55
|
+
config,
|
|
56
|
+
reportModelList,
|
|
57
|
+
numberOfVulnerableLibraries,
|
|
58
|
+
numberOfCves
|
|
59
|
+
) => {
|
|
60
|
+
createSummaryMessageTop(numberOfVulnerableLibraries, numberOfCves)
|
|
61
|
+
console.log()
|
|
62
|
+
const report = new ReportList()
|
|
63
|
+
|
|
64
|
+
for (const library of reportModelList) {
|
|
65
|
+
const { artifactName, version, vulnerabilities, remediationAdvice } =
|
|
66
|
+
library
|
|
67
|
+
|
|
68
|
+
const newOutputModel = new ReportModelStructure(
|
|
69
|
+
new ReportCompositeKey(
|
|
70
|
+
artifactName,
|
|
71
|
+
version,
|
|
72
|
+
findHighestSeverityCVESca(vulnerabilities),
|
|
73
|
+
severityCountAllCVEsSca(
|
|
74
|
+
vulnerabilities,
|
|
75
|
+
new SeverityCountModel()
|
|
76
|
+
).getTotal
|
|
77
|
+
),
|
|
78
|
+
vulnerabilities,
|
|
79
|
+
remediationAdvice
|
|
80
|
+
)
|
|
81
|
+
report.reportOutputList.push(newOutputModel)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const outputOrderedByLowestSeverityAndLowestNumOfCvesFirst = orderBy(
|
|
85
|
+
report.reportOutputList,
|
|
86
|
+
[
|
|
87
|
+
reportListItem => {
|
|
88
|
+
return reportListItem.compositeKey.highestSeverity.priority
|
|
89
|
+
},
|
|
90
|
+
reportListItem => {
|
|
91
|
+
return reportListItem.compositeKey.numberOfSeverities
|
|
92
|
+
}
|
|
93
|
+
],
|
|
94
|
+
['asc', 'desc']
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
let contrastHeaderNumCounter = 0
|
|
98
|
+
for (const reportModel of outputOrderedByLowestSeverityAndLowestNumOfCvesFirst) {
|
|
99
|
+
contrastHeaderNumCounter++
|
|
100
|
+
const { libraryName, libraryVersion, highestSeverity } =
|
|
101
|
+
reportModel.compositeKey
|
|
102
|
+
|
|
103
|
+
const { cveArray, remediationAdvice } = reportModel
|
|
104
|
+
|
|
105
|
+
const numOfCVEs = reportModel.cveArray.length
|
|
106
|
+
|
|
107
|
+
const table = getReportTable()
|
|
108
|
+
|
|
109
|
+
const header = buildHeader(
|
|
110
|
+
highestSeverity,
|
|
111
|
+
contrastHeaderNumCounter,
|
|
112
|
+
libraryName,
|
|
113
|
+
libraryVersion,
|
|
114
|
+
numOfCVEs
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
const body = buildBody(cveArray, remediationAdvice)
|
|
118
|
+
|
|
119
|
+
const reportOutputModel = new ReportOutputModel(header, body)
|
|
120
|
+
|
|
121
|
+
table.push(
|
|
122
|
+
reportOutputModel.body.issueMessage,
|
|
123
|
+
reportOutputModel.body.adviceMessage
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
console.log(
|
|
127
|
+
reportOutputModel.header.vulnMessage,
|
|
128
|
+
reportOutputModel.header.introducesMessage
|
|
129
|
+
)
|
|
130
|
+
console.log(table.toString() + '\n')
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
createSummaryMessageBottom(numberOfVulnerableLibraries)
|
|
134
|
+
const {
|
|
135
|
+
criticalMessage,
|
|
136
|
+
highMessage,
|
|
137
|
+
mediumMessage,
|
|
138
|
+
lowMessage,
|
|
139
|
+
noteMessage
|
|
140
|
+
} = buildFooter(outputOrderedByLowestSeverityAndLowestNumOfCvesFirst)
|
|
141
|
+
console.log(
|
|
142
|
+
`${criticalMessage} | ${highMessage} | ${mediumMessage} | ${lowMessage} | ${noteMessage}`
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
if (config.host !== CE_URL) {
|
|
146
|
+
console.log(
|
|
147
|
+
'\n' + chalk.bold('View your full dependency tree in Contrast:')
|
|
148
|
+
)
|
|
149
|
+
console.log(
|
|
150
|
+
`${config.host}/Contrast/static/ng/index.html#/${config.organizationId}/applications/${config.applicationId}/libs/dependency-tree`
|
|
151
|
+
)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function getReportTable() {
|
|
156
|
+
return new Table({
|
|
157
|
+
chars: {
|
|
158
|
+
top: '',
|
|
159
|
+
'top-mid': '',
|
|
160
|
+
'top-left': '',
|
|
161
|
+
'top-right': '',
|
|
162
|
+
bottom: '',
|
|
163
|
+
'bottom-mid': '',
|
|
164
|
+
'bottom-left': '',
|
|
165
|
+
'bottom-right': '',
|
|
166
|
+
left: '',
|
|
167
|
+
'left-mid': '',
|
|
168
|
+
mid: '',
|
|
169
|
+
'mid-mid': '',
|
|
170
|
+
right: '',
|
|
171
|
+
'right-mid': '',
|
|
172
|
+
middle: ' '
|
|
173
|
+
},
|
|
174
|
+
style: { 'padding-left': 0, 'padding-right': 0 },
|
|
175
|
+
colAligns: ['right'],
|
|
176
|
+
wordWrap: true,
|
|
177
|
+
colWidths: [12, 1, 100]
|
|
178
|
+
})
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function buildHeader(
|
|
182
|
+
highestSeverity,
|
|
183
|
+
contrastHeaderNum,
|
|
184
|
+
libraryName,
|
|
185
|
+
version,
|
|
186
|
+
numOfCVEs
|
|
187
|
+
) {
|
|
188
|
+
const vulnerabilityPluralised =
|
|
189
|
+
numOfCVEs > 1 ? 'vulnerabilities' : 'vulnerability'
|
|
190
|
+
const formattedHeaderNum = buildFormattedHeaderNum(contrastHeaderNum)
|
|
191
|
+
|
|
192
|
+
const headerColour = chalk.hex(highestSeverity.colour)
|
|
193
|
+
const headerNumAndSeverity = headerColour(
|
|
194
|
+
`${formattedHeaderNum} - [${highestSeverity.severity}]`
|
|
195
|
+
)
|
|
196
|
+
const libraryNameAndVersion = headerColour.bold(`${libraryName}-${version}`)
|
|
197
|
+
const vulnMessage = `${headerNumAndSeverity} ${libraryNameAndVersion}`
|
|
198
|
+
|
|
199
|
+
const introducesMessage = `introduces ${numOfCVEs} ${vulnerabilityPluralised}`
|
|
200
|
+
|
|
201
|
+
return new ReportOutputHeaderModel(vulnMessage, introducesMessage)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function buildBody(cveArray, advice) {
|
|
205
|
+
const orderedCvesWithSeverityAssigned = orderByHighestPrioritySca(
|
|
206
|
+
cveArray.map(cve => findCVESeveritySca(cve))
|
|
207
|
+
)
|
|
208
|
+
const issueMessage = getIssueRow(orderedCvesWithSeverityAssigned)
|
|
209
|
+
const adviceMessage = getAdviceRow(advice)
|
|
210
|
+
|
|
211
|
+
return new ReportOutputBodyModel(issueMessage, adviceMessage)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function getIssueRow(cveArray) {
|
|
215
|
+
const cveMessagesList = getIssueCveMsgList(cveArray)
|
|
216
|
+
return [chalk.bold('Issue'), ':', `${cveMessagesList.join(', ')}`]
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function getAdviceRow(advice) {
|
|
220
|
+
const latestOrClosest = advice.latestStableVersion
|
|
221
|
+
? advice.latestStableVersion
|
|
222
|
+
: advice.closestStableVersion
|
|
223
|
+
const displayAdvice = latestOrClosest
|
|
224
|
+
? `Change to version ${chalk.bold(latestOrClosest)}`
|
|
225
|
+
: 'No recommendation is available according to our data. Upgrade to the latest stable is the best advice we can give.'
|
|
226
|
+
|
|
227
|
+
return [chalk.bold(`Advice`), chalk.bold(`:`), `${displayAdvice}`]
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const buildFooter = reportModelStructure => {
|
|
231
|
+
const { critical, high, medium, low, note } =
|
|
232
|
+
countVulnerableLibrariesBySeverity(reportModelStructure)
|
|
233
|
+
|
|
234
|
+
const criticalMessage = chalk
|
|
235
|
+
.hex(CRITICAL_COLOUR)
|
|
236
|
+
.bold(`${critical} Critical`)
|
|
237
|
+
const highMessage = chalk.hex(HIGH_COLOUR).bold(`${high} High`)
|
|
238
|
+
const mediumMessage = chalk.hex(MEDIUM_COLOUR).bold(`${medium} Medium`)
|
|
239
|
+
const lowMessage = chalk.hex(LOW_COLOUR).bold(`${low} Low`)
|
|
240
|
+
const noteMessage = chalk.hex(NOTE_COLOUR).bold(`${note} Note`)
|
|
241
|
+
|
|
242
|
+
return {
|
|
243
|
+
criticalMessage,
|
|
244
|
+
highMessage,
|
|
245
|
+
mediumMessage,
|
|
246
|
+
lowMessage,
|
|
247
|
+
noteMessage
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const getIssueCveMsgList = reportSeverityModels => {
|
|
252
|
+
const cveMessages = []
|
|
253
|
+
reportSeverityModels.forEach(reportSeverityModel => {
|
|
254
|
+
const { colour, severity, name } = reportSeverityModel
|
|
255
|
+
|
|
256
|
+
const severityShorthand = chalk
|
|
257
|
+
.hex(colour)
|
|
258
|
+
.bold(`[${severity.charAt(0).toUpperCase()}]`)
|
|
259
|
+
|
|
260
|
+
const builtMessage = severityShorthand + name
|
|
261
|
+
cveMessages.push(builtMessage)
|
|
262
|
+
})
|
|
263
|
+
return cveMessages
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
module.exports = {
|
|
267
|
+
createSummaryMessageTop,
|
|
268
|
+
createSummaryMessageBottom,
|
|
269
|
+
printFormattedOutputSca,
|
|
270
|
+
getReportTable,
|
|
271
|
+
buildHeader,
|
|
272
|
+
buildBody,
|
|
273
|
+
getIssueRow,
|
|
274
|
+
buildFormattedHeaderNum,
|
|
275
|
+
getIssueCveMsgList
|
|
276
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
export class ScaReportModel {
|
|
2
|
+
uuid: string
|
|
3
|
+
groupName: string
|
|
4
|
+
artifactName: string
|
|
5
|
+
version: string
|
|
6
|
+
hash: string
|
|
7
|
+
fileName: string
|
|
8
|
+
libraryLanguage: string
|
|
9
|
+
vulnerable: boolean
|
|
10
|
+
privateLibrary: boolean
|
|
11
|
+
severity: string
|
|
12
|
+
releaseDate: string
|
|
13
|
+
latestVersionReleaseDate: string
|
|
14
|
+
latestVersion: string
|
|
15
|
+
versionsBehind: number
|
|
16
|
+
vulnerabilities: ScaReportVulnerabilityModel[]
|
|
17
|
+
remediationAdvice: ScaReportRemediationAdviceModel
|
|
18
|
+
|
|
19
|
+
constructor(library: any) {
|
|
20
|
+
this.uuid = library.uuid
|
|
21
|
+
this.groupName = library.groupName
|
|
22
|
+
this.artifactName = library.artifactName
|
|
23
|
+
this.version = library.version
|
|
24
|
+
this.hash = library.hash
|
|
25
|
+
this.fileName = library.fileName
|
|
26
|
+
this.libraryLanguage = library.libraryLanguage
|
|
27
|
+
this.vulnerable = library.vulnerable
|
|
28
|
+
this.privateLibrary = library.privateLibrary
|
|
29
|
+
this.severity = library.severity
|
|
30
|
+
this.releaseDate = library.releaseDate
|
|
31
|
+
this.latestVersionReleaseDate = library.latestVersionReleaseDate
|
|
32
|
+
this.latestVersion = library.latestVersion
|
|
33
|
+
this.versionsBehind = library.versionsBehind
|
|
34
|
+
this.vulnerabilities = library.vulnerabilities
|
|
35
|
+
this.remediationAdvice = library.remediationAdvice
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export class ScaReportVulnerabilityModel {
|
|
40
|
+
name: string
|
|
41
|
+
description: string
|
|
42
|
+
cvss2Vector: string
|
|
43
|
+
severityValue: number
|
|
44
|
+
severity: string
|
|
45
|
+
cvss3Vector: string
|
|
46
|
+
cvss3SeverityValue: number
|
|
47
|
+
cvss3Severity: string
|
|
48
|
+
hasCvss3: boolean
|
|
49
|
+
|
|
50
|
+
constructor(
|
|
51
|
+
name: string,
|
|
52
|
+
description: string,
|
|
53
|
+
cvss2Vector: string,
|
|
54
|
+
severityValue: number,
|
|
55
|
+
severity: string,
|
|
56
|
+
cvss3Vector: string,
|
|
57
|
+
cvss3SeverityValue: number,
|
|
58
|
+
cvss3Severity: string,
|
|
59
|
+
hasCvss3: boolean
|
|
60
|
+
) {
|
|
61
|
+
this.name = name
|
|
62
|
+
this.description = description
|
|
63
|
+
this.cvss2Vector = cvss2Vector
|
|
64
|
+
this.severityValue = severityValue
|
|
65
|
+
this.severity = severity
|
|
66
|
+
this.cvss3Vector = cvss3Vector
|
|
67
|
+
this.cvss3SeverityValue = cvss3SeverityValue
|
|
68
|
+
this.cvss3Severity = cvss3Severity
|
|
69
|
+
this.hasCvss3 = hasCvss3
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export class ScaReportRemediationAdviceModel {
|
|
74
|
+
closestStableVersion: string
|
|
75
|
+
latestStableVersion: string
|
|
76
|
+
|
|
77
|
+
constructor(closestStableVersion: string, latestStableVersion: string) {
|
|
78
|
+
this.closestStableVersion = closestStableVersion
|
|
79
|
+
this.latestStableVersion = latestStableVersion
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -46,17 +46,19 @@ const scaTreeUpload = async (analysis, config) => {
|
|
|
46
46
|
if (res.body.status === 'COMPLETED') {
|
|
47
47
|
keepChecking = false
|
|
48
48
|
return client.scaServiceReport(config, reportID).then(res => {
|
|
49
|
-
|
|
49
|
+
const reportBody = res.body
|
|
50
|
+
return { reportBody, reportID }
|
|
50
51
|
})
|
|
51
52
|
}
|
|
52
53
|
})
|
|
53
54
|
|
|
54
55
|
if (!keepChecking) {
|
|
55
|
-
return
|
|
56
|
+
return { reportArray: res.reportBody, reportID }
|
|
56
57
|
}
|
|
57
58
|
await requestUtils.sleep(5000)
|
|
58
59
|
}
|
|
59
|
-
|
|
60
|
+
|
|
61
|
+
return { reportArray: res, reportID }
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
module.exports = {
|
|
@@ -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
|
}
|