@contrast/contrast 1.0.5 → 1.0.8
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/.prettierignore +0 -5
- package/dist/audit/autodetection/autoDetectLanguage.js +3 -3
- package/dist/audit/catalogueApplication/catalogueApplication.js +23 -5
- package/dist/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +4 -2
- package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +2 -1
- package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +2 -1
- package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +2 -1
- package/dist/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +5 -5
- package/dist/audit/languageAnalysisEngine/getProjectRootFilenames.js +9 -9
- package/dist/audit/languageAnalysisEngine/index.js +2 -2
- package/dist/audit/languageAnalysisEngine/languageAnalysisFactory.js +6 -27
- package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +25 -5
- package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +99 -20
- package/dist/audit/languageAnalysisEngine/report/models/reportListModel.js +2 -1
- package/dist/audit/languageAnalysisEngine/report/models/reportOutputModel.js +24 -0
- package/dist/audit/languageAnalysisEngine/report/models/reportSeverityModel.js +3 -1
- package/dist/audit/languageAnalysisEngine/report/models/severityCountModel.js +16 -0
- package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +35 -14
- package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +58 -47
- package/dist/audit/languageAnalysisEngine/sendSnapshot.js +65 -3
- package/dist/audit/save.js +29 -0
- package/dist/commands/audit/auditController.js +22 -6
- package/dist/commands/audit/help.js +24 -1
- package/dist/commands/audit/processAudit.js +8 -2
- package/dist/commands/audit/saveFile.js +7 -3
- package/dist/commands/scan/processScan.js +1 -1
- package/dist/commands/scan/sca/scaAnalysis.js +48 -11
- package/dist/common/HTTPClient.js +56 -15
- package/dist/common/errorHandling.js +6 -1
- package/dist/common/versionChecker.js +20 -5
- package/dist/constants/constants.js +13 -3
- package/dist/constants/locales.js +15 -12
- package/dist/constants.js +9 -4
- package/dist/index.js +4 -3
- package/dist/lambda/analytics.js +11 -0
- package/dist/lambda/lambda.js +35 -4
- package/dist/lambda/types.js +13 -0
- package/dist/sbom/generateSbom.js +4 -3
- package/dist/scaAnalysis/common/formatMessage.js +46 -1
- package/dist/scaAnalysis/common/treeUpload.js +1 -3
- package/dist/scaAnalysis/go/goAnalysis.js +17 -0
- package/dist/scaAnalysis/go/goParseDeps.js +158 -0
- package/dist/scaAnalysis/go/goReadDepFile.js +21 -0
- package/dist/scaAnalysis/java/analysis.js +11 -22
- package/dist/scaAnalysis/java/index.js +6 -6
- package/dist/scaAnalysis/java/javaBuildDepsParser.js +14 -1
- package/dist/scaAnalysis/javascript/analysis.js +110 -0
- package/dist/scaAnalysis/javascript/index.js +41 -0
- package/dist/scaAnalysis/php/analysis.js +89 -0
- package/dist/scaAnalysis/php/index.js +10 -0
- package/dist/scaAnalysis/python/analysis.js +42 -0
- package/dist/scaAnalysis/python/index.js +10 -0
- package/dist/scaAnalysis/ruby/analysis.js +226 -0
- package/dist/scaAnalysis/ruby/index.js +10 -0
- package/dist/scan/autoDetection.js +8 -4
- package/dist/scan/fileUtils.js +26 -8
- package/dist/scan/formatScanOutput.js +18 -17
- package/dist/scan/models/groupedResultsModel.js +1 -1
- package/dist/scan/models/scanResultsModel.js +3 -1
- package/dist/scan/populateProjectIdAndProjectName.js +2 -1
- package/dist/scan/scan.js +5 -3
- package/dist/scan/scanConfig.js +6 -1
- package/dist/scan/scanController.js +26 -6
- package/dist/scan/scanResults.js +20 -6
- package/dist/utils/commonApi.js +4 -1
- package/dist/utils/filterProjectPath.js +7 -2
- package/dist/utils/oraWrapper.js +5 -1
- package/package.json +13 -9
- package/src/audit/autodetection/autoDetectLanguage.ts +3 -3
- package/src/audit/catalogueApplication/catalogueApplication.js +28 -7
- package/src/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +11 -8
- package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +2 -1
- package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +2 -1
- package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +2 -1
- package/src/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +5 -5
- package/src/audit/languageAnalysisEngine/getProjectRootFilenames.js +11 -11
- package/src/audit/languageAnalysisEngine/index.js +2 -2
- package/src/audit/languageAnalysisEngine/languageAnalysisFactory.js +11 -31
- package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +35 -32
- package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +179 -25
- package/src/audit/languageAnalysisEngine/report/models/reportLibraryModel.ts +3 -3
- package/src/audit/languageAnalysisEngine/report/models/reportListModel.ts +18 -11
- package/src/audit/languageAnalysisEngine/report/models/reportOutputModel.ts +29 -0
- package/src/audit/languageAnalysisEngine/report/models/reportSeverityModel.ts +12 -3
- package/src/audit/languageAnalysisEngine/report/models/severityCountModel.ts +20 -0
- package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +50 -18
- package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +88 -66
- package/src/audit/languageAnalysisEngine/sendSnapshot.js +78 -3
- package/src/audit/save.js +32 -0
- package/src/commands/audit/auditController.ts +23 -15
- package/src/commands/audit/help.ts +24 -1
- package/src/commands/audit/processAudit.ts +7 -4
- package/src/commands/audit/saveFile.ts +5 -1
- package/src/commands/scan/processScan.js +2 -1
- package/src/commands/scan/sca/scaAnalysis.js +70 -29
- package/src/common/HTTPClient.js +72 -25
- package/src/common/errorHandling.ts +10 -1
- package/src/common/versionChecker.ts +24 -5
- package/src/constants/constants.js +13 -3
- package/src/constants/locales.js +15 -12
- package/src/constants.js +9 -4
- package/src/index.ts +5 -3
- package/src/lambda/analytics.ts +9 -0
- package/src/lambda/arn.ts +2 -1
- package/src/lambda/lambda.ts +37 -17
- package/src/lambda/types.ts +35 -0
- package/src/lambda/utils.ts +2 -7
- package/src/sbom/generateSbom.ts +1 -1
- package/src/scaAnalysis/common/formatMessage.js +51 -1
- package/src/scaAnalysis/common/treeUpload.js +1 -6
- package/src/scaAnalysis/go/goAnalysis.js +19 -0
- package/src/scaAnalysis/go/goParseDeps.js +203 -0
- package/src/scaAnalysis/go/goReadDepFile.js +30 -0
- package/src/scaAnalysis/java/analysis.js +15 -32
- package/src/scaAnalysis/java/index.js +6 -6
- package/src/scaAnalysis/java/javaBuildDepsParser.js +15 -2
- package/src/scaAnalysis/javascript/analysis.js +127 -0
- package/src/scaAnalysis/javascript/index.js +56 -0
- package/src/scaAnalysis/php/analysis.js +98 -0
- package/src/scaAnalysis/php/index.js +11 -0
- package/src/scaAnalysis/python/analysis.js +49 -0
- package/src/scaAnalysis/python/index.js +11 -0
- package/src/scaAnalysis/ruby/analysis.js +282 -0
- package/src/scaAnalysis/ruby/index.js +11 -0
- package/src/scan/autoDetection.js +11 -7
- package/src/scan/fileUtils.js +27 -8
- package/src/scan/formatScanOutput.ts +26 -18
- package/src/scan/models/groupedResultsModel.ts +3 -3
- package/src/scan/models/resultContentModel.ts +1 -1
- package/src/scan/models/scanResultsModel.ts +5 -2
- package/src/scan/populateProjectIdAndProjectName.js +3 -1
- package/src/scan/scan.ts +8 -6
- package/src/scan/scanConfig.js +5 -1
- package/src/scan/scanController.js +30 -9
- package/src/scan/scanResults.js +31 -10
- package/src/utils/commonApi.js +4 -1
- package/src/utils/filterProjectPath.js +6 -2
- package/src/utils/oraWrapper.js +6 -1
|
@@ -29,4 +29,5 @@ const checkIdentifiedLanguageHasProjectFile = identifiedLanguages => {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
//For testing purposes
|
|
32
|
-
exports.checkIdentifiedLanguageHasProjectFile =
|
|
32
|
+
exports.checkIdentifiedLanguageHasProjectFile =
|
|
33
|
+
checkIdentifiedLanguageHasProjectFile
|
|
@@ -5,15 +5,15 @@ const path = require('path')
|
|
|
5
5
|
* language, project file name and paths
|
|
6
6
|
*/
|
|
7
7
|
module.exports = exports = (analysis, next) => {
|
|
8
|
-
const {
|
|
8
|
+
const { file, languageAnalysis } = analysis
|
|
9
9
|
languageAnalysis.identifiedLanguageInfo = getIdentifiedLanguageInfo(
|
|
10
|
-
|
|
10
|
+
file,
|
|
11
11
|
languageAnalysis.identifiedLanguages
|
|
12
12
|
)
|
|
13
13
|
next()
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
const getIdentifiedLanguageInfo = (
|
|
16
|
+
const getIdentifiedLanguageInfo = (file, identifiedLanguages) => {
|
|
17
17
|
const [language] = Object.keys(identifiedLanguages)
|
|
18
18
|
const {
|
|
19
19
|
projectFilenames: [projectFilename],
|
|
@@ -23,14 +23,14 @@ const getIdentifiedLanguageInfo = (projectPath, identifiedLanguages) => {
|
|
|
23
23
|
let identifiedLanguageInfo = {
|
|
24
24
|
language,
|
|
25
25
|
projectFilename,
|
|
26
|
-
projectFilePath: path.join(
|
|
26
|
+
projectFilePath: path.join(file, projectFilename)
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
if (lockFilename) {
|
|
30
30
|
identifiedLanguageInfo = {
|
|
31
31
|
...identifiedLanguageInfo,
|
|
32
32
|
lockFilename,
|
|
33
|
-
lockFilePath: path.join(
|
|
33
|
+
lockFilePath: path.join(file, lockFilename)
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
|
|
@@ -9,21 +9,21 @@ const i18n = require('i18n')
|
|
|
9
9
|
* Will fail and throw for a manner of reasons when doing file/directory
|
|
10
10
|
* inspection.
|
|
11
11
|
*
|
|
12
|
-
* @param {string}
|
|
12
|
+
* @param {string} file - The path to a projects root directory or a
|
|
13
13
|
* specific project file
|
|
14
14
|
*
|
|
15
15
|
* @return {string[]} List of filenames associated with a projects root
|
|
16
16
|
* directory or the name of the specific project file if that was provided to
|
|
17
|
-
* the '
|
|
17
|
+
* the 'file' parameter
|
|
18
18
|
*
|
|
19
19
|
* @throws {Error} If the project path doesn't exist
|
|
20
20
|
* @throws {Error} If the project path information can't be collected
|
|
21
21
|
* @throws {Error} If a non-file or non-directory inspected
|
|
22
22
|
*/
|
|
23
23
|
module.exports = exports = (analysis, next) => {
|
|
24
|
-
const {
|
|
24
|
+
const { file, languageAnalysis } = analysis
|
|
25
25
|
try {
|
|
26
|
-
languageAnalysis.projectRootFilenames = getProjectRootFilenames(
|
|
26
|
+
languageAnalysis.projectRootFilenames = getProjectRootFilenames(file)
|
|
27
27
|
} catch (err) {
|
|
28
28
|
next(err)
|
|
29
29
|
return
|
|
@@ -31,13 +31,13 @@ module.exports = exports = (analysis, next) => {
|
|
|
31
31
|
next()
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
const getProjectRootFilenames =
|
|
34
|
+
const getProjectRootFilenames = file => {
|
|
35
35
|
let projectStats = null
|
|
36
36
|
try {
|
|
37
|
-
projectStats = fs.statSync(
|
|
37
|
+
projectStats = fs.statSync(file)
|
|
38
38
|
} catch (err) {
|
|
39
39
|
throw new Error(
|
|
40
|
-
i18n.__('languageAnalysisProjectRootFileNameFailure',
|
|
40
|
+
i18n.__('languageAnalysisProjectRootFileNameFailure', file) +
|
|
41
41
|
`${err.message}`
|
|
42
42
|
)
|
|
43
43
|
}
|
|
@@ -45,10 +45,10 @@ const getProjectRootFilenames = projectPath => {
|
|
|
45
45
|
// Return the contents of a directory...
|
|
46
46
|
if (projectStats.isDirectory()) {
|
|
47
47
|
try {
|
|
48
|
-
return fs.readdirSync(
|
|
48
|
+
return fs.readdirSync(file)
|
|
49
49
|
} catch (err) {
|
|
50
50
|
throw new Error(
|
|
51
|
-
i18n.__('languageAnalysisProjectRootFileNameReadError',
|
|
51
|
+
i18n.__('languageAnalysisProjectRootFileNameReadError', file) +
|
|
52
52
|
`${err.message}`
|
|
53
53
|
)
|
|
54
54
|
}
|
|
@@ -57,14 +57,14 @@ const getProjectRootFilenames = projectPath => {
|
|
|
57
57
|
// If we are working with a file return it in a list as we do when we work
|
|
58
58
|
// with a directory...
|
|
59
59
|
if (projectStats.isFile()) {
|
|
60
|
-
return [path.basename(
|
|
60
|
+
return [path.basename(file)]
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
// Error out if we are working with something like a socket file or some
|
|
64
64
|
// other craziness...
|
|
65
65
|
throw new Error(
|
|
66
66
|
i18n.__('languageAnalysisProjectRootFileNameMissingError'),
|
|
67
|
-
|
|
67
|
+
file
|
|
68
68
|
)
|
|
69
69
|
}
|
|
70
70
|
|
|
@@ -10,10 +10,10 @@ const checkIdentifiedLanguageHasLockFile = require('./checkIdentifiedLanguageHas
|
|
|
10
10
|
const getIdentifiedLanguageInfo = require('./getIdentifiedLanguageInfo')
|
|
11
11
|
const { libraryAnalysisError } = require('../../common/errorHandling')
|
|
12
12
|
|
|
13
|
-
module.exports = exports = (
|
|
13
|
+
module.exports = exports = (file, callback, appId, config) => {
|
|
14
14
|
// Create an analysis engine to identify the project language
|
|
15
15
|
const ae = new AnalysisEngine({
|
|
16
|
-
|
|
16
|
+
file,
|
|
17
17
|
appId,
|
|
18
18
|
languageAnalysis: { appId: appId },
|
|
19
19
|
config
|
|
@@ -11,16 +11,13 @@ const phpAE = require('../phpAnalysisEngine')
|
|
|
11
11
|
const goAE = require('../goAnalysisEngine')
|
|
12
12
|
const { vulnerabilityReport } = require('./report/reportingFeature')
|
|
13
13
|
const { newSendSnapShot } = require('../languageAnalysisEngine/sendSnapshot')
|
|
14
|
-
const fs = require('fs')
|
|
15
|
-
const chalk = require('chalk')
|
|
16
|
-
const saveFile = require('../../commands/audit/saveFile').default
|
|
17
|
-
const generateSbom = require('../../sbom/generateSbom').default
|
|
18
14
|
const {
|
|
19
|
-
failSpinner,
|
|
20
15
|
returnOra,
|
|
21
16
|
startSpinner,
|
|
22
17
|
succeedSpinner
|
|
23
18
|
} = require('../../utils/oraWrapper')
|
|
19
|
+
const { pollForSnapshotCompletition } = require('./sendSnapshot')
|
|
20
|
+
const auditSave = require('../save')
|
|
24
21
|
|
|
25
22
|
module.exports = exports = (err, analysis) => {
|
|
26
23
|
const { identifiedLanguageInfo } = analysis.languageAnalysis
|
|
@@ -54,12 +51,19 @@ module.exports = exports = (err, analysis) => {
|
|
|
54
51
|
const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'))
|
|
55
52
|
startSpinner(reportSpinner)
|
|
56
53
|
const snapshotResponse = await newSendSnapShot(analysis, catalogueAppId)
|
|
57
|
-
|
|
54
|
+
|
|
55
|
+
//poll for completion
|
|
56
|
+
await pollForSnapshotCompletition(
|
|
57
|
+
analysis.config,
|
|
58
|
+
snapshotResponse.id,
|
|
59
|
+
reportSpinner
|
|
60
|
+
)
|
|
61
|
+
succeedSpinner(reportSpinner, i18n.__('auditSCAAnalysisComplete'))
|
|
58
62
|
|
|
59
63
|
await vulnerabilityReport(analysis, catalogueAppId, snapshotResponse.id)
|
|
60
64
|
|
|
61
65
|
//should be moved to processAudit.ts once promises implemented
|
|
62
|
-
await auditSave(config)
|
|
66
|
+
await auditSave.auditSave(config)
|
|
63
67
|
}
|
|
64
68
|
|
|
65
69
|
if (identifiedLanguageInfo.language === DOTNET) {
|
|
@@ -90,27 +94,3 @@ module.exports = exports = (err, analysis) => {
|
|
|
90
94
|
goAE(identifiedLanguageInfo, analysis.config, langCallback)
|
|
91
95
|
}
|
|
92
96
|
}
|
|
93
|
-
|
|
94
|
-
async function auditSave(config) {
|
|
95
|
-
//should be moved to processAudit.ts once promises implemented
|
|
96
|
-
if (config.save) {
|
|
97
|
-
if (config.save.toLowerCase() === 'sbom') {
|
|
98
|
-
saveFile(config, await generateSbom(config))
|
|
99
|
-
|
|
100
|
-
const filename = `${config.applicationId}-sbom-cyclonedx.json`
|
|
101
|
-
if (fs.existsSync(filename)) {
|
|
102
|
-
console.log(i18n.__('auditSBOMSaveSuccess') + ` - ${filename}`)
|
|
103
|
-
} else {
|
|
104
|
-
console.log(
|
|
105
|
-
chalk.yellow.bold(
|
|
106
|
-
`\n Unable to save ${filename} Software Bill of Materials (SBOM)`
|
|
107
|
-
)
|
|
108
|
-
)
|
|
109
|
-
}
|
|
110
|
-
} else {
|
|
111
|
-
console.log(i18n.__('auditBadFiletypeSpecifiedForSave'))
|
|
112
|
-
}
|
|
113
|
-
} else if (config.save === null) {
|
|
114
|
-
console.log(i18n.__('auditNoFiletypeSpecifiedForSave'))
|
|
115
|
-
}
|
|
116
|
-
}
|
|
@@ -46,35 +46,38 @@ const deduceLanguageScaAnalysis = filenames => {
|
|
|
46
46
|
|
|
47
47
|
if (isNodeProjectFilename(filename)) {
|
|
48
48
|
deducedLanguages.push(filename)
|
|
49
|
-
language =
|
|
49
|
+
language = JAVASCRIPT
|
|
50
50
|
}
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
// if (isDotNetProjectFilename(filename)) {
|
|
53
53
|
// deducedLanguages.push({language: DOTNET, projectFilename: filename})
|
|
54
54
|
// }
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
55
|
+
|
|
56
|
+
if (isRubyProjectFilename(filename)) {
|
|
57
|
+
deducedLanguages.push(filename)
|
|
58
|
+
language = RUBY
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (isPythonProjectFilename(filename)) {
|
|
62
|
+
deducedLanguages.push(filename)
|
|
63
|
+
language = PYTHON
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (isPhpProjectFilename(filename)) {
|
|
67
|
+
deducedLanguages.push({ language: PHP, projectFilename: filename })
|
|
68
|
+
language = PHP
|
|
69
|
+
}
|
|
70
|
+
|
|
68
71
|
// // Check for lock filenames...
|
|
69
72
|
// if (isDotNetLockFilename(filename)) {
|
|
70
73
|
// deducedLanguages.push({language: DOTNET, lockFilename: filename})
|
|
71
74
|
// }
|
|
72
|
-
|
|
75
|
+
|
|
73
76
|
if (isNodeLockFilename(filename)) {
|
|
74
77
|
deducedLanguages.push(filename)
|
|
75
|
-
language =
|
|
78
|
+
language = JAVASCRIPT
|
|
76
79
|
}
|
|
77
|
-
|
|
80
|
+
|
|
78
81
|
// if (isRubyLockFilename(filename)) {
|
|
79
82
|
// deducedLanguages.push({language: RUBY, lockFilename: filename})
|
|
80
83
|
// }
|
|
@@ -83,15 +86,16 @@ const deduceLanguageScaAnalysis = filenames => {
|
|
|
83
86
|
// if (isPipfileLockLockFilename(filename)) {
|
|
84
87
|
// deducedLanguages.push({language: PYTHON, lockFilename: filename})
|
|
85
88
|
// }
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
//
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
89
|
+
|
|
90
|
+
if (isPhpLockFilename(filename)) {
|
|
91
|
+
deducedLanguages.push({ language: PHP, lockFilename: filename })
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// go does not have a lockfile, it should have a go.mod file containing the modules
|
|
95
|
+
if (isGoProjectFilename(filename)) {
|
|
96
|
+
deducedLanguages.push({ language: GO, projectFilename: filename })
|
|
97
|
+
language = GO
|
|
98
|
+
}
|
|
95
99
|
})
|
|
96
100
|
let identifiedLanguages = { [language]: deducedLanguages }
|
|
97
101
|
|
|
@@ -189,7 +193,7 @@ const reduceIdentifiedLanguages = identifiedLanguages =>
|
|
|
189
193
|
* specifies a specific language
|
|
190
194
|
*/
|
|
191
195
|
module.exports = exports = (analysis, next) => {
|
|
192
|
-
const {
|
|
196
|
+
const { file, languageAnalysis, config } = analysis
|
|
193
197
|
|
|
194
198
|
let identifiedLanguages = languageAnalysis.projectRootFilenames.reduce(
|
|
195
199
|
(accumulator, filename) => {
|
|
@@ -200,15 +204,14 @@ module.exports = exports = (analysis, next) => {
|
|
|
200
204
|
)
|
|
201
205
|
|
|
202
206
|
if (Object.keys(identifiedLanguages).length === 0) {
|
|
203
|
-
next(new Error(i18n.__('languageAnalysisNoLanguage',
|
|
207
|
+
next(new Error(i18n.__('languageAnalysisNoLanguage', file)))
|
|
204
208
|
return
|
|
205
209
|
}
|
|
206
210
|
|
|
207
211
|
let language = config.language
|
|
208
212
|
if (language === undefined) {
|
|
209
|
-
languageAnalysis.identifiedLanguages =
|
|
210
|
-
identifiedLanguages
|
|
211
|
-
)
|
|
213
|
+
languageAnalysis.identifiedLanguages =
|
|
214
|
+
reduceIdentifiedLanguages(identifiedLanguages)
|
|
212
215
|
} else {
|
|
213
216
|
let refinedIdentifiedLanguages = []
|
|
214
217
|
for (let x in identifiedLanguages) {
|
|
@@ -7,8 +7,27 @@ import {
|
|
|
7
7
|
import { ReportSeverityModel } from './models/reportSeverityModel'
|
|
8
8
|
import { orderBy } from 'lodash'
|
|
9
9
|
import chalk from 'chalk'
|
|
10
|
-
import { ReportLibraryModel } from './models/reportLibraryModel'
|
|
11
|
-
import {
|
|
10
|
+
import { ReportCVEModel, ReportLibraryModel } from './models/reportLibraryModel'
|
|
11
|
+
import {
|
|
12
|
+
findCVESeveritiesAndOrderByHighestPriority,
|
|
13
|
+
findHighestSeverityCVE,
|
|
14
|
+
findNameAndVersion,
|
|
15
|
+
severityCountAllCVEs,
|
|
16
|
+
severityCountAllLibraries
|
|
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
|
+
CRITICAL_COLOUR,
|
|
26
|
+
HIGH_COLOUR,
|
|
27
|
+
LOW_COLOUR,
|
|
28
|
+
MEDIUM_COLOUR,
|
|
29
|
+
NOTE_COLOUR
|
|
30
|
+
} from '../../../constants/constants'
|
|
12
31
|
|
|
13
32
|
export const createLibraryHeader = (
|
|
14
33
|
id: string,
|
|
@@ -16,11 +35,9 @@ export const createLibraryHeader = (
|
|
|
16
35
|
numberOfCves: number
|
|
17
36
|
) => {
|
|
18
37
|
numberOfVulnerableLibraries === 1
|
|
19
|
-
? console.log(
|
|
20
|
-
` Found 1 vulnerable library containing ${numberOfCves} CVE's`
|
|
21
|
-
)
|
|
38
|
+
? console.log(`Found 1 vulnerable library containing ${numberOfCves} CVEs`)
|
|
22
39
|
: console.log(
|
|
23
|
-
`
|
|
40
|
+
`Found ${numberOfVulnerableLibraries} vulnerable libraries containing ${numberOfCves} CVEs `
|
|
24
41
|
)
|
|
25
42
|
}
|
|
26
43
|
|
|
@@ -32,10 +49,6 @@ export const getReport = async (config: any, reportId: string) => {
|
|
|
32
49
|
if (res.statusCode === 200) {
|
|
33
50
|
return res.body
|
|
34
51
|
} else {
|
|
35
|
-
console.log('config-------------------')
|
|
36
|
-
console.log(config)
|
|
37
|
-
console.log('reportId----------------')
|
|
38
|
-
console.log(reportId)
|
|
39
52
|
console.log(JSON.stringify(res))
|
|
40
53
|
handleResponseErrors(res, 'report')
|
|
41
54
|
}
|
|
@@ -70,7 +83,11 @@ export const printFormattedOutput = (
|
|
|
70
83
|
new ReportCompositeKey(
|
|
71
84
|
name,
|
|
72
85
|
version,
|
|
73
|
-
findHighestSeverityCVE(library.cveArray) as ReportSeverityModel
|
|
86
|
+
findHighestSeverityCVE(library.cveArray) as ReportSeverityModel,
|
|
87
|
+
severityCountAllCVEs(
|
|
88
|
+
library.cveArray,
|
|
89
|
+
new SeverityCountModel()
|
|
90
|
+
).getTotal
|
|
74
91
|
),
|
|
75
92
|
library.cveArray
|
|
76
93
|
)
|
|
@@ -78,28 +95,165 @@ export const printFormattedOutput = (
|
|
|
78
95
|
report.reportOutputList.push(newOutputModel)
|
|
79
96
|
}
|
|
80
97
|
|
|
81
|
-
const
|
|
98
|
+
const outputOrderedByLowestSeverityAndLowestNumOfCvesFirst = orderBy(
|
|
82
99
|
report.reportOutputList,
|
|
83
|
-
|
|
100
|
+
[
|
|
101
|
+
(reportListItem: ReportModelStructure) => {
|
|
102
|
+
return reportListItem.compositeKey.highestSeverity.priority
|
|
103
|
+
},
|
|
104
|
+
(reportListItem: ReportModelStructure) => {
|
|
105
|
+
return reportListItem.compositeKey.numberOfSeverities
|
|
106
|
+
}
|
|
107
|
+
],
|
|
108
|
+
['desc']
|
|
84
109
|
)
|
|
85
110
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
111
|
+
let contrastHeaderNumCounter =
|
|
112
|
+
outputOrderedByLowestSeverityAndLowestNumOfCvesFirst.length + 1
|
|
113
|
+
for (const reportModel of outputOrderedByLowestSeverityAndLowestNumOfCvesFirst) {
|
|
114
|
+
contrastHeaderNumCounter--
|
|
115
|
+
const { libraryName, libraryVersion, highestSeverity } =
|
|
116
|
+
reportModel.compositeKey
|
|
91
117
|
const numOfCVEs = reportModel.cveArray.length
|
|
92
118
|
|
|
93
|
-
const
|
|
119
|
+
const header = buildHeader(
|
|
120
|
+
highestSeverity,
|
|
121
|
+
contrastHeaderNumCounter,
|
|
122
|
+
libraryName,
|
|
123
|
+
libraryVersion,
|
|
124
|
+
numOfCVEs
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
const body = buildBody(reportModel.cveArray)
|
|
128
|
+
|
|
129
|
+
const reportOutputModel = new ReportOutputModel(header, body)
|
|
130
|
+
console.log(
|
|
131
|
+
reportOutputModel.header.vulnMessage,
|
|
132
|
+
reportOutputModel.header.introducesMessage
|
|
133
|
+
)
|
|
134
|
+
console.log(reportOutputModel.body.issueMessage)
|
|
135
|
+
console.log(reportOutputModel.body.adviceMessage + '\n')
|
|
136
|
+
}
|
|
94
137
|
|
|
95
|
-
|
|
138
|
+
const {
|
|
139
|
+
criticalMessage,
|
|
140
|
+
highMessage,
|
|
141
|
+
mediumMessage,
|
|
142
|
+
lowMessage,
|
|
143
|
+
noteMessage,
|
|
144
|
+
total
|
|
145
|
+
} = buildFooter(libraries)
|
|
96
146
|
|
|
97
|
-
|
|
98
|
-
const cvePluralised = numOfCVEs > 1 ? 'CVEs' : 'CVE'
|
|
147
|
+
if (total > 1) {
|
|
99
148
|
console.log(
|
|
100
|
-
|
|
149
|
+
`${criticalMessage} | ${highMessage} | ${mediumMessage} | ${lowMessage} | ${noteMessage}`
|
|
101
150
|
)
|
|
102
|
-
console.log(` ${cveNames.join(', ')}`)
|
|
103
|
-
console.log(chalk.bold(' How to fix: Update to latest version'))
|
|
104
151
|
}
|
|
105
152
|
}
|
|
153
|
+
|
|
154
|
+
export function buildHeader(
|
|
155
|
+
highestSeverity: ReportSeverityModel,
|
|
156
|
+
contrastHeaderNum: number,
|
|
157
|
+
libraryName: string,
|
|
158
|
+
version: string,
|
|
159
|
+
numOfCVEs: number
|
|
160
|
+
) {
|
|
161
|
+
const vulnerabilityPluralised =
|
|
162
|
+
numOfCVEs > 1 ? 'vulnerabilities' : 'vulnerability'
|
|
163
|
+
const formattedHeaderNum = buildFormattedHeaderNum(contrastHeaderNum)
|
|
164
|
+
|
|
165
|
+
const vulnMessage = chalk
|
|
166
|
+
.hex(highestSeverity.outputColour)
|
|
167
|
+
.bold(
|
|
168
|
+
`${formattedHeaderNum} - [${highestSeverity.severity}] ${libraryName}-${version}`
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
const introducesMessage = chalk.bold(
|
|
172
|
+
`introduces ${numOfCVEs} ${vulnerabilityPluralised}`
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
return new ReportOutputHeaderModel(vulnMessage, introducesMessage)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export function buildBody(cveArray: ReportCVEModel[]) {
|
|
179
|
+
const cveMessages: string[] = []
|
|
180
|
+
|
|
181
|
+
findCVESeveritiesAndOrderByHighestPriority(cveArray).forEach(
|
|
182
|
+
reportSeverityModel => {
|
|
183
|
+
// @ts-ignore
|
|
184
|
+
const { outputColour, severity, cveName } = reportSeverityModel
|
|
185
|
+
|
|
186
|
+
const severityShorthand = chalk
|
|
187
|
+
.hex(outputColour)
|
|
188
|
+
.bold(`[${severity.charAt(0).toUpperCase()}]`)
|
|
189
|
+
|
|
190
|
+
const builtMessage = `${severityShorthand} ${cveName}`
|
|
191
|
+
cveMessages.push(builtMessage)
|
|
192
|
+
}
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
const numAndSeverityType = getNumOfAndSeverityType(cveArray)
|
|
196
|
+
|
|
197
|
+
const issueMessage = ` ${chalk.bold(
|
|
198
|
+
'Issue'
|
|
199
|
+
)} : ${numAndSeverityType} ${cveMessages.join(', ')}.`
|
|
200
|
+
|
|
201
|
+
const adviceMessage = ` ${chalk.bold('Advice')} : ${chalk.bold(
|
|
202
|
+
'Update to latest version'
|
|
203
|
+
)}.`
|
|
204
|
+
|
|
205
|
+
return new ReportOutputBodyModel(issueMessage, adviceMessage)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const buildFooter = (libraries: ReportLibraryModel[]) => {
|
|
209
|
+
const { critical, high, medium, low, note, getTotal } =
|
|
210
|
+
severityCountAllLibraries(libraries)
|
|
211
|
+
const criticalMessage = chalk
|
|
212
|
+
.hex(CRITICAL_COLOUR)
|
|
213
|
+
.bold(`${critical} Critical`)
|
|
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`)
|
|
218
|
+
|
|
219
|
+
return {
|
|
220
|
+
criticalMessage,
|
|
221
|
+
highMessage,
|
|
222
|
+
mediumMessage,
|
|
223
|
+
lowMessage,
|
|
224
|
+
noteMessage,
|
|
225
|
+
total: getTotal
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function buildFormattedHeaderNum(contrastHeaderNum: number) {
|
|
230
|
+
let formattedHeaderNum
|
|
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}`
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export function getNumOfAndSeverityType(cveArray: ReportCVEModel[]) {
|
|
244
|
+
const { critical, high, medium, low, note } = severityCountAllCVEs(
|
|
245
|
+
cveArray,
|
|
246
|
+
new SeverityCountModel()
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
const criticalMessage = critical > 0 ? `${critical} Critical` : ''
|
|
250
|
+
const highMessage = high > 0 ? `${high} High` : ''
|
|
251
|
+
const mediumMessage = medium > 0 ? `${medium} Medium` : ''
|
|
252
|
+
const lowMessage = low > 0 ? `${low} Low` : ''
|
|
253
|
+
const noteMessage = note > 0 ? `${note} Note` : ''
|
|
254
|
+
|
|
255
|
+
//removes/trims whitespace to single spaces
|
|
256
|
+
return `${criticalMessage} ${highMessage} ${mediumMessage} ${lowMessage} ${noteMessage}`
|
|
257
|
+
.replace(/\s+/g, ' ')
|
|
258
|
+
.trim()
|
|
259
|
+
}
|
|
@@ -2,7 +2,7 @@ export class ReportLibraryModel {
|
|
|
2
2
|
name: string
|
|
3
3
|
cveArray: ReportCVEModel[]
|
|
4
4
|
|
|
5
|
-
constructor
|
|
5
|
+
constructor(name: string, cveArray: ReportCVEModel[]) {
|
|
6
6
|
this.name = name
|
|
7
7
|
this.cveArray = cveArray
|
|
8
8
|
}
|
|
@@ -16,12 +16,12 @@ export class ReportCVEModel {
|
|
|
16
16
|
severityCode?: string
|
|
17
17
|
cvss3SeverityCode?: string
|
|
18
18
|
|
|
19
|
-
constructor
|
|
19
|
+
constructor(
|
|
20
20
|
name: string,
|
|
21
21
|
description: string,
|
|
22
22
|
severityCode: string,
|
|
23
23
|
cvss3SeverityCode: string
|
|
24
|
-
){
|
|
24
|
+
) {
|
|
25
25
|
this.name = name
|
|
26
26
|
this.description = description
|
|
27
27
|
this.severityCode = severityCode
|
|
@@ -1,32 +1,39 @@
|
|
|
1
|
-
import {ReportSeverityModel} from
|
|
2
|
-
import {ReportCVEModel} from
|
|
1
|
+
import { ReportSeverityModel } from './reportSeverityModel'
|
|
2
|
+
import { ReportCVEModel } from './reportLibraryModel'
|
|
3
3
|
|
|
4
4
|
export class ReportList {
|
|
5
5
|
reportOutputList: ReportModelStructure[]
|
|
6
6
|
|
|
7
|
-
constructor
|
|
7
|
+
constructor() {
|
|
8
8
|
this.reportOutputList = []
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export class ReportModelStructure {
|
|
13
|
-
compositeKey: ReportCompositeKey
|
|
14
|
-
cveArray: ReportCVEModel[]
|
|
13
|
+
compositeKey: ReportCompositeKey
|
|
14
|
+
cveArray: ReportCVEModel[]
|
|
15
15
|
|
|
16
|
-
constructor
|
|
16
|
+
constructor(compositeKey: ReportCompositeKey, cveArray: ReportCVEModel[]) {
|
|
17
17
|
this.compositeKey = compositeKey
|
|
18
18
|
this.cveArray = cveArray
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export class ReportCompositeKey {
|
|
23
|
-
libraryName!: string
|
|
24
|
-
libraryVersion!: string
|
|
25
|
-
highestSeverity!: ReportSeverityModel
|
|
23
|
+
libraryName!: string
|
|
24
|
+
libraryVersion!: string
|
|
25
|
+
highestSeverity!: ReportSeverityModel
|
|
26
|
+
numberOfSeverities!: number
|
|
26
27
|
|
|
27
|
-
constructor
|
|
28
|
+
constructor(
|
|
29
|
+
libraryName: string,
|
|
30
|
+
libraryVersion: string,
|
|
31
|
+
highestSeverity: ReportSeverityModel,
|
|
32
|
+
numberOfSeverities: number
|
|
33
|
+
) {
|
|
28
34
|
this.libraryName = libraryName
|
|
29
35
|
this.libraryVersion = libraryVersion
|
|
30
36
|
this.highestSeverity = highestSeverity
|
|
37
|
+
this.numberOfSeverities = numberOfSeverities
|
|
31
38
|
}
|
|
32
|
-
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export class ReportOutputModel {
|
|
2
|
+
header: ReportOutputHeaderModel
|
|
3
|
+
body: ReportOutputBodyModel
|
|
4
|
+
|
|
5
|
+
constructor(header: ReportOutputHeaderModel, body: ReportOutputBodyModel) {
|
|
6
|
+
this.header = header
|
|
7
|
+
this.body = body
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class ReportOutputHeaderModel {
|
|
12
|
+
vulnMessage: string
|
|
13
|
+
introducesMessage: string
|
|
14
|
+
|
|
15
|
+
constructor(vulnMessage: string, introducesMessage: string) {
|
|
16
|
+
this.vulnMessage = vulnMessage
|
|
17
|
+
this.introducesMessage = introducesMessage
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export class ReportOutputBodyModel {
|
|
22
|
+
issueMessage: string
|
|
23
|
+
adviceMessage: string
|
|
24
|
+
|
|
25
|
+
constructor(bodyIssueMessage: string, bodyAdviceMessage: string) {
|
|
26
|
+
this.issueMessage = bodyIssueMessage
|
|
27
|
+
this.adviceMessage = bodyAdviceMessage
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
export class ReportSeverityModel {
|
|
2
|
-
severity
|
|
3
|
-
priority
|
|
2
|
+
severity: string
|
|
3
|
+
priority: number
|
|
4
|
+
outputColour: string
|
|
5
|
+
cveName: string
|
|
4
6
|
|
|
5
|
-
constructor(
|
|
7
|
+
constructor(
|
|
8
|
+
severity: string,
|
|
9
|
+
priority: number,
|
|
10
|
+
outputColour: string,
|
|
11
|
+
cveName: string
|
|
12
|
+
) {
|
|
6
13
|
this.severity = severity
|
|
7
14
|
this.priority = priority
|
|
15
|
+
this.outputColour = outputColour
|
|
16
|
+
this.cveName = cveName
|
|
8
17
|
}
|
|
9
18
|
}
|