@contrast/contrast 1.0.8 → 1.0.9
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/languageAnalysisEngine/getProjectRootFilenames.js +3 -12
- package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +88 -53
- package/dist/audit/languageAnalysisEngine/report/models/reportOutputModel.js +4 -3
- package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +58 -11
- package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +38 -5
- package/dist/audit/languageAnalysisEngine/sendSnapshot.js +6 -30
- package/dist/audit/save.js +21 -13
- package/dist/commands/audit/auditConfig.js +0 -16
- package/dist/commands/audit/auditController.js +1 -10
- package/dist/commands/audit/help.js +7 -24
- package/dist/commands/audit/processAudit.js +1 -7
- package/dist/commands/audit/saveFile.js +2 -2
- package/dist/commands/scan/sca/scaAnalysis.js +22 -9
- package/dist/common/HTTPClient.js +8 -8
- package/dist/constants/constants.js +7 -2
- package/dist/constants/locales.js +24 -30
- package/dist/constants.js +11 -9
- package/dist/index.js +54 -45
- package/dist/lambda/lambda.js +5 -2
- package/dist/sbom/generateSbom.js +2 -2
- package/dist/scaAnalysis/common/formatMessage.js +7 -1
- package/dist/scaAnalysis/common/treeUpload.js +4 -5
- package/dist/scaAnalysis/dotnet/analysis.js +43 -0
- package/dist/scaAnalysis/dotnet/index.js +10 -0
- package/dist/scaAnalysis/javascript/analysis.js +4 -7
- package/dist/scaAnalysis/javascript/index.js +14 -5
- package/dist/scaAnalysis/php/analysis.js +14 -33
- package/dist/scaAnalysis/php/index.js +11 -4
- package/dist/scaAnalysis/ruby/analysis.js +2 -10
- package/dist/scan/autoDetection.js +18 -21
- package/dist/scan/fileUtils.js +31 -12
- package/dist/scan/formatScanOutput.js +3 -3
- package/dist/scan/scanConfig.js +2 -2
- package/dist/utils/getConfig.js +1 -6
- package/package.json +2 -3
- package/src/audit/languageAnalysisEngine/getProjectRootFilenames.js +3 -32
- package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +128 -68
- package/src/audit/languageAnalysisEngine/report/models/reportOutputModel.ts +11 -5
- package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +41 -19
- package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +43 -4
- package/src/audit/languageAnalysisEngine/sendSnapshot.js +6 -32
- package/src/audit/save.js +32 -16
- package/src/commands/audit/auditConfig.ts +0 -25
- package/src/commands/audit/auditController.ts +0 -11
- package/src/commands/audit/help.ts +7 -24
- package/src/commands/audit/processAudit.ts +1 -7
- package/src/commands/audit/saveFile.ts +2 -2
- package/src/commands/scan/processScan.js +0 -1
- package/src/commands/scan/sca/scaAnalysis.js +28 -13
- package/src/common/HTTPClient.js +9 -9
- package/src/constants/constants.js +9 -3
- package/src/constants/locales.js +47 -35
- package/src/constants.js +12 -10
- package/src/index.ts +76 -66
- package/src/lambda/lambda.ts +5 -2
- package/src/lambda/types.ts +1 -0
- package/src/sbom/generateSbom.ts +2 -2
- package/src/scaAnalysis/common/formatMessage.js +8 -1
- package/src/scaAnalysis/common/treeUpload.js +4 -5
- package/src/scaAnalysis/dotnet/analysis.js +54 -0
- package/src/scaAnalysis/dotnet/index.js +11 -0
- package/src/scaAnalysis/javascript/analysis.js +6 -7
- package/src/scaAnalysis/javascript/index.js +23 -7
- package/src/scaAnalysis/php/analysis.js +15 -35
- package/src/scaAnalysis/php/index.js +15 -4
- package/src/scaAnalysis/ruby/analysis.js +2 -11
- package/src/scan/autoDetection.js +18 -24
- package/src/scan/fileUtils.js +33 -12
- package/src/scan/formatScanOutput.ts +3 -3
- package/src/scan/scanConfig.js +2 -4
- package/src/utils/getConfig.ts +1 -12
- package/dist/audit/AnalysisEngine.js +0 -37
- package/dist/audit/autodetection/autoDetectLanguage.js +0 -32
- package/dist/audit/dotnetAnalysisEngine/index.js +0 -25
- package/dist/audit/dotnetAnalysisEngine/parseLockFileContents.js +0 -35
- package/dist/audit/dotnetAnalysisEngine/parseProjectFileContents.js +0 -15
- package/dist/audit/dotnetAnalysisEngine/readLockFileContents.js +0 -18
- package/dist/audit/dotnetAnalysisEngine/readProjectFileContents.js +0 -14
- package/dist/audit/dotnetAnalysisEngine/sanitizer.js +0 -9
- package/dist/audit/goAnalysisEngine/index.js +0 -17
- package/dist/audit/goAnalysisEngine/parseProjectFileContents.js +0 -164
- package/dist/audit/goAnalysisEngine/readProjectFileContents.js +0 -21
- package/dist/audit/goAnalysisEngine/sanitizer.js +0 -5
- package/dist/audit/javaAnalysisEngine/index.js +0 -34
- package/dist/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +0 -155
- package/dist/audit/javaAnalysisEngine/parseProjectFileContents.js +0 -353
- package/dist/audit/javaAnalysisEngine/readProjectFileContents.js +0 -98
- package/dist/audit/javaAnalysisEngine/sanitizer.js +0 -5
- package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +0 -25
- package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +0 -25
- package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasLockFile.js +0 -35
- package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +0 -24
- package/dist/audit/languageAnalysisEngine/constants.js +0 -20
- package/dist/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +0 -25
- package/dist/audit/languageAnalysisEngine/index.js +0 -39
- package/dist/audit/languageAnalysisEngine/languageAnalysisFactory.js +0 -66
- package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +0 -166
- package/dist/audit/nodeAnalysisEngine/handleNPMLockFileV2.js +0 -40
- package/dist/audit/nodeAnalysisEngine/index.js +0 -31
- package/dist/audit/nodeAnalysisEngine/parseNPMLockFileContents.js +0 -18
- package/dist/audit/nodeAnalysisEngine/parseYarnLockFileContents.js +0 -18
- package/dist/audit/nodeAnalysisEngine/readNPMLockFileContents.js +0 -17
- package/dist/audit/nodeAnalysisEngine/readProjectFileContents.js +0 -14
- package/dist/audit/nodeAnalysisEngine/readYarnLockFileContents.js +0 -24
- package/dist/audit/nodeAnalysisEngine/sanitizer.js +0 -9
- package/dist/audit/phpAnalysisEngine/index.js +0 -23
- package/dist/audit/phpAnalysisEngine/parseLockFileContents.js +0 -52
- package/dist/audit/phpAnalysisEngine/readLockFileContents.js +0 -13
- package/dist/audit/phpAnalysisEngine/readProjectFileContents.js +0 -16
- package/dist/audit/phpAnalysisEngine/sanitizer.js +0 -5
- package/dist/audit/pythonAnalysisEngine/index.js +0 -25
- package/dist/audit/pythonAnalysisEngine/parsePipfileLockContents.js +0 -17
- package/dist/audit/pythonAnalysisEngine/parseProjectFileContents.js +0 -21
- package/dist/audit/pythonAnalysisEngine/readPipfileLockFileContents.js +0 -13
- package/dist/audit/pythonAnalysisEngine/readPythonProjectFileContents.js +0 -14
- package/dist/audit/pythonAnalysisEngine/sanitizer.js +0 -7
- package/dist/audit/rubyAnalysisEngine/index.js +0 -25
- package/dist/audit/rubyAnalysisEngine/parseGemfileLockContents.js +0 -176
- package/dist/audit/rubyAnalysisEngine/parsedGemfile.js +0 -22
- package/dist/audit/rubyAnalysisEngine/readGemfileContents.js +0 -14
- package/dist/audit/rubyAnalysisEngine/readGemfileLockContents.js +0 -14
- package/dist/audit/rubyAnalysisEngine/sanitizer.js +0 -6
- package/src/audit/AnalysisEngine.js +0 -103
- package/src/audit/autodetection/autoDetectLanguage.ts +0 -40
- package/src/audit/dotnetAnalysisEngine/index.js +0 -26
- package/src/audit/dotnetAnalysisEngine/parseLockFileContents.js +0 -47
- package/src/audit/dotnetAnalysisEngine/parseProjectFileContents.js +0 -29
- package/src/audit/dotnetAnalysisEngine/readLockFileContents.js +0 -30
- package/src/audit/dotnetAnalysisEngine/readProjectFileContents.js +0 -26
- package/src/audit/dotnetAnalysisEngine/sanitizer.js +0 -11
- package/src/audit/goAnalysisEngine/index.js +0 -18
- package/src/audit/goAnalysisEngine/parseProjectFileContents.js +0 -209
- package/src/audit/goAnalysisEngine/readProjectFileContents.js +0 -31
- package/src/audit/goAnalysisEngine/sanitizer.js +0 -7
- package/src/audit/javaAnalysisEngine/index.js +0 -41
- package/src/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +0 -225
- package/src/audit/javaAnalysisEngine/parseProjectFileContents.js +0 -420
- package/src/audit/javaAnalysisEngine/readProjectFileContents.js +0 -141
- package/src/audit/javaAnalysisEngine/sanitizer.js +0 -6
- package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +0 -36
- package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +0 -42
- package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasLockFile.js +0 -54
- package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +0 -33
- package/src/audit/languageAnalysisEngine/constants.js +0 -23
- package/src/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +0 -41
- package/src/audit/languageAnalysisEngine/index.js +0 -45
- package/src/audit/languageAnalysisEngine/languageAnalysisFactory.js +0 -96
- package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +0 -251
- package/src/audit/nodeAnalysisEngine/handleNPMLockFileV2.js +0 -49
- package/src/audit/nodeAnalysisEngine/index.js +0 -35
- package/src/audit/nodeAnalysisEngine/parseNPMLockFileContents.js +0 -20
- package/src/audit/nodeAnalysisEngine/parseYarnLockFileContents.js +0 -26
- package/src/audit/nodeAnalysisEngine/readNPMLockFileContents.js +0 -23
- package/src/audit/nodeAnalysisEngine/readProjectFileContents.js +0 -27
- package/src/audit/nodeAnalysisEngine/readYarnLockFileContents.js +0 -36
- package/src/audit/nodeAnalysisEngine/sanitizer.js +0 -11
- package/src/audit/phpAnalysisEngine/index.js +0 -27
- package/src/audit/phpAnalysisEngine/parseLockFileContents.js +0 -60
- package/src/audit/phpAnalysisEngine/readLockFileContents.js +0 -14
- package/src/audit/phpAnalysisEngine/readProjectFileContents.js +0 -25
- package/src/audit/phpAnalysisEngine/sanitizer.js +0 -4
- package/src/audit/pythonAnalysisEngine/index.js +0 -55
- package/src/audit/pythonAnalysisEngine/parsePipfileLockContents.js +0 -23
- package/src/audit/pythonAnalysisEngine/parseProjectFileContents.js +0 -33
- package/src/audit/pythonAnalysisEngine/readPipfileLockFileContents.js +0 -16
- package/src/audit/pythonAnalysisEngine/readPythonProjectFileContents.js +0 -22
- package/src/audit/pythonAnalysisEngine/sanitizer.js +0 -9
- package/src/audit/rubyAnalysisEngine/index.js +0 -30
- package/src/audit/rubyAnalysisEngine/parseGemfileLockContents.js +0 -215
- package/src/audit/rubyAnalysisEngine/parsedGemfile.js +0 -39
- package/src/audit/rubyAnalysisEngine/readGemfileContents.js +0 -18
- package/src/audit/rubyAnalysisEngine/readGemfileLockContents.js +0 -17
- package/src/audit/rubyAnalysisEngine/sanitizer.js +0 -8
|
@@ -9,11 +9,11 @@ import { orderBy } from 'lodash'
|
|
|
9
9
|
import chalk from 'chalk'
|
|
10
10
|
import { ReportCVEModel, ReportLibraryModel } from './models/reportLibraryModel'
|
|
11
11
|
import {
|
|
12
|
+
countVulnerableLibrariesBySeverity,
|
|
12
13
|
findCVESeveritiesAndOrderByHighestPriority,
|
|
13
14
|
findHighestSeverityCVE,
|
|
14
15
|
findNameAndVersion,
|
|
15
|
-
severityCountAllCVEs
|
|
16
|
-
severityCountAllLibraries
|
|
16
|
+
severityCountAllCVEs
|
|
17
17
|
} from './utils/reportUtils'
|
|
18
18
|
import { SeverityCountModel } from './models/severityCountModel'
|
|
19
19
|
import {
|
|
@@ -28,16 +28,16 @@ import {
|
|
|
28
28
|
MEDIUM_COLOUR,
|
|
29
29
|
NOTE_COLOUR
|
|
30
30
|
} from '../../../constants/constants'
|
|
31
|
+
import Table from 'cli-table3'
|
|
31
32
|
|
|
32
|
-
export const
|
|
33
|
-
id: string,
|
|
33
|
+
export const createSummaryMessage = (
|
|
34
34
|
numberOfVulnerableLibraries: number,
|
|
35
35
|
numberOfCves: number
|
|
36
36
|
) => {
|
|
37
37
|
numberOfVulnerableLibraries === 1
|
|
38
|
-
? console.log(`Found 1 vulnerable library containing ${numberOfCves}
|
|
38
|
+
? console.log(`Found 1 vulnerable library containing ${numberOfCves} CVE`)
|
|
39
39
|
: console.log(
|
|
40
|
-
`Found ${numberOfVulnerableLibraries} vulnerable libraries containing ${numberOfCves} CVEs
|
|
40
|
+
`Found ${numberOfVulnerableLibraries} vulnerable libraries containing ${numberOfCves} CVEs`
|
|
41
41
|
)
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -59,21 +59,35 @@ export const getReport = async (config: any, reportId: string) => {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
export const printVulnerabilityResponse = (
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
config: any,
|
|
63
|
+
vulnerableLibraries: ReportLibraryModel[],
|
|
64
|
+
numberOfVulnerableLibraries: number,
|
|
65
|
+
numberOfCves: number,
|
|
66
|
+
guidance: any
|
|
64
67
|
) => {
|
|
65
68
|
let hasSomeVulnerabilitiesReported = false
|
|
66
|
-
printFormattedOutput(
|
|
67
|
-
|
|
69
|
+
printFormattedOutput(
|
|
70
|
+
config,
|
|
71
|
+
vulnerableLibraries,
|
|
72
|
+
numberOfVulnerableLibraries,
|
|
73
|
+
numberOfCves,
|
|
74
|
+
guidance
|
|
75
|
+
)
|
|
76
|
+
if (Object.keys(vulnerableLibraries).length > 0) {
|
|
68
77
|
hasSomeVulnerabilitiesReported = true
|
|
69
78
|
}
|
|
70
79
|
return hasSomeVulnerabilitiesReported
|
|
71
80
|
}
|
|
72
81
|
|
|
73
82
|
export const printFormattedOutput = (
|
|
83
|
+
config: any,
|
|
74
84
|
libraries: ReportLibraryModel[],
|
|
75
|
-
|
|
85
|
+
numberOfVulnerableLibraries: number,
|
|
86
|
+
numberOfCves: number,
|
|
87
|
+
guidance: any
|
|
76
88
|
) => {
|
|
89
|
+
createSummaryMessage(numberOfVulnerableLibraries, numberOfCves)
|
|
90
|
+
console.log()
|
|
77
91
|
const report = new ReportList()
|
|
78
92
|
|
|
79
93
|
for (const library of libraries) {
|
|
@@ -91,7 +105,6 @@ export const printFormattedOutput = (
|
|
|
91
105
|
),
|
|
92
106
|
library.cveArray
|
|
93
107
|
)
|
|
94
|
-
|
|
95
108
|
report.reportOutputList.push(newOutputModel)
|
|
96
109
|
}
|
|
97
110
|
|
|
@@ -105,17 +118,40 @@ export const printFormattedOutput = (
|
|
|
105
118
|
return reportListItem.compositeKey.numberOfSeverities
|
|
106
119
|
}
|
|
107
120
|
],
|
|
108
|
-
['desc']
|
|
121
|
+
['asc', 'desc']
|
|
109
122
|
)
|
|
110
123
|
|
|
111
|
-
let contrastHeaderNumCounter =
|
|
112
|
-
outputOrderedByLowestSeverityAndLowestNumOfCvesFirst.length + 1
|
|
124
|
+
let contrastHeaderNumCounter = 0
|
|
113
125
|
for (const reportModel of outputOrderedByLowestSeverityAndLowestNumOfCvesFirst) {
|
|
114
|
-
contrastHeaderNumCounter
|
|
126
|
+
contrastHeaderNumCounter++
|
|
115
127
|
const { libraryName, libraryVersion, highestSeverity } =
|
|
116
128
|
reportModel.compositeKey
|
|
117
129
|
const numOfCVEs = reportModel.cveArray.length
|
|
118
130
|
|
|
131
|
+
const table = new Table({
|
|
132
|
+
chars: {
|
|
133
|
+
top: '',
|
|
134
|
+
'top-mid': '',
|
|
135
|
+
'top-left': '',
|
|
136
|
+
'top-right': '',
|
|
137
|
+
bottom: '',
|
|
138
|
+
'bottom-mid': '',
|
|
139
|
+
'bottom-left': '',
|
|
140
|
+
'bottom-right': '',
|
|
141
|
+
left: '',
|
|
142
|
+
'left-mid': '',
|
|
143
|
+
mid: '',
|
|
144
|
+
'mid-mid': '',
|
|
145
|
+
right: '',
|
|
146
|
+
'right-mid': '',
|
|
147
|
+
middle: ' '
|
|
148
|
+
},
|
|
149
|
+
style: { 'padding-left': 0, 'padding-right': 0 },
|
|
150
|
+
colAligns: ['right'],
|
|
151
|
+
wordWrap: true,
|
|
152
|
+
colWidths: [12, 1, 100]
|
|
153
|
+
})
|
|
154
|
+
|
|
119
155
|
const header = buildHeader(
|
|
120
156
|
highestSeverity,
|
|
121
157
|
contrastHeaderNumCounter,
|
|
@@ -124,31 +160,36 @@ export const printFormattedOutput = (
|
|
|
124
160
|
numOfCVEs
|
|
125
161
|
)
|
|
126
162
|
|
|
127
|
-
const
|
|
163
|
+
const advice = gatherRemediationAdvice(guidance, reportModel)
|
|
164
|
+
|
|
165
|
+
const body = buildBody(reportModel.cveArray, advice)
|
|
128
166
|
|
|
129
167
|
const reportOutputModel = new ReportOutputModel(header, body)
|
|
168
|
+
|
|
169
|
+
table.push(
|
|
170
|
+
reportOutputModel.body.issueMessage,
|
|
171
|
+
reportOutputModel.body.issueMessageCves,
|
|
172
|
+
reportOutputModel.body.adviceMessage
|
|
173
|
+
)
|
|
174
|
+
|
|
130
175
|
console.log(
|
|
131
176
|
reportOutputModel.header.vulnMessage,
|
|
132
177
|
reportOutputModel.header.introducesMessage
|
|
133
178
|
)
|
|
134
|
-
console.log(
|
|
135
|
-
console.log(reportOutputModel.body.adviceMessage + '\n')
|
|
179
|
+
console.log(table.toString() + '\n')
|
|
136
180
|
}
|
|
137
181
|
|
|
182
|
+
createSummaryMessage(numberOfVulnerableLibraries, numberOfCves)
|
|
138
183
|
const {
|
|
139
184
|
criticalMessage,
|
|
140
185
|
highMessage,
|
|
141
186
|
mediumMessage,
|
|
142
187
|
lowMessage,
|
|
143
|
-
noteMessage
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
console.log(
|
|
149
|
-
`${criticalMessage} | ${highMessage} | ${mediumMessage} | ${lowMessage} | ${noteMessage}`
|
|
150
|
-
)
|
|
151
|
-
}
|
|
188
|
+
noteMessage
|
|
189
|
+
} = buildFooter(outputOrderedByLowestSeverityAndLowestNumOfCvesFirst)
|
|
190
|
+
console.log(
|
|
191
|
+
`${criticalMessage} | ${highMessage} | ${mediumMessage} | ${lowMessage} | ${noteMessage}`
|
|
192
|
+
)
|
|
152
193
|
}
|
|
153
194
|
|
|
154
195
|
export function buildHeader(
|
|
@@ -168,14 +209,12 @@ export function buildHeader(
|
|
|
168
209
|
`${formattedHeaderNum} - [${highestSeverity.severity}] ${libraryName}-${version}`
|
|
169
210
|
)
|
|
170
211
|
|
|
171
|
-
const introducesMessage =
|
|
172
|
-
`introduces ${numOfCVEs} ${vulnerabilityPluralised}`
|
|
173
|
-
)
|
|
212
|
+
const introducesMessage = `introduces ${numOfCVEs} ${vulnerabilityPluralised}`
|
|
174
213
|
|
|
175
214
|
return new ReportOutputHeaderModel(vulnMessage, introducesMessage)
|
|
176
215
|
}
|
|
177
216
|
|
|
178
|
-
export function buildBody(cveArray: ReportCVEModel[]) {
|
|
217
|
+
export function buildBody(cveArray: ReportCVEModel[], advice: any) {
|
|
179
218
|
const cveMessages: string[] = []
|
|
180
219
|
|
|
181
220
|
findCVESeveritiesAndOrderByHighestPriority(cveArray).forEach(
|
|
@@ -187,57 +226,57 @@ export function buildBody(cveArray: ReportCVEModel[]) {
|
|
|
187
226
|
.hex(outputColour)
|
|
188
227
|
.bold(`[${severity.charAt(0).toUpperCase()}]`)
|
|
189
228
|
|
|
190
|
-
const builtMessage =
|
|
229
|
+
const builtMessage = severityShorthand + cveName
|
|
191
230
|
cveMessages.push(builtMessage)
|
|
192
231
|
}
|
|
193
232
|
)
|
|
194
233
|
|
|
195
234
|
const numAndSeverityType = getNumOfAndSeverityType(cveArray)
|
|
196
235
|
|
|
197
|
-
const issueMessage =
|
|
198
|
-
|
|
199
|
-
|
|
236
|
+
const issueMessage = [chalk.bold('Issue'), ':', `${numAndSeverityType}`]
|
|
237
|
+
|
|
238
|
+
const issueMessageCves = ['', '', cveMessages.join(', ')]
|
|
200
239
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
)}.`
|
|
240
|
+
//todo different advice based on remediationGuidance being available or now
|
|
241
|
+
// console.log(advice)
|
|
204
242
|
|
|
205
|
-
|
|
243
|
+
const displayAdvice = advice?.minimum
|
|
244
|
+
? `Update to version ${chalk.bold(advice.minimum)}`
|
|
245
|
+
: `Update to latest version`
|
|
246
|
+
|
|
247
|
+
const adviceMessage = [chalk.bold('Advice'), ':', displayAdvice]
|
|
248
|
+
|
|
249
|
+
return new ReportOutputBodyModel(
|
|
250
|
+
issueMessage,
|
|
251
|
+
issueMessageCves,
|
|
252
|
+
adviceMessage
|
|
253
|
+
)
|
|
206
254
|
}
|
|
207
255
|
|
|
208
|
-
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
const highMessage = chalk.hex(HIGH_COLOUR).bold(`${high} High`)
|
|
215
|
-
const mediumMessage = chalk.hex(MEDIUM_COLOUR).bold(`${medium} Medium`)
|
|
216
|
-
const lowMessage = chalk.hex(LOW_COLOUR).bold(`${low} Low`)
|
|
217
|
-
const noteMessage = chalk.hex(NOTE_COLOUR).bold(`${note} Note`)
|
|
256
|
+
export function gatherRemediationAdvice(guidance: any, reportModel: any) {
|
|
257
|
+
const guidanceData = {
|
|
258
|
+
minimum: undefined,
|
|
259
|
+
maximum: undefined,
|
|
260
|
+
latest: undefined
|
|
261
|
+
}
|
|
218
262
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
263
|
+
const data =
|
|
264
|
+
guidance[
|
|
265
|
+
reportModel.compositeKey.libraryName +
|
|
266
|
+
'@' +
|
|
267
|
+
reportModel.compositeKey.libraryVersion
|
|
268
|
+
]
|
|
269
|
+
|
|
270
|
+
if (data) {
|
|
271
|
+
guidanceData.minimum = data.minUpgradeVersion
|
|
272
|
+
guidanceData.maximum = data.maxUpgradeVersion
|
|
226
273
|
}
|
|
274
|
+
|
|
275
|
+
return guidanceData
|
|
227
276
|
}
|
|
228
277
|
|
|
229
278
|
export function buildFormattedHeaderNum(contrastHeaderNum: number) {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
if (contrastHeaderNum < 10) {
|
|
233
|
-
formattedHeaderNum = `00${contrastHeaderNum}`
|
|
234
|
-
} else if (contrastHeaderNum >= 10 && contrastHeaderNum < 100) {
|
|
235
|
-
formattedHeaderNum = `0${contrastHeaderNum}`
|
|
236
|
-
} else if (contrastHeaderNum >= 100) {
|
|
237
|
-
formattedHeaderNum = contrastHeaderNum
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
return `CONTRAST-${formattedHeaderNum}`
|
|
279
|
+
return `CONTRAST-${contrastHeaderNum.toString().padStart(3, '0')}`
|
|
241
280
|
}
|
|
242
281
|
|
|
243
282
|
export function getNumOfAndSeverityType(cveArray: ReportCVEModel[]) {
|
|
@@ -257,3 +296,24 @@ export function getNumOfAndSeverityType(cveArray: ReportCVEModel[]) {
|
|
|
257
296
|
.replace(/\s+/g, ' ')
|
|
258
297
|
.trim()
|
|
259
298
|
}
|
|
299
|
+
|
|
300
|
+
const buildFooter = (reportModelStructure: ReportModelStructure[]) => {
|
|
301
|
+
const { critical, high, medium, low, note } =
|
|
302
|
+
countVulnerableLibrariesBySeverity(reportModelStructure)
|
|
303
|
+
|
|
304
|
+
const criticalMessage = chalk
|
|
305
|
+
.hex(CRITICAL_COLOUR)
|
|
306
|
+
.bold(`${critical} Critical`)
|
|
307
|
+
const highMessage = chalk.hex(HIGH_COLOUR).bold(`${high} High`)
|
|
308
|
+
const mediumMessage = chalk.hex(MEDIUM_COLOUR).bold(`${medium} Medium`)
|
|
309
|
+
const lowMessage = chalk.hex(LOW_COLOUR).bold(`${low} Low`)
|
|
310
|
+
const noteMessage = chalk.hex(NOTE_COLOUR).bold(`${note} Note`)
|
|
311
|
+
|
|
312
|
+
return {
|
|
313
|
+
criticalMessage,
|
|
314
|
+
highMessage,
|
|
315
|
+
mediumMessage,
|
|
316
|
+
lowMessage,
|
|
317
|
+
noteMessage
|
|
318
|
+
}
|
|
319
|
+
}
|
|
@@ -19,11 +19,17 @@ export class ReportOutputHeaderModel {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export class ReportOutputBodyModel {
|
|
22
|
-
issueMessage: string
|
|
23
|
-
|
|
22
|
+
issueMessage: string[]
|
|
23
|
+
issueMessageCves: string[]
|
|
24
|
+
adviceMessage: string[]
|
|
24
25
|
|
|
25
|
-
constructor(
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
constructor(
|
|
27
|
+
issueMessage: string[],
|
|
28
|
+
issueMessageCves: string[],
|
|
29
|
+
adviceMessage: string[]
|
|
30
|
+
) {
|
|
31
|
+
this.issueMessage = issueMessage
|
|
32
|
+
this.issueMessageCves = issueMessageCves
|
|
33
|
+
this.adviceMessage = adviceMessage
|
|
28
34
|
}
|
|
29
35
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
createLibraryHeader,
|
|
3
2
|
getReport,
|
|
4
3
|
printVulnerabilityResponse
|
|
5
4
|
} from './commonReportingFunctions'
|
|
@@ -9,33 +8,51 @@ import {
|
|
|
9
8
|
} from './utils/reportUtils'
|
|
10
9
|
import i18n from 'i18n'
|
|
11
10
|
import chalk from 'chalk'
|
|
11
|
+
import * as constants from '../../../constants/constants'
|
|
12
12
|
|
|
13
|
-
export
|
|
14
|
-
|
|
15
|
-
applicationId: string,
|
|
16
|
-
reportId: string
|
|
17
|
-
) {
|
|
18
|
-
const reportResponse = await getReport(analysis.config, reportId)
|
|
13
|
+
export function convertKeysToStandardFormat(config: any, guidance: any) {
|
|
14
|
+
let convertedGuidance = guidance
|
|
19
15
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
switch (config.language) {
|
|
17
|
+
case constants.supportedLanguages.JAVA:
|
|
18
|
+
case constants.supportedLanguages.GO:
|
|
19
|
+
case constants.supportedLanguages.PHP:
|
|
20
|
+
break
|
|
21
|
+
case constants.supportedLanguages.NODE:
|
|
22
|
+
case constants.supportedLanguages.DOTNET:
|
|
23
|
+
case constants.supportedLanguages.PYTHON:
|
|
24
|
+
case constants.supportedLanguages.RUBY:
|
|
25
|
+
convertedGuidance = convertJSDotNetPython(guidance)
|
|
26
|
+
break
|
|
27
27
|
}
|
|
28
|
+
return convertedGuidance
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function convertJSDotNetPython(guidance: any) {
|
|
32
|
+
const returnObject = {}
|
|
33
|
+
|
|
34
|
+
Object.entries(guidance).forEach(([key, value]) => {
|
|
35
|
+
const splitKey = key.split('/')
|
|
36
|
+
if (splitKey.length === 2) {
|
|
37
|
+
// @ts-ignore
|
|
38
|
+
returnObject[splitKey[1]] = value
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
return returnObject
|
|
28
42
|
}
|
|
29
43
|
|
|
30
44
|
export function formatVulnerabilityOutput(
|
|
31
45
|
libraryVulnerabilityResponse: any,
|
|
32
46
|
id: string,
|
|
33
|
-
config: any
|
|
47
|
+
config: any,
|
|
48
|
+
remediationGuidance: any
|
|
34
49
|
) {
|
|
35
50
|
const vulnerableLibraries = convertGenericToTypedLibraryVulns(
|
|
36
51
|
libraryVulnerabilityResponse
|
|
37
52
|
)
|
|
38
53
|
|
|
54
|
+
const guidance = convertKeysToStandardFormat(config, remediationGuidance)
|
|
55
|
+
|
|
39
56
|
const numberOfVulnerableLibraries = vulnerableLibraries.length
|
|
40
57
|
|
|
41
58
|
if (numberOfVulnerableLibraries === 0) {
|
|
@@ -59,11 +76,12 @@ export function formatVulnerabilityOutput(
|
|
|
59
76
|
let numberOfCves = 0
|
|
60
77
|
vulnerableLibraries.forEach(lib => (numberOfCves += lib.cveArray.length))
|
|
61
78
|
|
|
62
|
-
createLibraryHeader(id, numberOfVulnerableLibraries, numberOfCves)
|
|
63
|
-
|
|
64
79
|
const hasSomeVulnerabilitiesReported = printVulnerabilityResponse(
|
|
80
|
+
config,
|
|
65
81
|
vulnerableLibraries,
|
|
66
|
-
|
|
82
|
+
numberOfVulnerableLibraries,
|
|
83
|
+
numberOfCves,
|
|
84
|
+
guidance
|
|
67
85
|
)
|
|
68
86
|
|
|
69
87
|
return [
|
|
@@ -75,6 +93,7 @@ export function formatVulnerabilityOutput(
|
|
|
75
93
|
}
|
|
76
94
|
|
|
77
95
|
export async function vulnerabilityReportV2(config: any, reportId: string) {
|
|
96
|
+
console.log()
|
|
78
97
|
const reportResponse = await getReport(config, reportId)
|
|
79
98
|
|
|
80
99
|
if (reportResponse !== undefined) {
|
|
@@ -82,7 +101,10 @@ export async function vulnerabilityReportV2(config: any, reportId: string) {
|
|
|
82
101
|
formatVulnerabilityOutput(
|
|
83
102
|
reportResponse.vulnerabilities,
|
|
84
103
|
config.applicationId,
|
|
85
|
-
config
|
|
104
|
+
config,
|
|
105
|
+
reportResponse.remediationGuidance
|
|
106
|
+
? reportResponse.remediationGuidance
|
|
107
|
+
: {}
|
|
86
108
|
)
|
|
87
109
|
}
|
|
88
110
|
}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
ReportLibraryModel
|
|
4
4
|
} from '../models/reportLibraryModel'
|
|
5
5
|
import { ReportSeverityModel } from '../models/reportSeverityModel'
|
|
6
|
-
import languageAnalysisEngine from '
|
|
6
|
+
import languageAnalysisEngine from './../../../../constants/constants'
|
|
7
7
|
import {
|
|
8
8
|
CRITICAL_COLOUR,
|
|
9
9
|
CRITICAL_PRIORITY,
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
} from '../../../../constants/constants'
|
|
19
19
|
import { orderBy } from 'lodash'
|
|
20
20
|
import { SeverityCountModel } from '../models/severityCountModel'
|
|
21
|
+
import { ReportModelStructure } from '../models/reportListModel'
|
|
21
22
|
const {
|
|
22
23
|
supportedLanguages: { GO }
|
|
23
24
|
} = languageAnalysisEngine
|
|
@@ -122,11 +123,49 @@ export function findNameAndVersion(library: ReportLibraryModel, config: any) {
|
|
|
122
123
|
|
|
123
124
|
return { name, version }
|
|
124
125
|
} else {
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
const
|
|
126
|
+
//spreads items from split into set so no duplicates appear
|
|
127
|
+
const uniqueSplitLibraryName = [...new Set(library.name.split('/'))]
|
|
128
|
+
const nameVersion = uniqueSplitLibraryName[1].split('@')
|
|
129
|
+
|
|
130
|
+
let parentLibrary
|
|
131
|
+
let name
|
|
132
|
+
if (
|
|
133
|
+
uniqueSplitLibraryName[0] !== 'null' &&
|
|
134
|
+
uniqueSplitLibraryName[0] !== '' &&
|
|
135
|
+
!uniqueSplitLibraryName[1].includes(uniqueSplitLibraryName[0])
|
|
136
|
+
) {
|
|
137
|
+
//if the parent lib (element 0) is not null, not blank and not already part of the library name
|
|
138
|
+
//e.g. shared-ini-file-loader-1.0.0-rc.3 is very generic - converts to @aws-sdk/shared-ini-file-loader-1.0.0-rc.3
|
|
139
|
+
parentLibrary = uniqueSplitLibraryName[0]
|
|
140
|
+
name = `${parentLibrary}/${nameVersion[0]}`
|
|
141
|
+
} else {
|
|
142
|
+
name = nameVersion[0]
|
|
143
|
+
}
|
|
144
|
+
|
|
128
145
|
const version = nameVersion[1]
|
|
129
146
|
|
|
130
147
|
return { name, version }
|
|
131
148
|
}
|
|
132
149
|
}
|
|
150
|
+
|
|
151
|
+
export function countVulnerableLibrariesBySeverity(
|
|
152
|
+
reportModelStructure: ReportModelStructure[]
|
|
153
|
+
) {
|
|
154
|
+
const severityCount = new SeverityCountModel()
|
|
155
|
+
reportModelStructure.forEach(vuln => {
|
|
156
|
+
const currentSeverity = vuln.compositeKey.highestSeverity.severity
|
|
157
|
+
if (currentSeverity === 'CRITICAL') {
|
|
158
|
+
severityCount.critical += 1
|
|
159
|
+
} else if (currentSeverity === 'HIGH') {
|
|
160
|
+
severityCount.high += 1
|
|
161
|
+
} else if (currentSeverity === 'MEDIUM') {
|
|
162
|
+
severityCount.medium += 1
|
|
163
|
+
} else if (currentSeverity === 'LOW') {
|
|
164
|
+
severityCount.low += 1
|
|
165
|
+
} else if (currentSeverity === 'NOTE') {
|
|
166
|
+
severityCount.note += 1
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
return severityCount
|
|
171
|
+
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
const { handleResponseErrors } = require('../../common/errorHandling')
|
|
2
|
-
const { APP_VERSION } = require('../../constants/constants')
|
|
3
1
|
const commonApi = require('../../utils/commonApi')
|
|
4
2
|
const _ = require('lodash')
|
|
5
3
|
const oraFunctions = require('../../utils/oraWrapper')
|
|
@@ -8,30 +6,6 @@ const oraWrapper = require('../../utils/oraWrapper')
|
|
|
8
6
|
const requestUtils = require('../../utils/requestUtils')
|
|
9
7
|
const { performance } = require('perf_hooks')
|
|
10
8
|
|
|
11
|
-
const newSendSnapShot = async analysis => {
|
|
12
|
-
const analysisLanguage = analysis.config.language.toLowerCase()
|
|
13
|
-
const requestBody = {
|
|
14
|
-
appID: analysis.config.applicationId,
|
|
15
|
-
cliVersion: APP_VERSION,
|
|
16
|
-
snapshot: { [analysisLanguage]: analysis[analysisLanguage] }
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const client = commonApi.getHttpClient(analysis.config)
|
|
20
|
-
|
|
21
|
-
return client
|
|
22
|
-
.sendSnapshot(requestBody, analysis.config)
|
|
23
|
-
.then(res => {
|
|
24
|
-
if (res.statusCode === 201) {
|
|
25
|
-
return res.body
|
|
26
|
-
} else {
|
|
27
|
-
handleResponseErrors(res, 'snapshot')
|
|
28
|
-
}
|
|
29
|
-
})
|
|
30
|
-
.catch(err => {
|
|
31
|
-
console.log(err)
|
|
32
|
-
})
|
|
33
|
-
}
|
|
34
|
-
|
|
35
9
|
const pollSnapshotResults = async (config, snapshotId, client) => {
|
|
36
10
|
await requestUtils.sleep(5000)
|
|
37
11
|
return client
|
|
@@ -49,9 +23,9 @@ const getTimeout = config => {
|
|
|
49
23
|
return config.timeout
|
|
50
24
|
} else {
|
|
51
25
|
if (config.verbose) {
|
|
52
|
-
console.log('Timeout set to
|
|
26
|
+
console.log('Timeout set to 5 minutes')
|
|
53
27
|
}
|
|
54
|
-
return
|
|
28
|
+
return 300
|
|
55
29
|
}
|
|
56
30
|
}
|
|
57
31
|
|
|
@@ -91,16 +65,16 @@ const pollForSnapshotCompletition = async (
|
|
|
91
65
|
if (requestUtils.millisToSeconds(endTime) > timeout) {
|
|
92
66
|
oraFunctions.failSpinner(
|
|
93
67
|
reportSpinner,
|
|
94
|
-
'Contrast audit timed out at the specified
|
|
68
|
+
'Contrast audit timed out at the specified timeout of ' +
|
|
69
|
+
timeout +
|
|
70
|
+
' seconds.'
|
|
95
71
|
)
|
|
96
|
-
|
|
97
|
-
process.exit(1)
|
|
72
|
+
throw new Error('You can update the timeout using --timeout')
|
|
98
73
|
}
|
|
99
74
|
}
|
|
100
75
|
}
|
|
101
76
|
}
|
|
102
77
|
|
|
103
78
|
module.exports = {
|
|
104
|
-
newSendSnapShot: newSendSnapShot,
|
|
105
79
|
pollForSnapshotCompletition: pollForSnapshotCompletition
|
|
106
80
|
}
|
package/src/audit/save.js
CHANGED
|
@@ -3,27 +3,43 @@ const i18n = require('i18n')
|
|
|
3
3
|
const chalk = require('chalk')
|
|
4
4
|
const save = require('../commands/audit/saveFile')
|
|
5
5
|
const sbom = require('../sbom/generateSbom')
|
|
6
|
+
const {
|
|
7
|
+
SBOM_CYCLONE_DX_FILE,
|
|
8
|
+
SBOM_SPDX_FILE
|
|
9
|
+
} = require('../constants/constants')
|
|
6
10
|
|
|
7
11
|
async function auditSave(config) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
12
|
+
let fileFormat
|
|
13
|
+
switch (config.save) {
|
|
14
|
+
case null:
|
|
15
|
+
case SBOM_CYCLONE_DX_FILE:
|
|
16
|
+
fileFormat = SBOM_CYCLONE_DX_FILE
|
|
17
|
+
break
|
|
18
|
+
case SBOM_SPDX_FILE:
|
|
19
|
+
fileFormat = SBOM_SPDX_FILE
|
|
20
|
+
break
|
|
21
|
+
default:
|
|
22
|
+
break
|
|
23
|
+
}
|
|
11
24
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
25
|
+
if (fileFormat) {
|
|
26
|
+
save.saveFile(
|
|
27
|
+
config,
|
|
28
|
+
fileFormat,
|
|
29
|
+
await sbom.generateSbom(config, fileFormat)
|
|
30
|
+
)
|
|
31
|
+
const filename = `${config.applicationId}-sbom-${fileFormat}.json`
|
|
32
|
+
if (fs.existsSync(filename)) {
|
|
33
|
+
console.log(i18n.__('auditSBOMSaveSuccess') + ` - ${filename}`)
|
|
22
34
|
} else {
|
|
23
|
-
console.log(
|
|
35
|
+
console.log(
|
|
36
|
+
chalk.yellow.bold(
|
|
37
|
+
`\n Unable to save ${filename} Software Bill of Materials (SBOM)`
|
|
38
|
+
)
|
|
39
|
+
)
|
|
24
40
|
}
|
|
25
|
-
} else
|
|
26
|
-
console.log(i18n.__('
|
|
41
|
+
} else {
|
|
42
|
+
console.log(i18n.__('auditBadFiletypeSpecifiedForSave'))
|
|
27
43
|
}
|
|
28
44
|
}
|
|
29
45
|
|
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
import paramHandler from '../../utils/paramsUtil/paramHandler'
|
|
2
2
|
import constants from '../../constants'
|
|
3
3
|
import cliOptions from '../../utils/parsedCLIOptions'
|
|
4
|
-
import languageAnalysisEngine from '../../audit/languageAnalysisEngine/constants'
|
|
5
|
-
import {
|
|
6
|
-
determineProjectLanguage,
|
|
7
|
-
identifyLanguages
|
|
8
|
-
} from '../../audit/autodetection/autoDetectLanguage'
|
|
9
|
-
|
|
10
|
-
const {
|
|
11
|
-
supportedLanguages: { NODE, JAVASCRIPT }
|
|
12
|
-
} = languageAnalysisEngine
|
|
13
4
|
|
|
14
5
|
export const getAuditConfig = (argv: string[]): { [key: string]: string } => {
|
|
15
6
|
const auditParameters = cliOptions.getCommandLineArgsCustom(
|
|
@@ -18,22 +9,6 @@ export const getAuditConfig = (argv: string[]): { [key: string]: string } => {
|
|
|
18
9
|
)
|
|
19
10
|
const paramsAuth = paramHandler.getAuth(auditParameters)
|
|
20
11
|
|
|
21
|
-
if (
|
|
22
|
-
auditParameters.language === undefined ||
|
|
23
|
-
auditParameters.language === null
|
|
24
|
-
) {
|
|
25
|
-
try {
|
|
26
|
-
auditParameters.language = determineProjectLanguage(
|
|
27
|
-
identifyLanguages(auditParameters)
|
|
28
|
-
)
|
|
29
|
-
} catch (err: any) {
|
|
30
|
-
console.log(err.message)
|
|
31
|
-
process.exit(1)
|
|
32
|
-
}
|
|
33
|
-
} else if (auditParameters.language.toUpperCase() === JAVASCRIPT) {
|
|
34
|
-
auditParameters.language = NODE.toLowerCase()
|
|
35
|
-
}
|
|
36
|
-
|
|
37
12
|
// @ts-ignore
|
|
38
13
|
return { ...paramsAuth, ...auditParameters }
|
|
39
14
|
}
|