@contrast/contrast 1.0.10 → 1.0.13
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/README.md +1 -1
- package/dist/audit/{languageAnalysisEngine/report → report}/commonReportingFunctions.js +56 -35
- package/dist/audit/report/models/reportGuidanceModel.js +6 -0
- package/dist/audit/{languageAnalysisEngine/report → report}/models/reportLibraryModel.js +0 -0
- package/dist/audit/{languageAnalysisEngine/report → report}/models/reportListModel.js +0 -0
- package/dist/audit/{languageAnalysisEngine/report → report}/models/reportOutputModel.js +1 -2
- package/dist/audit/{languageAnalysisEngine/report → report}/models/reportSeverityModel.js +0 -0
- package/dist/audit/{languageAnalysisEngine/report → report}/models/severityCountModel.js +1 -0
- package/dist/audit/{languageAnalysisEngine/report → report}/reportingFeature.js +12 -8
- package/dist/audit/{languageAnalysisEngine/report → report}/utils/reportUtils.js +3 -4
- package/dist/commands/audit/auditConfig.js +3 -3
- package/dist/commands/audit/help.js +3 -1
- package/dist/commands/audit/processAudit.js +14 -2
- package/dist/commands/auth/auth.js +1 -1
- package/dist/commands/config/config.js +2 -2
- package/dist/commands/scan/processScan.js +20 -4
- package/dist/commands/scan/sca/scaAnalysis.js +15 -5
- package/dist/common/HTTPClient.js +39 -2
- package/dist/common/commonHelp.js +19 -0
- package/dist/common/fail.js +70 -0
- package/dist/common/versionChecker.js +14 -6
- package/dist/constants/constants.js +2 -2
- package/dist/constants/locales.js +15 -5
- package/dist/constants.js +42 -5
- package/dist/index.js +6 -3
- package/dist/lambda/help.js +2 -3
- package/dist/lambda/lambda.js +7 -0
- package/dist/scaAnalysis/common/scaParserForGoAndJava.js +32 -0
- package/dist/scaAnalysis/common/scaServicesUpload.js +52 -0
- package/dist/scaAnalysis/common/treeUpload.js +20 -5
- package/dist/scaAnalysis/dotnet/analysis.js +15 -3
- package/dist/scaAnalysis/go/goAnalysis.js +8 -2
- package/dist/scaAnalysis/java/analysis.js +10 -6
- package/dist/scaAnalysis/java/index.js +7 -1
- package/dist/scaAnalysis/java/javaBuildDepsParser.js +19 -3
- package/dist/scaAnalysis/javascript/index.js +4 -0
- package/dist/scaAnalysis/javascript/scaServiceParser.js +109 -0
- package/dist/scaAnalysis/php/analysis.js +1 -1
- package/dist/scaAnalysis/php/index.js +12 -6
- package/dist/scaAnalysis/php/phpNewServicesMapper.js +62 -0
- package/dist/scaAnalysis/python/analysis.js +43 -5
- package/dist/scaAnalysis/python/index.js +7 -2
- package/dist/scaAnalysis/ruby/analysis.js +116 -9
- package/dist/scaAnalysis/ruby/index.js +6 -1
- package/dist/scan/formatScanOutput.js +6 -5
- package/dist/scan/help.js +2 -3
- package/dist/scan/populateProjectIdAndProjectName.js +5 -0
- package/dist/scan/scan.js +4 -0
- package/dist/scan/scanConfig.js +4 -4
- package/dist/scan/scanResults.js +46 -3
- package/dist/telemetry/telemetry.js +137 -0
- package/dist/{audit/languageAnalysisEngine/util → utils}/capabilities.js +0 -0
- package/dist/{audit/languageAnalysisEngine/util → utils}/generalAPI.js +14 -5
- package/dist/utils/getConfig.js +2 -4
- package/dist/utils/parsedCLIOptions.js +3 -1
- package/dist/utils/requestUtils.js +7 -1
- package/package.json +4 -2
- package/src/audit/{languageAnalysisEngine/report → report}/commonReportingFunctions.ts +80 -44
- package/src/audit/report/models/reportGuidanceModel.ts +5 -0
- package/src/audit/{languageAnalysisEngine/report → report}/models/reportLibraryModel.ts +0 -0
- package/src/audit/{languageAnalysisEngine/report → report}/models/reportListModel.ts +0 -0
- package/src/audit/{languageAnalysisEngine/report → report}/models/reportOutputModel.ts +1 -7
- package/src/audit/{languageAnalysisEngine/report → report}/models/reportSeverityModel.ts +0 -0
- package/src/audit/{languageAnalysisEngine/report → report}/models/severityCountModel.ts +2 -0
- package/src/audit/{languageAnalysisEngine/report → report}/reportingFeature.ts +16 -9
- package/src/audit/{languageAnalysisEngine/report → report}/utils/reportUtils.ts +4 -4
- package/src/commands/audit/auditConfig.ts +10 -3
- package/src/commands/audit/help.ts +3 -1
- package/src/commands/audit/processAudit.ts +24 -2
- package/src/commands/auth/auth.js +3 -1
- package/src/commands/config/config.js +4 -2
- package/src/commands/scan/processScan.js +32 -4
- package/src/commands/scan/sca/scaAnalysis.js +23 -5
- package/src/common/HTTPClient.js +59 -2
- package/src/common/commonHelp.ts +13 -0
- package/src/common/fail.js +79 -0
- package/src/common/versionChecker.ts +18 -8
- package/src/constants/constants.js +2 -2
- package/src/constants/locales.js +19 -7
- package/src/constants.js +46 -6
- package/src/index.ts +18 -4
- package/src/lambda/help.ts +2 -3
- package/src/lambda/lambda.ts +12 -0
- package/src/scaAnalysis/common/scaParserForGoAndJava.js +41 -0
- package/src/scaAnalysis/common/scaServicesUpload.js +54 -0
- package/src/scaAnalysis/common/treeUpload.js +21 -5
- package/src/scaAnalysis/dotnet/analysis.js +21 -3
- package/src/scaAnalysis/go/goAnalysis.js +9 -2
- package/src/scaAnalysis/java/analysis.js +11 -6
- package/src/scaAnalysis/java/index.js +9 -1
- package/src/scaAnalysis/java/javaBuildDepsParser.js +25 -6
- package/src/scaAnalysis/javascript/index.js +4 -0
- package/src/scaAnalysis/javascript/scaServiceParser.js +145 -0
- package/src/scaAnalysis/php/analysis.js +1 -1
- package/src/scaAnalysis/php/index.js +12 -6
- package/src/scaAnalysis/php/phpNewServicesMapper.js +77 -0
- package/src/scaAnalysis/python/analysis.js +49 -5
- package/src/scaAnalysis/python/index.js +7 -2
- package/src/scaAnalysis/ruby/analysis.js +149 -9
- package/src/scaAnalysis/ruby/index.js +6 -1
- package/src/scan/formatScanOutput.ts +7 -5
- package/src/scan/help.js +2 -3
- package/src/scan/populateProjectIdAndProjectName.js +5 -1
- package/src/scan/scan.ts +4 -0
- package/src/scan/scanConfig.js +6 -4
- package/src/scan/scanResults.js +52 -3
- package/src/telemetry/telemetry.ts +154 -0
- package/src/{audit/languageAnalysisEngine/util → utils}/capabilities.js +0 -0
- package/src/{audit/languageAnalysisEngine/util → utils}/generalAPI.js +16 -6
- package/src/utils/getConfig.ts +2 -11
- package/src/utils/parsedCLIOptions.js +14 -1
- package/src/utils/requestUtils.js +8 -1
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.sha1Base64Value = exports.findParamValueFromArgs = exports.paramExists = exports.obfuscateParams = exports.sendTelemetryRequest = exports.sendTelemetryConfigAsObject = exports.sendTelemetryConfigAsConfObj = exports.TELEMETRY_CLI_TIME_TO_AUTH_EVENT = exports.TELEMETRY_CLI_COMMANDS_EVENT = void 0;
|
|
27
|
+
const commonApi_1 = require("../utils/commonApi");
|
|
28
|
+
const crypto = __importStar(require("crypto"));
|
|
29
|
+
exports.TELEMETRY_CLI_COMMANDS_EVENT = 'CLI_COMMANDS';
|
|
30
|
+
exports.TELEMETRY_CLI_TIME_TO_AUTH_EVENT = 'CLI_TIME_TO_AUTH';
|
|
31
|
+
const sendTelemetryConfigAsConfObj = async (config, command, argv, result, language) => {
|
|
32
|
+
const hostParam = '--host';
|
|
33
|
+
const hostParamAlias = '-h';
|
|
34
|
+
const orgIdParam = '--organization-id';
|
|
35
|
+
const orgIdParamAlias = '-o';
|
|
36
|
+
const authParam = '--authorization';
|
|
37
|
+
const apiKeyParam = '--api-key';
|
|
38
|
+
let configToUse;
|
|
39
|
+
if ((0, exports.paramExists)(argv, hostParam, hostParamAlias) &&
|
|
40
|
+
(0, exports.paramExists)(argv, orgIdParam, orgIdParamAlias) &&
|
|
41
|
+
(0, exports.paramExists)(argv, authParam, null) &&
|
|
42
|
+
(0, exports.paramExists)(argv, apiKeyParam, null)) {
|
|
43
|
+
configToUse = {
|
|
44
|
+
host: (0, exports.findParamValueFromArgs)(argv, hostParam, hostParamAlias),
|
|
45
|
+
organizationId: (0, exports.findParamValueFromArgs)(argv, orgIdParam, orgIdParamAlias),
|
|
46
|
+
authorization: (0, exports.findParamValueFromArgs)(argv, authParam, null),
|
|
47
|
+
apiKey: (0, exports.findParamValueFromArgs)(argv, apiKeyParam, null)
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
else if (config &&
|
|
51
|
+
config.get('host') &&
|
|
52
|
+
config.get('organizationId') &&
|
|
53
|
+
config.get('authorization') &&
|
|
54
|
+
config.get('apiKey')) {
|
|
55
|
+
configToUse = {
|
|
56
|
+
host: config.get('host')?.slice(0, -1),
|
|
57
|
+
organizationId: config.get('organizationId'),
|
|
58
|
+
authorization: config.get('authorization'),
|
|
59
|
+
apiKey: config.get('apiKey')
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
return await (0, exports.sendTelemetryConfigAsObject)(configToUse, command, argv, result, language);
|
|
66
|
+
};
|
|
67
|
+
exports.sendTelemetryConfigAsConfObj = sendTelemetryConfigAsConfObj;
|
|
68
|
+
const sendTelemetryConfigAsObject = async (config, command, argv, result, language) => {
|
|
69
|
+
const obfuscatedParams = (0, exports.obfuscateParams)(argv);
|
|
70
|
+
const requestBody = {
|
|
71
|
+
event: exports.TELEMETRY_CLI_COMMANDS_EVENT,
|
|
72
|
+
details: {
|
|
73
|
+
ip_address: '',
|
|
74
|
+
account_name: '',
|
|
75
|
+
account_host: '',
|
|
76
|
+
company_domain: '',
|
|
77
|
+
command: `contrast ${command} ${obfuscatedParams}`,
|
|
78
|
+
app_id: config && config.applicationId
|
|
79
|
+
? (0, exports.sha1Base64Value)(config.applicationId)
|
|
80
|
+
: 'undefined',
|
|
81
|
+
project_id: config && config.projectId
|
|
82
|
+
? (0, exports.sha1Base64Value)(config.projectId)
|
|
83
|
+
: 'undefined',
|
|
84
|
+
language: language,
|
|
85
|
+
result: result,
|
|
86
|
+
additional_info: '',
|
|
87
|
+
timestamp: new Date().toUTCString()
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
return await (0, exports.sendTelemetryRequest)(config, requestBody);
|
|
91
|
+
};
|
|
92
|
+
exports.sendTelemetryConfigAsObject = sendTelemetryConfigAsObject;
|
|
93
|
+
const sendTelemetryRequest = async (config, requestBody) => {
|
|
94
|
+
const client = (0, commonApi_1.getHttpClient)(config);
|
|
95
|
+
return client
|
|
96
|
+
.postTelemetry(config, requestBody)
|
|
97
|
+
.then((res) => {
|
|
98
|
+
if (res.statusCode !== 200 && config.debug === true) {
|
|
99
|
+
console.log('Telemetry failed to send with status', res.statusCode);
|
|
100
|
+
}
|
|
101
|
+
return { statusCode: res.statusCode, statusMessage: res.statusMessage };
|
|
102
|
+
})
|
|
103
|
+
.catch((err) => {
|
|
104
|
+
return;
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
exports.sendTelemetryRequest = sendTelemetryRequest;
|
|
108
|
+
const obfuscateParams = (argv) => {
|
|
109
|
+
return argv
|
|
110
|
+
.join(' ')
|
|
111
|
+
.replace(/--(authorization [A-Z0-9]+)/gi, '--authorization *****')
|
|
112
|
+
.replace(/-(o [A-Z0-9-]+)/gi, '-o *****')
|
|
113
|
+
.replace(/--(organization-id [A-Z0-9-]+)/gi, '--organization-id *****')
|
|
114
|
+
.replace(/--(api-key [A-Z0-9]+)/gi, '--api-key *****');
|
|
115
|
+
};
|
|
116
|
+
exports.obfuscateParams = obfuscateParams;
|
|
117
|
+
const paramExists = (argv, param, paramAlias) => {
|
|
118
|
+
return argv.find((arg) => arg === param || arg === paramAlias);
|
|
119
|
+
};
|
|
120
|
+
exports.paramExists = paramExists;
|
|
121
|
+
const findParamValueFromArgs = (argv, param, paramAlias) => {
|
|
122
|
+
let paramAsValue;
|
|
123
|
+
argv.forEach((arg, index) => {
|
|
124
|
+
if (arg === param ||
|
|
125
|
+
(arg === paramAlias &&
|
|
126
|
+
argv[index + 1] !== undefined &&
|
|
127
|
+
argv[index + 1] !== null)) {
|
|
128
|
+
paramAsValue = argv[index + 1];
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
return paramAsValue;
|
|
132
|
+
};
|
|
133
|
+
exports.findParamValueFromArgs = findParamValueFromArgs;
|
|
134
|
+
const sha1Base64Value = (value) => {
|
|
135
|
+
return crypto.createHash('sha1').update(value).digest('base64');
|
|
136
|
+
};
|
|
137
|
+
exports.sha1Base64Value = sha1Base64Value;
|
|
File without changes
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const { featuresTeamServer } = require('./capabilities');
|
|
3
3
|
const semver = require('semver');
|
|
4
|
-
const { handleResponseErrors } = require('
|
|
5
|
-
const
|
|
4
|
+
const { handleResponseErrors } = require('../common/errorHandling');
|
|
5
|
+
const commonApi = require('./commonApi');
|
|
6
|
+
const { isNil } = require('lodash');
|
|
6
7
|
const getGlobalProperties = async (config) => {
|
|
7
|
-
const client = getHttpClient(config);
|
|
8
|
+
const client = commonApi.getHttpClient(config);
|
|
8
9
|
return client
|
|
9
|
-
.getGlobalProperties(config)
|
|
10
|
+
.getGlobalProperties(config.host)
|
|
10
11
|
.then(res => {
|
|
11
12
|
if (res.statusCode === 200) {
|
|
12
13
|
return res.body;
|
|
@@ -19,6 +20,13 @@ const getGlobalProperties = async (config) => {
|
|
|
19
20
|
console.log(err);
|
|
20
21
|
});
|
|
21
22
|
};
|
|
23
|
+
const getMode = async (config) => {
|
|
24
|
+
const features = await getGlobalProperties(config);
|
|
25
|
+
if (!isNil(features?.mode)) {
|
|
26
|
+
return features.mode;
|
|
27
|
+
}
|
|
28
|
+
return '';
|
|
29
|
+
};
|
|
22
30
|
const getFeatures = version => {
|
|
23
31
|
const featuresEnabled = [];
|
|
24
32
|
featuresTeamServer.forEach(feature => {
|
|
@@ -35,5 +43,6 @@ const isFeatureEnabled = (features, featureName) => {
|
|
|
35
43
|
module.exports = {
|
|
36
44
|
getGlobalProperties,
|
|
37
45
|
getFeatures,
|
|
38
|
-
isFeatureEnabled
|
|
46
|
+
isFeatureEnabled,
|
|
47
|
+
getMode
|
|
39
48
|
};
|
package/dist/utils/getConfig.js
CHANGED
|
@@ -5,16 +5,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.setConfigValues = exports.localConfig = void 0;
|
|
7
7
|
const conf_1 = __importDefault(require("conf"));
|
|
8
|
+
const constants_1 = require("../constants/constants");
|
|
8
9
|
const localConfig = (name, version) => {
|
|
9
10
|
const config = new conf_1.default({
|
|
10
11
|
configName: name
|
|
11
12
|
});
|
|
12
13
|
config.set('version', version);
|
|
13
|
-
if (process.env.CONTRAST_CODSEC_DISABLE_UPDATE_MESSAGE) {
|
|
14
|
-
config.set('updateMessageHidden', JSON.parse(process.env.CONTRAST_CODSEC_DISABLE_UPDATE_MESSAGE.toLowerCase()));
|
|
15
|
-
}
|
|
16
14
|
if (!config.has('host')) {
|
|
17
|
-
config.set('host',
|
|
15
|
+
config.set('host', constants_1.CE_URL);
|
|
18
16
|
}
|
|
19
17
|
return config;
|
|
20
18
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const commandLineArgs = require('command-line-args');
|
|
3
|
-
const
|
|
3
|
+
const { sendTelemetryConfigAsConfObj } = require('../telemetry/telemetry');
|
|
4
|
+
const getCommandLineArgsCustom = async (contrastConf, command, parameterList, optionDefinitions) => {
|
|
4
5
|
try {
|
|
5
6
|
return commandLineArgs(optionDefinitions, {
|
|
6
7
|
argv: parameterList,
|
|
@@ -10,6 +11,7 @@ const getCommandLineArgsCustom = (parameterList, optionDefinitions) => {
|
|
|
10
11
|
});
|
|
11
12
|
}
|
|
12
13
|
catch (e) {
|
|
14
|
+
await sendTelemetryConfigAsConfObj(contrastConf, command, parameterList, 'FAILURE', 'undefined');
|
|
13
15
|
console.log(e.message.toString());
|
|
14
16
|
process.exit(1);
|
|
15
17
|
}
|
|
@@ -11,8 +11,14 @@ const millisToSeconds = millis => {
|
|
|
11
11
|
const sleep = ms => {
|
|
12
12
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
13
13
|
};
|
|
14
|
+
const timeOutError = (ms, reject) => {
|
|
15
|
+
return setTimeout(() => {
|
|
16
|
+
reject(new Error(`No input detected after 30s`));
|
|
17
|
+
}, ms);
|
|
18
|
+
};
|
|
14
19
|
module.exports = {
|
|
15
20
|
sendRequest: sendRequest,
|
|
16
21
|
sleep: sleep,
|
|
17
|
-
millisToSeconds: millisToSeconds
|
|
22
|
+
millisToSeconds: millisToSeconds,
|
|
23
|
+
timeOutError: timeOutError
|
|
18
24
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contrast/contrast",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.13",
|
|
4
4
|
"description": "Contrast Security's command line tool",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -23,7 +23,9 @@
|
|
|
23
23
|
"test": "jest --testPathIgnorePatterns=./test-integration/",
|
|
24
24
|
"test-int": "jest ./test-integration/",
|
|
25
25
|
"test-int-scan": "jest ./test-integration/scan",
|
|
26
|
-
"test-int-audit": "jest test-integration/audit
|
|
26
|
+
"test-int-audit": "jest test-integration/audit",
|
|
27
|
+
"test-int-audit-reports": "jest test-integration/audit/audit-language-reports.spec.js",
|
|
28
|
+
"test-int-audit-features": "jest test-integration/audit/auditFeatures/",
|
|
27
29
|
"format": "prettier --write \"**/*.{ts,tsx,js,json,md,yml}\" .eslintrc.*",
|
|
28
30
|
"check-format": "prettier --check \"**/*.{ts,tsx,js,json,md,yml}\" .eslintrc.*",
|
|
29
31
|
"coverage-local": "nyc --reporter=text mocha './test/**/*.spec.js'",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getHttpClient, handleResponseErrors } from '
|
|
1
|
+
import { getHttpClient, handleResponseErrors } from '../../utils/commonApi'
|
|
2
2
|
import {
|
|
3
3
|
ReportCompositeKey,
|
|
4
4
|
ReportList,
|
|
@@ -22,15 +22,17 @@ import {
|
|
|
22
22
|
ReportOutputModel
|
|
23
23
|
} from './models/reportOutputModel'
|
|
24
24
|
import {
|
|
25
|
+
CE_URL,
|
|
25
26
|
CRITICAL_COLOUR,
|
|
26
27
|
HIGH_COLOUR,
|
|
27
28
|
LOW_COLOUR,
|
|
28
29
|
MEDIUM_COLOUR,
|
|
29
30
|
NOTE_COLOUR
|
|
30
|
-
} from '
|
|
31
|
+
} from '../../constants/constants'
|
|
31
32
|
import Table from 'cli-table3'
|
|
33
|
+
import { ReportGuidanceModel } from './models/reportGuidanceModel'
|
|
32
34
|
|
|
33
|
-
export const
|
|
35
|
+
export const createSummaryMessageTop = (
|
|
34
36
|
numberOfVulnerableLibraries: number,
|
|
35
37
|
numberOfCves: number
|
|
36
38
|
) => {
|
|
@@ -41,6 +43,14 @@ export const createSummaryMessage = (
|
|
|
41
43
|
)
|
|
42
44
|
}
|
|
43
45
|
|
|
46
|
+
export const createSummaryMessageBottom = (
|
|
47
|
+
numberOfVulnerableLibraries: number
|
|
48
|
+
) => {
|
|
49
|
+
numberOfVulnerableLibraries === 1
|
|
50
|
+
? console.log(`Found 1 vulnerable library`)
|
|
51
|
+
: console.log(`Found ${numberOfVulnerableLibraries} vulnerable libraries`)
|
|
52
|
+
}
|
|
53
|
+
|
|
44
54
|
export const getReport = async (config: any, reportId: string) => {
|
|
45
55
|
const client = getHttpClient(config)
|
|
46
56
|
return client
|
|
@@ -86,7 +96,7 @@ export const printFormattedOutput = (
|
|
|
86
96
|
numberOfCves: number,
|
|
87
97
|
guidance: any
|
|
88
98
|
) => {
|
|
89
|
-
|
|
99
|
+
createSummaryMessageTop(numberOfVulnerableLibraries, numberOfCves)
|
|
90
100
|
console.log()
|
|
91
101
|
const report = new ReportList()
|
|
92
102
|
|
|
@@ -160,7 +170,11 @@ export const printFormattedOutput = (
|
|
|
160
170
|
numOfCVEs
|
|
161
171
|
)
|
|
162
172
|
|
|
163
|
-
const advice = gatherRemediationAdvice(
|
|
173
|
+
const advice = gatherRemediationAdvice(
|
|
174
|
+
guidance,
|
|
175
|
+
libraryName,
|
|
176
|
+
libraryVersion
|
|
177
|
+
)
|
|
164
178
|
|
|
165
179
|
const body = buildBody(reportModel.cveArray, advice)
|
|
166
180
|
|
|
@@ -168,7 +182,6 @@ export const printFormattedOutput = (
|
|
|
168
182
|
|
|
169
183
|
table.push(
|
|
170
184
|
reportOutputModel.body.issueMessage,
|
|
171
|
-
reportOutputModel.body.issueMessageCves,
|
|
172
185
|
reportOutputModel.body.adviceMessage
|
|
173
186
|
)
|
|
174
187
|
|
|
@@ -179,7 +192,7 @@ export const printFormattedOutput = (
|
|
|
179
192
|
console.log(table.toString() + '\n')
|
|
180
193
|
}
|
|
181
194
|
|
|
182
|
-
|
|
195
|
+
createSummaryMessageBottom(numberOfVulnerableLibraries)
|
|
183
196
|
const {
|
|
184
197
|
criticalMessage,
|
|
185
198
|
highMessage,
|
|
@@ -190,6 +203,15 @@ export const printFormattedOutput = (
|
|
|
190
203
|
console.log(
|
|
191
204
|
`${criticalMessage} | ${highMessage} | ${mediumMessage} | ${lowMessage} | ${noteMessage}`
|
|
192
205
|
)
|
|
206
|
+
|
|
207
|
+
if (config.host !== CE_URL) {
|
|
208
|
+
console.log(
|
|
209
|
+
'\n' + chalk.bold('View your full dependency tree in Contrast:')
|
|
210
|
+
)
|
|
211
|
+
console.log(
|
|
212
|
+
`${config.host}/Contrast/static/ng/index.html#/${config.organizationId}/applications/${config.applicationId}/libs/dependency-tree`
|
|
213
|
+
)
|
|
214
|
+
}
|
|
193
215
|
}
|
|
194
216
|
|
|
195
217
|
export function buildHeader(
|
|
@@ -203,18 +225,22 @@ export function buildHeader(
|
|
|
203
225
|
numOfCVEs > 1 ? 'vulnerabilities' : 'vulnerability'
|
|
204
226
|
const formattedHeaderNum = buildFormattedHeaderNum(contrastHeaderNum)
|
|
205
227
|
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
.
|
|
209
|
-
|
|
210
|
-
|
|
228
|
+
const headerColour = chalk.hex(highestSeverity.outputColour)
|
|
229
|
+
const headerNumAndSeverity = headerColour(
|
|
230
|
+
`${formattedHeaderNum} - [${highestSeverity.severity}]`
|
|
231
|
+
)
|
|
232
|
+
const libraryNameAndVersion = headerColour.bold(`${libraryName}-${version}`)
|
|
233
|
+
const vulnMessage = `${headerNumAndSeverity} ${libraryNameAndVersion}`
|
|
211
234
|
|
|
212
235
|
const introducesMessage = `introduces ${numOfCVEs} ${vulnerabilityPluralised}`
|
|
213
236
|
|
|
214
237
|
return new ReportOutputHeaderModel(vulnMessage, introducesMessage)
|
|
215
238
|
}
|
|
216
239
|
|
|
217
|
-
export function buildBody(
|
|
240
|
+
export function buildBody(
|
|
241
|
+
cveArray: ReportCVEModel[],
|
|
242
|
+
advice: ReportGuidanceModel
|
|
243
|
+
) {
|
|
218
244
|
const cveMessages: string[] = []
|
|
219
245
|
|
|
220
246
|
findCVESeveritiesAndOrderByHighestPriority(cveArray).forEach(
|
|
@@ -233,46 +259,40 @@ export function buildBody(cveArray: ReportCVEModel[], advice: any) {
|
|
|
233
259
|
|
|
234
260
|
const numAndSeverityType = getNumOfAndSeverityType(cveArray)
|
|
235
261
|
|
|
236
|
-
const issueMessage = [
|
|
237
|
-
|
|
238
|
-
|
|
262
|
+
const issueMessage = [
|
|
263
|
+
chalk.bold('Issue'),
|
|
264
|
+
':',
|
|
265
|
+
`${numAndSeverityType} ${cveMessages.join(', ')}`
|
|
266
|
+
]
|
|
239
267
|
|
|
240
268
|
//todo different advice based on remediationGuidance being available or now
|
|
241
269
|
// console.log(advice)
|
|
242
270
|
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
271
|
+
const minOrMax = advice.maximum ? advice.maximum : advice.minimum
|
|
272
|
+
const displayAdvice = minOrMax
|
|
273
|
+
? `Change to version ${chalk.bold(minOrMax)}`
|
|
274
|
+
: 'No recommendation is available according to our data. Upgrade to the latest stable is the best advice we can give.'
|
|
246
275
|
|
|
247
276
|
const adviceMessage = [chalk.bold('Advice'), ':', displayAdvice]
|
|
248
277
|
|
|
249
|
-
return new ReportOutputBodyModel(
|
|
250
|
-
issueMessage,
|
|
251
|
-
issueMessageCves,
|
|
252
|
-
adviceMessage
|
|
253
|
-
)
|
|
278
|
+
return new ReportOutputBodyModel(issueMessage, adviceMessage)
|
|
254
279
|
}
|
|
255
280
|
|
|
256
|
-
export function gatherRemediationAdvice(
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
281
|
+
export function gatherRemediationAdvice(
|
|
282
|
+
guidance: any,
|
|
283
|
+
libraryName: string,
|
|
284
|
+
libraryVersion: string
|
|
285
|
+
) {
|
|
286
|
+
const guidanceModel = new ReportGuidanceModel()
|
|
262
287
|
|
|
263
|
-
const data =
|
|
264
|
-
guidance[
|
|
265
|
-
reportModel.compositeKey.libraryName +
|
|
266
|
-
'@' +
|
|
267
|
-
reportModel.compositeKey.libraryVersion
|
|
268
|
-
]
|
|
288
|
+
const data = guidance[libraryName + '@' + libraryVersion]
|
|
269
289
|
|
|
270
290
|
if (data) {
|
|
271
|
-
|
|
272
|
-
|
|
291
|
+
guidanceModel.minimum = data.minUpgradeVersion
|
|
292
|
+
guidanceModel.maximum = data.maxUpgradeVersion
|
|
273
293
|
}
|
|
274
294
|
|
|
275
|
-
return
|
|
295
|
+
return guidanceModel
|
|
276
296
|
}
|
|
277
297
|
|
|
278
298
|
export function buildFormattedHeaderNum(contrastHeaderNum: number) {
|
|
@@ -285,11 +305,27 @@ export function getNumOfAndSeverityType(cveArray: ReportCVEModel[]) {
|
|
|
285
305
|
new SeverityCountModel()
|
|
286
306
|
)
|
|
287
307
|
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
const
|
|
291
|
-
const
|
|
292
|
-
|
|
308
|
+
const criticalNumCheck = critical > 0
|
|
309
|
+
|
|
310
|
+
const highNumCheck = high > 0
|
|
311
|
+
const highDivider = highNumCheck ? '|' : ''
|
|
312
|
+
|
|
313
|
+
const mediumNumCheck = medium > 0
|
|
314
|
+
const mediumDivider = mediumNumCheck ? '|' : ''
|
|
315
|
+
|
|
316
|
+
const lowNumCheck = low > 0
|
|
317
|
+
const lowDivider = lowNumCheck ? '|' : ''
|
|
318
|
+
|
|
319
|
+
const noteNumCheck = low > 0
|
|
320
|
+
const noteDivider = noteNumCheck ? '|' : ''
|
|
321
|
+
|
|
322
|
+
const criticalMessage = criticalNumCheck
|
|
323
|
+
? `${critical} Critical ${highDivider}`
|
|
324
|
+
: ''
|
|
325
|
+
const highMessage = highNumCheck ? `${high} High ${mediumDivider}` : ''
|
|
326
|
+
const mediumMessage = mediumNumCheck ? `${medium} Medium ${lowDivider}` : ''
|
|
327
|
+
const lowMessage = lowNumCheck ? `${low} Low ${noteDivider}` : ''
|
|
328
|
+
const noteMessage = noteNumCheck ? `${note} Note` : ''
|
|
293
329
|
|
|
294
330
|
//removes/trims whitespace to single spaces
|
|
295
331
|
return `${criticalMessage} ${highMessage} ${mediumMessage} ${lowMessage} ${noteMessage}`
|
|
File without changes
|
|
File without changes
|
|
@@ -20,16 +20,10 @@ export class ReportOutputHeaderModel {
|
|
|
20
20
|
|
|
21
21
|
export class ReportOutputBodyModel {
|
|
22
22
|
issueMessage: string[]
|
|
23
|
-
issueMessageCves: string[]
|
|
24
23
|
adviceMessage: string[]
|
|
25
24
|
|
|
26
|
-
constructor(
|
|
27
|
-
issueMessage: string[],
|
|
28
|
-
issueMessageCves: string[],
|
|
29
|
-
adviceMessage: string[]
|
|
30
|
-
) {
|
|
25
|
+
constructor(issueMessage: string[], adviceMessage: string[]) {
|
|
31
26
|
this.issueMessage = issueMessage
|
|
32
|
-
this.issueMessageCves = issueMessageCves
|
|
33
27
|
this.adviceMessage = adviceMessage
|
|
34
28
|
}
|
|
35
29
|
}
|
|
File without changes
|
|
@@ -4,6 +4,7 @@ export class SeverityCountModel {
|
|
|
4
4
|
medium!: number
|
|
5
5
|
low!: number
|
|
6
6
|
note!: number
|
|
7
|
+
total!: number
|
|
7
8
|
|
|
8
9
|
//needed as default to stop NaN when new object constructed
|
|
9
10
|
constructor() {
|
|
@@ -12,6 +13,7 @@ export class SeverityCountModel {
|
|
|
12
13
|
this.medium = 0
|
|
13
14
|
this.low = 0
|
|
14
15
|
this.note = 0
|
|
16
|
+
this.total = 0
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
get getTotal(): number {
|
|
@@ -8,7 +8,9 @@ import {
|
|
|
8
8
|
} from './utils/reportUtils'
|
|
9
9
|
import i18n from 'i18n'
|
|
10
10
|
import chalk from 'chalk'
|
|
11
|
-
import * as constants from '
|
|
11
|
+
import * as constants from '../../constants/constants'
|
|
12
|
+
import { SeverityCountModel } from './models/severityCountModel'
|
|
13
|
+
import * as common from '../../common/fail'
|
|
12
14
|
|
|
13
15
|
export function convertKeysToStandardFormat(config: any, guidance: any) {
|
|
14
16
|
let convertedGuidance = guidance
|
|
@@ -72,6 +74,7 @@ export function formatVulnerabilityOutput(
|
|
|
72
74
|
String(0)
|
|
73
75
|
)
|
|
74
76
|
)
|
|
77
|
+
return [false, 0, [new SeverityCountModel()]]
|
|
75
78
|
} else {
|
|
76
79
|
let numberOfCves = 0
|
|
77
80
|
vulnerableLibraries.forEach(lib => (numberOfCves += lib.cveArray.length))
|
|
@@ -83,12 +86,13 @@ export function formatVulnerabilityOutput(
|
|
|
83
86
|
numberOfCves,
|
|
84
87
|
guidance
|
|
85
88
|
)
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
let severityCount = new SeverityCountModel()
|
|
90
|
+
severityCount = severityCountAllLibraries(
|
|
91
|
+
vulnerableLibraries,
|
|
92
|
+
severityCount
|
|
93
|
+
)
|
|
94
|
+
severityCount.total = severityCount.getTotal
|
|
95
|
+
return [hasSomeVulnerabilitiesReported, numberOfCves, severityCount]
|
|
92
96
|
}
|
|
93
97
|
}
|
|
94
98
|
|
|
@@ -97,8 +101,7 @@ export async function vulnerabilityReportV2(config: any, reportId: string) {
|
|
|
97
101
|
const reportResponse = await getReport(config, reportId)
|
|
98
102
|
|
|
99
103
|
if (reportResponse !== undefined) {
|
|
100
|
-
|
|
101
|
-
formatVulnerabilityOutput(
|
|
104
|
+
let output = formatVulnerabilityOutput(
|
|
102
105
|
reportResponse.vulnerabilities,
|
|
103
106
|
config.applicationId,
|
|
104
107
|
config,
|
|
@@ -106,5 +109,9 @@ export async function vulnerabilityReportV2(config: any, reportId: string) {
|
|
|
106
109
|
? reportResponse.remediationGuidance
|
|
107
110
|
: {}
|
|
108
111
|
)
|
|
112
|
+
|
|
113
|
+
if (config.fail) {
|
|
114
|
+
common.processFail(config, output[2])
|
|
115
|
+
}
|
|
109
116
|
}
|
|
110
117
|
}
|
|
@@ -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,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
MEDIUM_PRIORITY,
|
|
16
16
|
NOTE_COLOUR,
|
|
17
17
|
NOTE_PRIORITY
|
|
18
|
-
} from '
|
|
18
|
+
} from '../../../constants/constants'
|
|
19
19
|
import { orderBy } from 'lodash'
|
|
20
20
|
import { SeverityCountModel } from '../models/severityCountModel'
|
|
21
21
|
import { ReportModelStructure } from '../models/reportListModel'
|
|
@@ -75,9 +75,9 @@ export function convertGenericToTypedLibraryVulns(libraries: any) {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
export function severityCountAllLibraries(
|
|
78
|
-
vulnerableLibraries: ReportLibraryModel[]
|
|
78
|
+
vulnerableLibraries: ReportLibraryModel[],
|
|
79
|
+
severityCount: SeverityCountModel
|
|
79
80
|
) {
|
|
80
|
-
const severityCount = new SeverityCountModel()
|
|
81
81
|
vulnerableLibraries.forEach(lib =>
|
|
82
82
|
severityCountAllCVEs(lib.cveArray, severityCount)
|
|
83
83
|
)
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import paramHandler from '../../utils/paramsUtil/paramHandler'
|
|
2
2
|
import constants from '../../constants'
|
|
3
|
-
import
|
|
3
|
+
import { getCommandLineArgsCustom } from '../../utils/parsedCLIOptions'
|
|
4
|
+
import { ContrastConf } from '../../utils/getConfig'
|
|
4
5
|
|
|
5
|
-
export const getAuditConfig = (
|
|
6
|
-
|
|
6
|
+
export const getAuditConfig = async (
|
|
7
|
+
contrastConf: ContrastConf,
|
|
8
|
+
command: string,
|
|
9
|
+
argv: string[]
|
|
10
|
+
): Promise<{ [key: string]: string }> => {
|
|
11
|
+
const auditParameters = await getCommandLineArgsCustom(
|
|
12
|
+
contrastConf,
|
|
13
|
+
command,
|
|
7
14
|
argv,
|
|
8
15
|
constants.commandLineDefinitions.auditOptionDefinitions
|
|
9
16
|
)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import commandLineUsage from 'command-line-usage'
|
|
2
2
|
import i18n from 'i18n'
|
|
3
3
|
import constants from '../../constants'
|
|
4
|
+
import { commonHelpLinks } from '../../common/commonHelp'
|
|
4
5
|
|
|
5
6
|
const auditUsageGuide = commandLineUsage([
|
|
6
7
|
{
|
|
@@ -48,7 +49,8 @@ const auditUsageGuide = commandLineUsage([
|
|
|
48
49
|
'app-groups',
|
|
49
50
|
'metadata'
|
|
50
51
|
]
|
|
51
|
-
}
|
|
52
|
+
},
|
|
53
|
+
commonHelpLinks()
|
|
52
54
|
])
|
|
53
55
|
|
|
54
56
|
export { auditUsageGuide }
|