@contrast/contrast 1.0.3 → 1.0.4
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 +1 -0
- package/README.md +20 -14
- package/dist/audit/languageAnalysisEngine/{langugageAnalysisFactory.js → languageAnalysisFactory.js} +2 -12
- package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +62 -234
- package/dist/audit/languageAnalysisEngine/report/models/reportLibraryModel.js +19 -0
- package/dist/audit/languageAnalysisEngine/report/models/reportListModel.js +24 -0
- package/dist/audit/languageAnalysisEngine/report/models/reportSeverityModel.js +10 -0
- package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +24 -129
- package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +85 -0
- package/dist/audit/languageAnalysisEngine/sendSnapshot.js +3 -1
- package/dist/commands/audit/auditController.js +6 -3
- package/dist/commands/scan/processScan.js +4 -3
- package/dist/common/HTTPClient.js +19 -26
- package/dist/common/versionChecker.js +14 -12
- package/dist/constants/constants.js +1 -1
- package/dist/constants/lambda.js +3 -1
- package/dist/constants/locales.js +17 -10
- package/dist/constants.js +5 -1
- package/dist/index.js +2 -2
- package/dist/lambda/help.js +22 -14
- package/dist/lambda/lambda.js +6 -0
- package/dist/scan/models/groupedResultsModel.js +10 -0
- package/dist/scan/models/resultContentModel.js +2 -0
- package/dist/scan/models/scanResultsModel.js +11 -0
- package/dist/scan/scan.js +90 -95
- package/dist/scan/scanConfig.js +1 -1
- package/dist/utils/getConfig.js +3 -0
- package/package.json +2 -2
- package/src/audit/languageAnalysisEngine/{langugageAnalysisFactory.js → languageAnalysisFactory.js} +2 -16
- package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +127 -0
- package/src/audit/languageAnalysisEngine/report/models/reportLibraryModel.ts +30 -0
- package/src/audit/languageAnalysisEngine/report/models/reportListModel.ts +32 -0
- package/src/audit/languageAnalysisEngine/report/models/reportSeverityModel.ts +9 -0
- package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +56 -0
- package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +110 -0
- package/src/audit/languageAnalysisEngine/sendSnapshot.js +3 -1
- package/src/commands/audit/auditController.ts +12 -3
- package/src/commands/scan/processScan.js +4 -6
- package/src/common/HTTPClient.js +31 -38
- package/src/common/errorHandling.ts +0 -1
- package/src/common/versionChecker.ts +24 -22
- package/src/constants/constants.js +1 -1
- package/src/constants/lambda.js +3 -1
- package/src/constants/locales.js +20 -10
- package/src/constants.js +7 -1
- package/src/index.ts +2 -3
- package/src/lambda/help.ts +22 -14
- package/src/lambda/lambda.ts +8 -0
- package/src/scan/models/groupedResultsModel.ts +18 -0
- package/src/scan/models/resultContentModel.ts +86 -0
- package/src/scan/models/scanResultsModel.ts +52 -0
- package/src/scan/scan.ts +192 -0
- package/src/scan/scanConfig.js +1 -1
- package/src/scan/scanController.js +2 -0
- package/src/utils/getConfig.ts +10 -0
- package/dist/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +0 -17
- package/dist/audit/languageAnalysisEngine/report/newReportingFeature.js +0 -81
- package/src/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +0 -27
- package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.js +0 -303
- package/src/audit/languageAnalysisEngine/report/newReportingFeature.js +0 -124
- package/src/audit/languageAnalysisEngine/report/reportingFeature.js +0 -190
- package/src/scan/scan.js +0 -195
package/.prettierignore
CHANGED
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ CodeSec delivers:
|
|
|
9
9
|
|
|
10
10
|
## Install
|
|
11
11
|
|
|
12
|
-
```
|
|
12
|
+
```shell
|
|
13
13
|
npm install -g @contrast/contrast
|
|
14
14
|
```
|
|
15
15
|
|
|
@@ -23,7 +23,8 @@ In the resulting browser window, log in and authenticate with your GitHub or Goo
|
|
|
23
23
|
|
|
24
24
|
### SAST scan
|
|
25
25
|
|
|
26
|
-
####Requirements
|
|
26
|
+
#### Scan Requirements
|
|
27
|
+
|
|
27
28
|
Make sure you have the correct file types to scan.
|
|
28
29
|
|
|
29
30
|
- Upload a .jar or .war file to scan a Java project for analysis
|
|
@@ -36,7 +37,7 @@ Use the Contrast scan command `contrast scan`
|
|
|
36
37
|
|
|
37
38
|
### Lambda function scan
|
|
38
39
|
|
|
39
|
-
####Requirements
|
|
40
|
+
#### Lambda Requirements
|
|
40
41
|
|
|
41
42
|
- Currently supports Java and Python functions on AWS.
|
|
42
43
|
Configure AWS credentials on your local environment by running the commands with your credentials:
|
|
@@ -85,19 +86,24 @@ Performs a security SAST scan.
|
|
|
85
86
|
|
|
86
87
|
**Options:**
|
|
87
88
|
|
|
88
|
-
- **contrast scan --file**
|
|
89
|
-
|
|
89
|
+
- **contrast scan --file**
|
|
90
|
+
|
|
91
|
+
- Path of the file you want to scan. Contrast searches for a .jar, .war, .js. or .zip file in the working directory if a file is not specified.
|
|
92
|
+
- Alias: **--f**
|
|
90
93
|
|
|
91
94
|
- **contrast scan --name**
|
|
92
|
-
|
|
93
|
-
|
|
95
|
+
|
|
96
|
+
- Contrast project name. If not specified, Contrast uses contrast.settings to identify the project or creates a project.
|
|
97
|
+
- Alias: **–n**
|
|
98
|
+
|
|
94
99
|
- **contrast scan --save**
|
|
95
|
-
|
|
96
|
-
|
|
100
|
+
|
|
101
|
+
- Download the results to a Static Analysis Results Interchange Format (SARIF) file. The file is downloaded to the current working directory with a default name of results.sarif. You can view the file with any text editor.
|
|
102
|
+
- Alias: **-s**
|
|
97
103
|
|
|
98
104
|
- **contrast scan --timeout**
|
|
99
|
-
Time in seconds to wait for the scan to complete. Default value is 300 seconds.
|
|
100
|
-
Alias: **-t**
|
|
105
|
+
- Time in seconds to wait for the scan to complete. Default value is 300 seconds.
|
|
106
|
+
- Alias: **-t**
|
|
101
107
|
|
|
102
108
|
### lambda
|
|
103
109
|
|
|
@@ -107,6 +113,9 @@ Name of AWS lambda function to scan.
|
|
|
107
113
|
|
|
108
114
|
**Options:**
|
|
109
115
|
|
|
116
|
+
- **contrast lambda --list-functions**
|
|
117
|
+
Lists all available lambda functions to scan.
|
|
118
|
+
|
|
110
119
|
- **contrast lambda --function-name --endpoint-url**
|
|
111
120
|
AWS Endpoint override. Similar to AWS CLI.
|
|
112
121
|
Alias: **-e**
|
|
@@ -127,9 +136,6 @@ Name of AWS lambda function to scan.
|
|
|
127
136
|
Returns extended information to the terminal.
|
|
128
137
|
Alias: **-v**
|
|
129
138
|
|
|
130
|
-
- **contrast lambda -–function-name --list-functions**
|
|
131
|
-
Lists all available lambda functions to scan.
|
|
132
|
-
|
|
133
139
|
- **contrast lambda --function-name -–help**
|
|
134
140
|
Displays usage guide.
|
|
135
141
|
Alias: **-h**
|
package/dist/audit/languageAnalysisEngine/{langugageAnalysisFactory.js → languageAnalysisFactory.js}
RENAMED
|
@@ -9,8 +9,6 @@ const pythonAE = require('../pythonAnalysisEngine');
|
|
|
9
9
|
const phpAE = require('../phpAnalysisEngine');
|
|
10
10
|
const goAE = require('../goAnalysisEngine');
|
|
11
11
|
const { vulnerabilityReport } = require('./report/reportingFeature');
|
|
12
|
-
const { vulnReportWithoutDevDep } = require('./report/newReportingFeature');
|
|
13
|
-
const { checkDevDeps } = require('./report/checkIgnoreDevDep');
|
|
14
12
|
const { newSendSnapShot } = require('../languageAnalysisEngine/sendSnapshot');
|
|
15
13
|
const fs = require('fs');
|
|
16
14
|
const chalk = require('chalk');
|
|
@@ -39,15 +37,7 @@ module.exports = exports = (err, analysis) => {
|
|
|
39
37
|
}
|
|
40
38
|
console.log('\n **************CONTRAST OSS ANALYSIS BEGINS**************');
|
|
41
39
|
const snapshotResponse = await newSendSnapShot(analysis, catalogueAppId);
|
|
42
|
-
|
|
43
|
-
const ignoreDevUrl = await checkDevDeps(config);
|
|
44
|
-
if (ignoreDevUrl) {
|
|
45
|
-
await vulnReportWithoutDevDep(analysis, catalogueAppId, snapshotResponse.id, config);
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
await vulnerabilityReport(analysis, catalogueAppId, config);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
40
|
+
await vulnerabilityReport(analysis, catalogueAppId, snapshotResponse.id);
|
|
51
41
|
await auditSave(config);
|
|
52
42
|
console.log('\n ***************CONTRAST OSS ANALYSIS COMPLETE************** \n');
|
|
53
43
|
};
|
|
@@ -89,7 +79,7 @@ async function auditSave(config) {
|
|
|
89
79
|
console.log(i18n.__('auditBadFiletypeSpecifiedForSave'));
|
|
90
80
|
}
|
|
91
81
|
}
|
|
92
|
-
else {
|
|
82
|
+
else if (config.save === null) {
|
|
93
83
|
console.log(i18n.__('auditNoFiletypeSpecifiedForSave'));
|
|
94
84
|
}
|
|
95
85
|
}
|
|
@@ -1,257 +1,85 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
function displaySuccessMessageReport() {
|
|
5
|
-
console.log('\n' + i18n.__('reportSuccessMessage'));
|
|
6
|
-
}
|
|
7
|
-
function getAllDependenciesArray(packageJson) {
|
|
8
|
-
const { dependencies, optionalDependencies, devDependencies, peerDependencies } = packageJson;
|
|
9
|
-
const allDep = {
|
|
10
|
-
...dependencies,
|
|
11
|
-
...devDependencies,
|
|
12
|
-
...optionalDependencies,
|
|
13
|
-
...peerDependencies
|
|
14
|
-
};
|
|
15
|
-
return Object.entries(allDep);
|
|
16
|
-
}
|
|
17
|
-
function checkIfDepIsScoped(arrDep) {
|
|
18
|
-
let count = 0;
|
|
19
|
-
arrDep.forEach(([key, value]) => {
|
|
20
|
-
if (!key.startsWith('@')) {
|
|
21
|
-
console.log(` WARNING not scoped: ${key}:${value}`);
|
|
22
|
-
count++;
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
return count;
|
|
26
|
-
}
|
|
27
|
-
const dependencyRiskReport = async (packageJson, config) => {
|
|
28
|
-
const arrDep = getAllDependenciesArray(packageJson);
|
|
29
|
-
const unRegisteredDeps = await checkIfDepIsRegisteredOnNPM(arrDep, config);
|
|
30
|
-
let scopedCount = checkIfDepIsScoped(unRegisteredDeps);
|
|
31
|
-
return {
|
|
32
|
-
scopedCount: scopedCount,
|
|
33
|
-
unRegisteredCount: unRegisteredDeps.length
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
|
-
const checkIfDepIsRegisteredOnNPM = async (arrDep, config) => {
|
|
37
|
-
let promises = [];
|
|
38
|
-
let unRegisteredDeps = [];
|
|
39
|
-
const client = getHttpClient(config);
|
|
40
|
-
for (const [index, element] of arrDep) {
|
|
41
|
-
const query = `query artifactByGAV($name: String!, $language: String!, $groupName: String, $version: String!, $nameCheck: Boolean) {
|
|
42
|
-
artifact: exactVersion(name: $name, language: $language, groupName: $groupName, version: $version, nameCheck: $nameCheck) {
|
|
43
|
-
version
|
|
44
|
-
cves {
|
|
45
|
-
baseScore
|
|
46
|
-
}}}`;
|
|
47
|
-
const data = {
|
|
48
|
-
query: query,
|
|
49
|
-
variables: {
|
|
50
|
-
name: index,
|
|
51
|
-
version: element,
|
|
52
|
-
language: 'node',
|
|
53
|
-
nameCheck: true
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
promises.push(client.checkLibrary(data));
|
|
57
|
-
}
|
|
58
|
-
await Promise.all(promises).then(response => {
|
|
59
|
-
response.forEach(res => {
|
|
60
|
-
const libName = JSON.parse(res.request.body);
|
|
61
|
-
if (res.statusCode === 200) {
|
|
62
|
-
if (res.body.data.artifact == null) {
|
|
63
|
-
unRegisteredDeps.push([
|
|
64
|
-
libName.variables.name,
|
|
65
|
-
libName.variables.version
|
|
66
|
-
]);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
if (unRegisteredDeps.length !== 0) {
|
|
72
|
-
console.log('\n Dependencies Risk Report', '\n\n Private libraries that are not scoped. We recommend these libraries are reviewed and the scope claimed to prevent dependency confusion breaches');
|
|
73
|
-
}
|
|
74
|
-
return unRegisteredDeps;
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
75
4
|
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.printFormattedOutput = exports.printVulnerabilityResponse = exports.getReport = exports.createLibraryHeader = void 0;
|
|
7
|
+
const i18n_1 = __importDefault(require("i18n"));
|
|
8
|
+
const commonApi_1 = require("../../../utils/commonApi");
|
|
9
|
+
const reportListModel_1 = require("./models/reportListModel");
|
|
10
|
+
const lodash_1 = require("lodash");
|
|
11
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
12
|
+
const reportUtils_1 = require("./utils/reportUtils");
|
|
13
|
+
const oraWrapper_1 = require("../../../utils/oraWrapper");
|
|
76
14
|
const createLibraryHeader = (id, numberOfVulnerableLibraries, numberOfCves, name) => {
|
|
77
15
|
name
|
|
78
|
-
? console.log(
|
|
16
|
+
? console.log(`\n Application Name: ${name} | Application ID: ${id}`)
|
|
79
17
|
: console.log(` Application ID: ${id}`);
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const inputtedCLIOptions = cliOptions.getCommandLineArgs();
|
|
88
|
-
let cveSeverityOption = inputtedCLIOptions['cve_severity'];
|
|
89
|
-
let fail = inputtedCLIOptions['fail'];
|
|
90
|
-
let cve_threshold = inputtedCLIOptions['cve_threshold'];
|
|
91
|
-
let expr;
|
|
92
|
-
if (cveSeverityOption && fail && cve_threshold) {
|
|
93
|
-
expr = 'SeverityAndThreshold';
|
|
94
|
-
}
|
|
95
|
-
else if (!cveSeverityOption && fail && cve_threshold) {
|
|
96
|
-
expr = 'ThresholdOnly';
|
|
97
|
-
}
|
|
98
|
-
else if (!cve_threshold && fail && hasSomeVulnerabilitiesReported[0]) {
|
|
99
|
-
expr = 'FailOnly';
|
|
100
|
-
}
|
|
101
|
-
return expr;
|
|
102
|
-
};
|
|
103
|
-
const analyseReportOptions = hasSomeVulnerabilitiesReported => {
|
|
104
|
-
const inputtedCLIOptions = cliOptions.getCommandLineArgs();
|
|
105
|
-
let cve_threshold = inputtedCLIOptions['cve_threshold'];
|
|
106
|
-
let cveSeverity;
|
|
107
|
-
let criticalSeverity;
|
|
108
|
-
let highSeverity;
|
|
109
|
-
let mediumSeverity;
|
|
110
|
-
let lowSeverity;
|
|
111
|
-
switch (parameterOptions(hasSomeVulnerabilitiesReported)) {
|
|
112
|
-
case 'SeverityAndThreshold':
|
|
113
|
-
cveSeverity = inputtedCLIOptions['cve_severity'].severity;
|
|
114
|
-
criticalSeverity = hasSomeVulnerabilitiesReported[2].critical;
|
|
115
|
-
highSeverity = hasSomeVulnerabilitiesReported[2].high;
|
|
116
|
-
mediumSeverity = hasSomeVulnerabilitiesReported[2].medium;
|
|
117
|
-
lowSeverity = hasSomeVulnerabilitiesReported[2].low;
|
|
118
|
-
if (cveSeverity === 'HIGH') {
|
|
119
|
-
if (cve_threshold < highSeverity + criticalSeverity) {
|
|
120
|
-
breakPipeline();
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
if (cveSeverity === 'MEDIUM') {
|
|
124
|
-
if (cve_threshold < mediumSeverity + highSeverity) {
|
|
125
|
-
breakPipeline();
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
if (cveSeverity === 'LOW') {
|
|
129
|
-
if (cve_threshold < lowSeverity + mediumSeverity + highSeverity) {
|
|
130
|
-
breakPipeline();
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
break;
|
|
134
|
-
case 'ThresholdOnly':
|
|
135
|
-
if (cve_threshold < hasSomeVulnerabilitiesReported[1]) {
|
|
136
|
-
breakPipeline();
|
|
137
|
-
}
|
|
138
|
-
break;
|
|
139
|
-
case 'FailOnly':
|
|
140
|
-
breakPipeline();
|
|
141
|
-
break;
|
|
142
|
-
}
|
|
18
|
+
numberOfVulnerableLibraries === 1
|
|
19
|
+
? console.log('\n **************************' +
|
|
20
|
+
` Found 1 vulnerable library containing ${numberOfCves} CVE's` +
|
|
21
|
+
'************************** ')
|
|
22
|
+
: console.log('\n **************************' +
|
|
23
|
+
` Found ${numberOfVulnerableLibraries} vulnerable libraries containing ${numberOfCves} CVE's ` +
|
|
24
|
+
'************************** ');
|
|
143
25
|
};
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const
|
|
147
|
-
const
|
|
148
|
-
|
|
26
|
+
exports.createLibraryHeader = createLibraryHeader;
|
|
27
|
+
const getReport = async (config, reportId) => {
|
|
28
|
+
const client = (0, commonApi_1.getHttpClient)(config);
|
|
29
|
+
const reportSpinner = (0, oraWrapper_1.returnOra)(i18n_1.default.__('auditReportWaiting'));
|
|
30
|
+
reportSpinner.indent = 1;
|
|
31
|
+
(0, oraWrapper_1.startSpinner)(reportSpinner);
|
|
149
32
|
return client
|
|
150
|
-
.
|
|
151
|
-
.then(res => {
|
|
33
|
+
.getReportById(config, reportId)
|
|
34
|
+
.then((res) => {
|
|
152
35
|
if (res.statusCode === 200) {
|
|
153
|
-
|
|
36
|
+
(0, oraWrapper_1.succeedSpinner)(reportSpinner, i18n_1.default.__('auditReportSuccessMessage'));
|
|
154
37
|
return res.body;
|
|
155
38
|
}
|
|
156
39
|
else {
|
|
157
|
-
|
|
40
|
+
(0, oraWrapper_1.failSpinner)(reportSpinner, i18n_1.default.__('auditReportFail'));
|
|
41
|
+
console.log('config-------------------');
|
|
42
|
+
console.log(config);
|
|
43
|
+
console.log('reportId----------------');
|
|
44
|
+
console.log(reportId);
|
|
45
|
+
console.log(JSON.stringify(res));
|
|
46
|
+
(0, commonApi_1.handleResponseErrors)(res, 'report');
|
|
158
47
|
}
|
|
159
48
|
})
|
|
160
|
-
.catch(err => {
|
|
49
|
+
.catch((err) => {
|
|
161
50
|
console.log(err);
|
|
162
51
|
});
|
|
163
52
|
};
|
|
164
|
-
|
|
53
|
+
exports.getReport = getReport;
|
|
54
|
+
const printVulnerabilityResponse = (vulnerabilities, config) => {
|
|
165
55
|
let hasSomeVulnerabilitiesReported = false;
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
hasSomeVulnerabilitiesReported = true;
|
|
170
|
-
}
|
|
171
|
-
else {
|
|
172
|
-
returnCveData(vulnerabilities);
|
|
173
|
-
if (Object.keys(vulnerabilities).length > 0)
|
|
174
|
-
hasSomeVulnerabilitiesReported = true;
|
|
56
|
+
(0, exports.printFormattedOutput)(vulnerabilities, config);
|
|
57
|
+
if (Object.keys(vulnerabilities).length > 0) {
|
|
58
|
+
hasSomeVulnerabilitiesReported = true;
|
|
175
59
|
}
|
|
176
60
|
return hasSomeVulnerabilitiesReported;
|
|
177
61
|
};
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
const
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
const version = nameVersion[1];
|
|
186
|
-
const libName = group !== 'null'
|
|
187
|
-
? `${group}/${name}/${version} is vulnerable`
|
|
188
|
-
: `${name}/${version} is vulnerable`;
|
|
189
|
-
console.log('\n\n ' + libName);
|
|
190
|
-
value.forEach(vuln => {
|
|
191
|
-
let sevCode = vuln.severityCode || vuln.severity_code;
|
|
192
|
-
console.log('\n ' + vuln.name + ' ' + sevCode + '\n ' + vuln.description);
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
};
|
|
196
|
-
function searchHighCVEs(vuln) {
|
|
197
|
-
let sevCode = vuln.severityCode || vuln.severity_code;
|
|
198
|
-
if (sevCode === 'HIGH') {
|
|
199
|
-
return vuln;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
function searchMediumCVEs(vuln) {
|
|
203
|
-
let sevCode = vuln.severityCode || vuln.severity_code;
|
|
204
|
-
if (sevCode === 'HIGH' || sevCode === 'MEDIUM') {
|
|
205
|
-
return vuln;
|
|
62
|
+
exports.printVulnerabilityResponse = printVulnerabilityResponse;
|
|
63
|
+
const printFormattedOutput = (libraries, config) => {
|
|
64
|
+
const report = new reportListModel_1.ReportList();
|
|
65
|
+
for (const library of libraries) {
|
|
66
|
+
const { name, version } = (0, reportUtils_1.findNameAndVersion)(library, config);
|
|
67
|
+
const newOutputModel = new reportListModel_1.ReportModelStructure(new reportListModel_1.ReportCompositeKey(name, version, (0, reportUtils_1.findHighestSeverityCVE)(library.cveArray)), library.cveArray);
|
|
68
|
+
report.reportOutputList.push(newOutputModel);
|
|
206
69
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
70
|
+
const orderedOutputList = (0, lodash_1.orderBy)(report.reportOutputList, reportListItem => reportListItem.compositeKey.highestSeverity.priority);
|
|
71
|
+
for (const reportModel of orderedOutputList) {
|
|
72
|
+
const name = reportModel.compositeKey.libraryName;
|
|
73
|
+
const version = reportModel.compositeKey.libraryVersion;
|
|
74
|
+
const highestSeverity = reportModel.compositeKey.highestSeverity.severity;
|
|
75
|
+
const numOfCVEs = reportModel.cveArray.length;
|
|
76
|
+
const cveNames = [];
|
|
77
|
+
reportModel.cveArray.forEach(cve => cveNames.push(cve.name));
|
|
78
|
+
const boldHeader = chalk_1.default.bold(`${highestSeverity} | Vulnerable Library`);
|
|
79
|
+
const cvePluralised = numOfCVEs > 1 ? 'CVEs' : 'CVE';
|
|
80
|
+
console.log(`\n ${boldHeader} ${name} (${version}) has ${numOfCVEs} known ${cvePluralised}`);
|
|
81
|
+
console.log(` ${cveNames.join(', ')}`);
|
|
82
|
+
console.log(chalk_1.default.bold(' How to fix: Update to latest version'));
|
|
212
83
|
}
|
|
213
|
-
}
|
|
214
|
-
const filterVulnerabilitiesBySeverity = (severity, vulnerabilities) => {
|
|
215
|
-
let filteredVulns = [];
|
|
216
|
-
if (severity) {
|
|
217
|
-
for (let x in vulnerabilities) {
|
|
218
|
-
if (severity.severity === 'HIGH') {
|
|
219
|
-
let highVulnerability = vulnerabilities[x].filter(searchHighCVEs);
|
|
220
|
-
if (highVulnerability.length > 0) {
|
|
221
|
-
filteredVulns[x] = highVulnerability;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
else if (severity.severity === 'MEDIUM') {
|
|
225
|
-
let mediumVulnerability = vulnerabilities[x].filter(searchMediumCVEs);
|
|
226
|
-
if (mediumVulnerability.length > 0) {
|
|
227
|
-
filteredVulns[x] = mediumVulnerability;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
else if (severity.severity === 'LOW') {
|
|
231
|
-
let lowVulnerability = vulnerabilities[x].filter(searchLowCVEs);
|
|
232
|
-
if (lowVulnerability.length > 0) {
|
|
233
|
-
filteredVulns[x] = lowVulnerability;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
return filteredVulns;
|
|
239
|
-
};
|
|
240
|
-
module.exports = {
|
|
241
|
-
displaySuccessMessageReport: displaySuccessMessageReport,
|
|
242
|
-
getAllDependenciesArray: getAllDependenciesArray,
|
|
243
|
-
dependencyRiskReport: dependencyRiskReport,
|
|
244
|
-
createLibraryHeader: createLibraryHeader,
|
|
245
|
-
breakPipeline: breakPipeline,
|
|
246
|
-
parameterOptions: parameterOptions,
|
|
247
|
-
analyseReportOptions: analyseReportOptions,
|
|
248
|
-
getReport: getReport,
|
|
249
|
-
checkIfDepIsScoped: checkIfDepIsScoped,
|
|
250
|
-
checkIfDepIsRegisteredOnNPM: checkIfDepIsRegisteredOnNPM,
|
|
251
|
-
filterVulnerabilitiesBySeverity: filterVulnerabilitiesBySeverity,
|
|
252
|
-
searchLowCVEs: searchLowCVEs,
|
|
253
|
-
searchMediumCVEs: searchMediumCVEs,
|
|
254
|
-
searchHighCVEs: searchHighCVEs,
|
|
255
|
-
returnCveData: returnCveData,
|
|
256
|
-
printVulnerabilityResponse: printVulnerabilityResponse
|
|
257
84
|
};
|
|
85
|
+
exports.printFormattedOutput = printFormattedOutput;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReportCVEModel = exports.ReportLibraryModel = void 0;
|
|
4
|
+
class ReportLibraryModel {
|
|
5
|
+
constructor(name, cveArray) {
|
|
6
|
+
this.name = name;
|
|
7
|
+
this.cveArray = cveArray;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.ReportLibraryModel = ReportLibraryModel;
|
|
11
|
+
class ReportCVEModel {
|
|
12
|
+
constructor(name, description, severityCode, cvss3SeverityCode) {
|
|
13
|
+
this.name = name;
|
|
14
|
+
this.description = description;
|
|
15
|
+
this.severityCode = severityCode;
|
|
16
|
+
this.cvss3SeverityCode = cvss3SeverityCode;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.ReportCVEModel = ReportCVEModel;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReportCompositeKey = exports.ReportModelStructure = exports.ReportList = void 0;
|
|
4
|
+
class ReportList {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.reportOutputList = [];
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
exports.ReportList = ReportList;
|
|
10
|
+
class ReportModelStructure {
|
|
11
|
+
constructor(compositeKey, cveArray) {
|
|
12
|
+
this.compositeKey = compositeKey;
|
|
13
|
+
this.cveArray = cveArray;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.ReportModelStructure = ReportModelStructure;
|
|
17
|
+
class ReportCompositeKey {
|
|
18
|
+
constructor(libraryName, libraryVersion, highestSeverity) {
|
|
19
|
+
this.libraryName = libraryName;
|
|
20
|
+
this.libraryVersion = libraryVersion;
|
|
21
|
+
this.highestSeverity = highestSeverity;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.ReportCompositeKey = ReportCompositeKey;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReportSeverityModel = void 0;
|
|
4
|
+
class ReportSeverityModel {
|
|
5
|
+
constructor(severity, priority) {
|
|
6
|
+
this.severity = severity;
|
|
7
|
+
this.priority = priority;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.ReportSeverityModel = ReportSeverityModel;
|
|
@@ -1,133 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
if (config['report']) {
|
|
14
|
-
const reportResponse = await commonReport.getReport(applicationId);
|
|
15
|
-
if (reportResponse !== undefined) {
|
|
16
|
-
const libraryVulnerabilityInput = createLibraryVulnerabilityInput(reportResponse.reports);
|
|
17
|
-
const libraryVulnerabilityResponse = await getLibraryVulnerabilities(libraryVulnerabilityInput, applicationId);
|
|
18
|
-
const severity = config['cve_severity'];
|
|
19
|
-
const id = applicationId;
|
|
20
|
-
const name = config.applicationName;
|
|
21
|
-
const hasSomeVulnerabilitiesReported = formatVulnerabilityOutput(libraryVulnerabilityResponse, severity, id, name, depRiskReportCount, config);
|
|
22
|
-
commonReport.analyseReportOptions(hasSomeVulnerabilitiesReported);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
const createLibraryVulnerabilityInput = report => {
|
|
27
|
-
const language = Object.keys(report[0].report)[0];
|
|
28
|
-
const reportTree = report[0].report[language].dependencyTree;
|
|
29
|
-
const libraries = reportTree[Object.keys(reportTree)[0]];
|
|
30
|
-
let gav = [];
|
|
31
|
-
for (const key of Object.keys(libraries)) {
|
|
32
|
-
gav.push({
|
|
33
|
-
name: libraries[key].name,
|
|
34
|
-
group: libraries[key].group,
|
|
35
|
-
version: libraries[key].resolved
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
return {
|
|
39
|
-
name_group_versions: gav,
|
|
40
|
-
language: language.toUpperCase()
|
|
41
|
-
};
|
|
42
|
-
};
|
|
43
|
-
const oldCountSeverity = vulnerableLibraries => {
|
|
44
|
-
const severityCount = {
|
|
45
|
-
critical: 0,
|
|
46
|
-
high: 0,
|
|
47
|
-
medium: 0,
|
|
48
|
-
low: 0
|
|
49
|
-
};
|
|
50
|
-
vulnerableLibraries.forEach(lib => {
|
|
51
|
-
lib.vulns.forEach(vuln => {
|
|
52
|
-
if (vuln.severity_code === 'HIGH') {
|
|
53
|
-
severityCount['high'] += 1;
|
|
54
|
-
}
|
|
55
|
-
else if (vuln.severity_code === 'MEDIUM') {
|
|
56
|
-
severityCount['medium'] += 1;
|
|
57
|
-
}
|
|
58
|
-
else if (vuln.severity_code === 'LOW') {
|
|
59
|
-
severityCount['low'] += 1;
|
|
60
|
-
}
|
|
61
|
-
else if (vuln.severity_code === 'CRITICAL') {
|
|
62
|
-
severityCount['critical'] += 1;
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
return severityCount;
|
|
67
|
-
};
|
|
68
|
-
const parseVulnerabilites = libraryVulnerabilityResponse => {
|
|
69
|
-
let parsedVulnerabilites = {};
|
|
70
|
-
let vulnName = libraryVulnerabilityResponse.libraries;
|
|
71
|
-
for (let x in vulnName) {
|
|
72
|
-
let vuln = vulnName[x].vulns;
|
|
73
|
-
if (vuln.length > 0) {
|
|
74
|
-
let libname = vulnName[x].group +
|
|
75
|
-
'/' +
|
|
76
|
-
vulnName[x].file_name +
|
|
77
|
-
'@' +
|
|
78
|
-
vulnName[x].file_version;
|
|
79
|
-
parsedVulnerabilites[libname] = vulnName[x].vulns;
|
|
80
|
-
}
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatVulnerabilityOutput = exports.vulnerabilityReport = void 0;
|
|
4
|
+
const commonReportingFunctions_1 = require("./commonReportingFunctions");
|
|
5
|
+
const reportUtils_1 = require("./utils/reportUtils");
|
|
6
|
+
async function vulnerabilityReport(analysis, applicationId, reportId) {
|
|
7
|
+
const reportResponse = await (0, commonReportingFunctions_1.getReport)(analysis.config, reportId);
|
|
8
|
+
if (reportResponse !== undefined) {
|
|
9
|
+
const id = applicationId;
|
|
10
|
+
const name = analysis.config.applicationName;
|
|
11
|
+
formatVulnerabilityOutput(reportResponse.vulnerabilities, id, name, analysis.config);
|
|
81
12
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
return data.vulns.length > 0;
|
|
87
|
-
});
|
|
13
|
+
}
|
|
14
|
+
exports.vulnerabilityReport = vulnerabilityReport;
|
|
15
|
+
function formatVulnerabilityOutput(libraryVulnerabilityResponse, id, name, config) {
|
|
16
|
+
const vulnerableLibraries = (0, reportUtils_1.convertGenericToTypedLibraries)(libraryVulnerabilityResponse);
|
|
88
17
|
const numberOfVulnerableLibraries = vulnerableLibraries.length;
|
|
89
18
|
let numberOfCves = 0;
|
|
90
|
-
vulnerableLibraries.forEach(lib => (numberOfCves += lib.
|
|
91
|
-
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if (depRiskReportCount && depRiskReportCount.scopedCount === 0) {
|
|
101
|
-
console.log(' No private libraries that are not scoped detected');
|
|
102
|
-
}
|
|
103
|
-
console.log(' \n Please go to the Contrast UI to view your dependency tree: \n' +
|
|
104
|
-
` \n ${config.host}/Contrast/static/ng/index.html#/${config.organizationId}/applications/${config.applicationId}/libs/dependency-tree`);
|
|
105
|
-
return [hasSomeVulnerabilitiesReported, numberOfCves, severityCount];
|
|
106
|
-
};
|
|
107
|
-
const getLibraryVulnerabilities = async (input, applicationId) => {
|
|
108
|
-
const requestBody = input;
|
|
109
|
-
const addParams = agent.getAdditionalParams();
|
|
110
|
-
const userParams = await util.getParams(applicationId);
|
|
111
|
-
const protocol = getValidHost(userParams.host);
|
|
112
|
-
const client = commonApi.getHttpClient(userParams, protocol, addParams);
|
|
113
|
-
return client
|
|
114
|
-
.getLibraryVulnerabilities(requestBody, userParams)
|
|
115
|
-
.then(res => {
|
|
116
|
-
if (res.statusCode === 200) {
|
|
117
|
-
displaySuccessMessageVulnerabilities();
|
|
118
|
-
return res.body;
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
handleResponseErrors(res, 'vulnerabilities');
|
|
122
|
-
}
|
|
123
|
-
})
|
|
124
|
-
.catch(err => {
|
|
125
|
-
console.log(err);
|
|
126
|
-
});
|
|
127
|
-
};
|
|
128
|
-
module.exports = {
|
|
129
|
-
vulnerabilityReport: vulnerabilityReport,
|
|
130
|
-
getLibraryVulnerabilities: getLibraryVulnerabilities,
|
|
131
|
-
formatVulnerabilityOutput: formatVulnerabilityOutput,
|
|
132
|
-
createLibraryVulnerabilityInput: createLibraryVulnerabilityInput
|
|
133
|
-
};
|
|
19
|
+
vulnerableLibraries.forEach(lib => (numberOfCves += lib.cveArray.length));
|
|
20
|
+
(0, commonReportingFunctions_1.createLibraryHeader)(id, numberOfVulnerableLibraries, numberOfCves, name);
|
|
21
|
+
const hasSomeVulnerabilitiesReported = (0, commonReportingFunctions_1.printVulnerabilityResponse)(vulnerableLibraries, config);
|
|
22
|
+
return [
|
|
23
|
+
hasSomeVulnerabilitiesReported,
|
|
24
|
+
numberOfCves,
|
|
25
|
+
(0, reportUtils_1.severityCount)(vulnerableLibraries)
|
|
26
|
+
];
|
|
27
|
+
}
|
|
28
|
+
exports.formatVulnerabilityOutput = formatVulnerabilityOutput;
|