@contrast/contrast 1.0.14 → 1.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/audit/languageAnalysisEngine/sendSnapshot.js +2 -2
- package/dist/audit/report/commonReportingFunctions.js +1 -19
- package/dist/audit/save.js +7 -2
- package/dist/{constants.js → cliConstants.js} +70 -31
- package/dist/commands/audit/auditConfig.js +2 -2
- package/dist/commands/audit/help.js +5 -3
- package/dist/commands/auth/auth.js +1 -1
- package/dist/commands/config/config.js +1 -1
- package/dist/commands/scan/processScan.js +0 -6
- package/dist/commands/scan/sca/scaAnalysis.js +64 -33
- package/dist/common/HTTPClient.js +25 -4
- package/dist/constants/constants.js +10 -2
- package/dist/constants/locales.js +7 -30
- package/dist/index.js +5 -5
- package/dist/sbom/generateSbom.js +18 -1
- package/dist/scaAnalysis/common/auditReport.js +3 -2
- package/dist/scaAnalysis/common/scaParserForGoAndJava.js +1 -1
- package/dist/scaAnalysis/common/scaServicesUpload.js +14 -7
- package/dist/scaAnalysis/javascript/scaServiceParser.js +2 -2
- package/dist/scaAnalysis/php/phpNewServicesMapper.js +3 -3
- package/dist/scaAnalysis/python/analysis.js +1 -1
- package/dist/scaAnalysis/repoMode/gradleParser.js +75 -0
- package/dist/scaAnalysis/repoMode/index.js +21 -0
- package/dist/scaAnalysis/repoMode/mavenParser.js +76 -0
- package/dist/scaAnalysis/ruby/analysis.js +4 -4
- package/dist/scan/help.js +1 -1
- package/dist/scan/scanConfig.js +1 -1
- package/dist/utils/commonApi.js +1 -0
- package/dist/utils/settingsHelper.js +24 -0
- package/package.json +2 -1
- package/src/audit/languageAnalysisEngine/sendSnapshot.js +2 -6
- package/src/audit/report/commonReportingFunctions.js +1 -23
- package/src/audit/save.js +14 -6
- package/src/{constants.js → cliConstants.js} +79 -35
- package/src/commands/audit/auditConfig.ts +1 -1
- package/src/commands/audit/help.ts +4 -2
- package/src/commands/auth/auth.js +1 -1
- package/src/commands/config/config.js +1 -1
- package/src/commands/scan/processScan.js +0 -8
- package/src/commands/scan/sca/scaAnalysis.js +85 -54
- package/src/common/HTTPClient.js +29 -4
- package/src/constants/constants.js +12 -2
- package/src/constants/locales.js +9 -44
- package/src/index.ts +1 -1
- package/src/sbom/generateSbom.ts +20 -0
- package/src/scaAnalysis/common/auditReport.js +3 -4
- package/src/scaAnalysis/common/scaParserForGoAndJava.js +1 -1
- package/src/scaAnalysis/common/scaServicesUpload.js +15 -7
- package/src/scaAnalysis/javascript/scaServiceParser.js +8 -2
- package/src/scaAnalysis/php/phpNewServicesMapper.js +3 -3
- package/src/scaAnalysis/python/analysis.js +1 -1
- package/src/scaAnalysis/repoMode/gradleParser.js +88 -0
- package/src/scaAnalysis/repoMode/index.js +21 -0
- package/src/scaAnalysis/repoMode/mavenParser.js +89 -0
- package/src/scaAnalysis/ruby/analysis.js +4 -4
- package/src/scan/help.js +1 -1
- package/src/scan/scanConfig.js +1 -1
- package/src/utils/commonApi.js +1 -0
- package/src/utils/settingsHelper.js +26 -0
|
@@ -28,7 +28,7 @@ const getTimeout = config => {
|
|
|
28
28
|
return 300;
|
|
29
29
|
}
|
|
30
30
|
};
|
|
31
|
-
const
|
|
31
|
+
const pollForSnapshotCompletion = async (config, snapshotId, reportSpinner) => {
|
|
32
32
|
const client = commonApi.getHttpClient(config);
|
|
33
33
|
const startTime = performance.now();
|
|
34
34
|
const timeout = getTimeout(config);
|
|
@@ -63,5 +63,5 @@ const pollForSnapshotCompletition = async (config, snapshotId, reportSpinner) =>
|
|
|
63
63
|
}
|
|
64
64
|
};
|
|
65
65
|
module.exports = {
|
|
66
|
-
|
|
66
|
+
pollForSnapshotCompletion
|
|
67
67
|
};
|
|
@@ -132,13 +132,7 @@ function buildBody(cveArray, advice) {
|
|
|
132
132
|
function getIssueRow(cveArray) {
|
|
133
133
|
orderByHighestPriority(cveArray);
|
|
134
134
|
const cveMessagesList = getIssueCveMsgList(cveArray);
|
|
135
|
-
|
|
136
|
-
const numAndSeverityTypeDesc = getNumOfAndSeverityType(cveNumbers);
|
|
137
|
-
return [
|
|
138
|
-
chalk.bold('Issue'),
|
|
139
|
-
':',
|
|
140
|
-
`${numAndSeverityTypeDesc} ${cveMessagesList.join(', ')}`
|
|
141
|
-
];
|
|
135
|
+
return [chalk.bold('Issue'), ':', `${cveMessagesList.join(', ')}`];
|
|
142
136
|
}
|
|
143
137
|
function gatherRemediationAdvice(guidance, libraryName, libraryVersion) {
|
|
144
138
|
const guidanceModel = new ReportGuidanceModel();
|
|
@@ -152,17 +146,6 @@ function gatherRemediationAdvice(guidance, libraryName, libraryVersion) {
|
|
|
152
146
|
function buildFormattedHeaderNum(contrastHeaderNum) {
|
|
153
147
|
return `CONTRAST-${contrastHeaderNum.toString().padStart(3, '0')}`;
|
|
154
148
|
}
|
|
155
|
-
function getNumOfAndSeverityType(cveNumbers) {
|
|
156
|
-
const { critical, high, medium, low, note } = cveNumbers;
|
|
157
|
-
const criticalMsg = critical > 0 ? `${critical} Critical | ` : '';
|
|
158
|
-
const highMsg = high > 0 ? `${high} High | ` : '';
|
|
159
|
-
const mediumMsg = medium > 0 ? `${medium} Medium | ` : '';
|
|
160
|
-
const lowMsg = low > 0 ? `${low} Low | ` : '';
|
|
161
|
-
const noteMsg = note > 0 ? `${note} Note` : '';
|
|
162
|
-
return `${criticalMsg} ${highMsg} ${mediumMsg} ${lowMsg} ${noteMsg}`
|
|
163
|
-
.replace(/\s+/g, ' ')
|
|
164
|
-
.trim();
|
|
165
|
-
}
|
|
166
149
|
const buildFooter = reportModelStructure => {
|
|
167
150
|
const { critical, high, medium, low, note } = countVulnerableLibrariesBySeverity(reportModelStructure);
|
|
168
151
|
const criticalMessage = chalk
|
|
@@ -257,7 +240,6 @@ module.exports = {
|
|
|
257
240
|
getIssueRow,
|
|
258
241
|
gatherRemediationAdvice,
|
|
259
242
|
buildFormattedHeaderNum,
|
|
260
|
-
getNumOfAndSeverityType,
|
|
261
243
|
getIssueCveMsgList,
|
|
262
244
|
getSeverityCounts,
|
|
263
245
|
printNoVulnFoundMsg,
|
package/dist/audit/save.js
CHANGED
|
@@ -5,7 +5,7 @@ const chalk = require('chalk');
|
|
|
5
5
|
const save = require('../commands/audit/saveFile');
|
|
6
6
|
const sbom = require('../sbom/generateSbom');
|
|
7
7
|
const { SBOM_CYCLONE_DX_FILE, SBOM_SPDX_FILE } = require('../constants/constants');
|
|
8
|
-
async function auditSave(config) {
|
|
8
|
+
async function auditSave(config, reportId) {
|
|
9
9
|
let fileFormat;
|
|
10
10
|
switch (config.save) {
|
|
11
11
|
case null:
|
|
@@ -19,7 +19,12 @@ async function auditSave(config) {
|
|
|
19
19
|
break;
|
|
20
20
|
}
|
|
21
21
|
if (fileFormat) {
|
|
22
|
-
|
|
22
|
+
if (config.experimental) {
|
|
23
|
+
save.saveFile(config, fileFormat, await sbom.generateSCASbom(config, fileFormat, reportId));
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
save.saveFile(config, fileFormat, await sbom.generateSbom(config, fileFormat));
|
|
27
|
+
}
|
|
23
28
|
const filename = `${config.applicationId}-sbom-${fileFormat}.json`;
|
|
24
29
|
if (fs.existsSync(filename)) {
|
|
25
30
|
console.log(i18n.__('auditSBOMSaveSuccess') + ` - ${filename}`);
|
|
@@ -10,7 +10,46 @@ i18n.configure({
|
|
|
10
10
|
},
|
|
11
11
|
defaultLocale: 'en'
|
|
12
12
|
});
|
|
13
|
+
const sharedOptionDefinitions = [
|
|
14
|
+
{
|
|
15
|
+
name: 'proxy',
|
|
16
|
+
description: '{bold ' +
|
|
17
|
+
i18n.__('constantsOptional') +
|
|
18
|
+
'}: ' +
|
|
19
|
+
i18n.__('constantsProxyServer')
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: 'key',
|
|
23
|
+
description: '{bold ' +
|
|
24
|
+
i18n.__('constantsOptional') +
|
|
25
|
+
'}: ' +
|
|
26
|
+
i18n.__('constantsProxyKey')
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'cacert',
|
|
30
|
+
description: '{bold ' +
|
|
31
|
+
i18n.__('constantsOptional') +
|
|
32
|
+
'}: ' +
|
|
33
|
+
i18n.__('constantsProxyCaCert')
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: 'cert',
|
|
37
|
+
description: '{bold ' +
|
|
38
|
+
i18n.__('constantsOptional') +
|
|
39
|
+
'}: ' +
|
|
40
|
+
i18n.__('constantsProxyCert')
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'ignore-cert-errors',
|
|
44
|
+
type: Boolean,
|
|
45
|
+
description: '{bold ' +
|
|
46
|
+
i18n.__('constantsOptional') +
|
|
47
|
+
'}:' +
|
|
48
|
+
i18n.__('constantsIgnoreCertErrors')
|
|
49
|
+
}
|
|
50
|
+
];
|
|
13
51
|
const scanOptionDefinitions = [
|
|
52
|
+
...sharedOptionDefinitions,
|
|
14
53
|
{
|
|
15
54
|
name: 'name',
|
|
16
55
|
alias: 'n',
|
|
@@ -88,13 +127,6 @@ const scanOptionDefinitions = [
|
|
|
88
127
|
'}: ' +
|
|
89
128
|
i18n.__('constantsHostId')
|
|
90
129
|
},
|
|
91
|
-
{
|
|
92
|
-
name: 'proxy',
|
|
93
|
-
description: '{bold ' +
|
|
94
|
-
i18n.__('constantsOptional') +
|
|
95
|
-
'}: ' +
|
|
96
|
-
i18n.__('constantsProxyServer')
|
|
97
|
-
},
|
|
98
130
|
{
|
|
99
131
|
name: 'fail',
|
|
100
132
|
type: Boolean,
|
|
@@ -117,15 +149,7 @@ const scanOptionDefinitions = [
|
|
|
117
149
|
description: '{bold ' +
|
|
118
150
|
i18n.__('constantsOptional') +
|
|
119
151
|
'}: ' +
|
|
120
|
-
i18n.__('
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
name: 'ignore-cert-errors',
|
|
124
|
-
type: Boolean,
|
|
125
|
-
description: '{bold ' +
|
|
126
|
-
i18n.__('constantsOptional') +
|
|
127
|
-
'}:' +
|
|
128
|
-
i18n.__('constantsIgnoreCertErrors')
|
|
152
|
+
i18n.__('constantsDoNotWaitForScan')
|
|
129
153
|
},
|
|
130
154
|
{
|
|
131
155
|
name: 'verbose',
|
|
@@ -190,6 +214,7 @@ const configOptionDefinitions = [
|
|
|
190
214
|
}
|
|
191
215
|
];
|
|
192
216
|
const auditOptionDefinitions = [
|
|
217
|
+
...sharedOptionDefinitions,
|
|
193
218
|
{
|
|
194
219
|
name: 'application-id',
|
|
195
220
|
description: '{bold ' +
|
|
@@ -299,21 +324,6 @@ const auditOptionDefinitions = [
|
|
|
299
324
|
'}: ' +
|
|
300
325
|
i18n.__('constantsHostId')
|
|
301
326
|
},
|
|
302
|
-
{
|
|
303
|
-
name: 'proxy',
|
|
304
|
-
description: '{bold ' +
|
|
305
|
-
i18n.__('constantsOptional') +
|
|
306
|
-
'}: ' +
|
|
307
|
-
i18n.__('constantsProxyServer')
|
|
308
|
-
},
|
|
309
|
-
{
|
|
310
|
-
name: 'ignore-cert-errors',
|
|
311
|
-
type: Boolean,
|
|
312
|
-
description: '{bold ' +
|
|
313
|
-
i18n.__('constantsOptional') +
|
|
314
|
-
'}:' +
|
|
315
|
-
i18n.__('constantsIgnoreCertErrors')
|
|
316
|
-
},
|
|
317
327
|
{
|
|
318
328
|
name: 'save',
|
|
319
329
|
alias: 's',
|
|
@@ -341,6 +351,35 @@ const auditOptionDefinitions = [
|
|
|
341
351
|
name: 'help',
|
|
342
352
|
alias: 'h',
|
|
343
353
|
type: Boolean
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
name: 'debug',
|
|
357
|
+
alias: 'd',
|
|
358
|
+
type: Boolean
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
name: 'verbose',
|
|
362
|
+
alias: 'v',
|
|
363
|
+
type: Boolean,
|
|
364
|
+
description: '{bold ' +
|
|
365
|
+
i18n.__('constantsOptional') +
|
|
366
|
+
'}:' +
|
|
367
|
+
i18n.__('scanOptionsVerboseSummary')
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
name: 'track',
|
|
371
|
+
type: Boolean,
|
|
372
|
+
description: '{bold ' +
|
|
373
|
+
i18n.__('constantsOptional') +
|
|
374
|
+
'}:' +
|
|
375
|
+
i18n.__('auditOptionsTrackSummary')
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
name: 'branch',
|
|
379
|
+
description: '{bold ' +
|
|
380
|
+
i18n.__('constantsOptional') +
|
|
381
|
+
'}:' +
|
|
382
|
+
i18n.__('auditOptionsBranchSummary')
|
|
344
383
|
}
|
|
345
384
|
];
|
|
346
385
|
const mainUsageGuide = commandLineUsage([
|
|
@@ -5,10 +5,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.getAuditConfig = void 0;
|
|
7
7
|
const paramHandler_1 = __importDefault(require("../../utils/paramsUtil/paramHandler"));
|
|
8
|
-
const
|
|
8
|
+
const cliConstants_1 = __importDefault(require("../../cliConstants"));
|
|
9
9
|
const parsedCLIOptions_1 = require("../../utils/parsedCLIOptions");
|
|
10
10
|
const getAuditConfig = async (contrastConf, command, argv) => {
|
|
11
|
-
const auditParameters = await (0, parsedCLIOptions_1.getCommandLineArgsCustom)(contrastConf, command, argv,
|
|
11
|
+
const auditParameters = await (0, parsedCLIOptions_1.getCommandLineArgsCustom)(contrastConf, command, argv, cliConstants_1.default.commandLineDefinitions.auditOptionDefinitions);
|
|
12
12
|
const paramsAuth = paramHandler_1.default.getAuth(auditParameters);
|
|
13
13
|
return { ...paramsAuth, ...auditParameters };
|
|
14
14
|
};
|
|
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.auditUsageGuide = void 0;
|
|
7
7
|
const command_line_usage_1 = __importDefault(require("command-line-usage"));
|
|
8
8
|
const i18n_1 = __importDefault(require("i18n"));
|
|
9
|
-
const
|
|
9
|
+
const cliConstants_1 = __importDefault(require("../../cliConstants"));
|
|
10
10
|
const commonHelp_1 = require("../../common/commonHelp");
|
|
11
11
|
const auditUsageGuide = (0, command_line_usage_1.default)([
|
|
12
12
|
{
|
|
@@ -30,7 +30,7 @@ const auditUsageGuide = (0, command_line_usage_1.default)([
|
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
header: i18n_1.default.__('constantsAuditOptions'),
|
|
33
|
-
optionList:
|
|
33
|
+
optionList: cliConstants_1.default.commandLineDefinitions.auditOptionDefinitions,
|
|
34
34
|
hide: [
|
|
35
35
|
'application-id',
|
|
36
36
|
'application-name',
|
|
@@ -52,7 +52,9 @@ const auditUsageGuide = (0, command_line_usage_1.default)([
|
|
|
52
52
|
'language',
|
|
53
53
|
'experimental',
|
|
54
54
|
'app-groups',
|
|
55
|
-
'metadata'
|
|
55
|
+
'metadata',
|
|
56
|
+
'track',
|
|
57
|
+
'branch'
|
|
56
58
|
]
|
|
57
59
|
},
|
|
58
60
|
(0, commonHelp_1.commonHelpLinks)()
|
|
@@ -8,7 +8,7 @@ const i18n = require('i18n');
|
|
|
8
8
|
const { returnOra, startSpinner, failSpinner, succeedSpinner } = require('../../utils/oraWrapper');
|
|
9
9
|
const { TIMEOUT, AUTH_UI_URL } = require('../../constants/constants');
|
|
10
10
|
const parsedCLIOptions = require('../../utils/parsedCLIOptions');
|
|
11
|
-
const constants = require('../../
|
|
11
|
+
const constants = require('../../cliConstants');
|
|
12
12
|
const commandLineUsage = require('command-line-usage');
|
|
13
13
|
const processAuth = async (argv, config) => {
|
|
14
14
|
let authParams = await parsedCLIOptions.getCommandLineArgsCustom(config, 'auth', argv, constants.commandLineDefinitions.authOptionDefinitions);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const parsedCLIOptions = require('../../utils/parsedCLIOptions');
|
|
3
|
-
const constants = require('../../
|
|
3
|
+
const constants = require('../../cliConstants');
|
|
4
4
|
const commandLineUsage = require('command-line-usage');
|
|
5
5
|
const i18n = require('i18n');
|
|
6
6
|
const processConfig = async (argv, config) => {
|
|
@@ -4,18 +4,12 @@ const { startScan } = require('../../scan/scanController');
|
|
|
4
4
|
const { saveScanFile } = require('../../utils/saveFile');
|
|
5
5
|
const { ScanResultsModel } = require('../../scan/models/scanResultsModel');
|
|
6
6
|
const { formatScanOutput } = require('../../scan/formatScanOutput');
|
|
7
|
-
const { processSca } = require('./sca/scaAnalysis');
|
|
8
7
|
const common = require('../../common/fail');
|
|
9
8
|
const { sendTelemetryConfigAsObject } = require('../../telemetry/telemetry');
|
|
10
9
|
const chalk = require('chalk');
|
|
11
|
-
const generalAPI = require('../../utils/generalAPI');
|
|
12
10
|
const processScan = async (contrastConf, argv) => {
|
|
13
11
|
let config = await scanConfig.getScanConfig(contrastConf, 'scan', argv);
|
|
14
12
|
let output = undefined;
|
|
15
|
-
config.mode = await generalAPI.getMode(config);
|
|
16
|
-
if (config.experimental) {
|
|
17
|
-
await processSca(config, argv);
|
|
18
|
-
}
|
|
19
13
|
let scanResults = new ScanResultsModel(await startScan(config));
|
|
20
14
|
await sendTelemetryConfigAsObject(config, 'scan', argv, 'SUCCESS', scanResults.scanDetail.language);
|
|
21
15
|
if (scanResults.scanResultsInstances !== undefined) {
|
|
@@ -1,26 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
const { supportedLanguages: { JAVA, GO, PYTHON, RUBY, JAVASCRIPT, NODE, PHP, DOTNET } } = require('../../../constants/constants');
|
|
3
|
+
const { pollForSnapshotCompletion } = require('../../../audit/languageAnalysisEngine/sendSnapshot');
|
|
4
|
+
const { returnOra, startSpinner, succeedSpinner } = require('../../../utils/oraWrapper');
|
|
5
|
+
const { vulnerabilityReportV2 } = require('../../../audit/report/reportingFeature');
|
|
2
6
|
const autoDetection = require('../../../scan/autoDetection');
|
|
3
|
-
const javaAnalysis = require('../../../scaAnalysis/java');
|
|
4
7
|
const treeUpload = require('../../../scaAnalysis/common/treeUpload');
|
|
5
8
|
const auditController = require('../../audit/auditController');
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const phpAnalysis = require('../../../scaAnalysis/php/index');
|
|
9
|
-
const { rubyAnalysis } = require('../../../scaAnalysis/ruby');
|
|
10
|
-
const { pythonAnalysis } = require('../../../scaAnalysis/python');
|
|
11
|
-
const javascriptAnalysis = require('../../../scaAnalysis/javascript');
|
|
12
|
-
const { pollForSnapshotCompletition } = require('../../../audit/languageAnalysisEngine/sendSnapshot');
|
|
13
|
-
const { returnOra, startSpinner, succeedSpinner } = require('../../../utils/oraWrapper');
|
|
9
|
+
const rootFile = require('../../../audit/languageAnalysisEngine/getProjectRootFilenames');
|
|
10
|
+
const path = require('path');
|
|
14
11
|
const i18n = require('i18n');
|
|
15
|
-
const { vulnerabilityReportV2 } = require('../../../audit/report/reportingFeature');
|
|
16
12
|
const auditSave = require('../../../audit/save');
|
|
17
|
-
const { dotNetAnalysis } = require('../../../scaAnalysis/dotnet');
|
|
18
13
|
const { auditUsageGuide } = require('../../audit/help');
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
14
|
+
const { buildRepo } = require('../../../scaAnalysis/repoMode/index');
|
|
15
|
+
const { dotNetAnalysis } = require('../../../scaAnalysis/dotnet');
|
|
16
|
+
const { goAnalysis } = require('../../../scaAnalysis/go/goAnalysis');
|
|
17
|
+
const { phpAnalysis } = require('../../../scaAnalysis/php/index');
|
|
18
|
+
const { rubyAnalysis } = require('../../../scaAnalysis/ruby');
|
|
19
|
+
const { pythonAnalysis } = require('../../../scaAnalysis/python');
|
|
20
|
+
const javaAnalysis = require('../../../scaAnalysis/java');
|
|
21
|
+
const jsAnalysis = require('../../../scaAnalysis/javascript');
|
|
22
|
+
const auditReport = require('../../../scaAnalysis/common/auditReport');
|
|
23
|
+
const scaUpload = require('../../../scaAnalysis/common/scaServicesUpload');
|
|
24
|
+
const settingsHelper = require('../../../utils/settingsHelper');
|
|
25
|
+
const chalk = require('chalk');
|
|
22
26
|
const processSca = async (config) => {
|
|
23
|
-
config
|
|
27
|
+
config = await settingsHelper.getSettings(config);
|
|
24
28
|
const startTime = performance.now();
|
|
25
29
|
let filesFound;
|
|
26
30
|
if (config.help) {
|
|
@@ -37,6 +41,15 @@ const processSca = async (config) => {
|
|
|
37
41
|
if (filesFound.length > 1 && pathWithFile) {
|
|
38
42
|
filesFound = filesFound.filter(i => Object.values(i)[0].includes(path.basename(config.fileName)));
|
|
39
43
|
}
|
|
44
|
+
if (config.mode === 'repo') {
|
|
45
|
+
try {
|
|
46
|
+
return buildRepo(config, filesFound[0]);
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
console.log('Unable to build in repository mode. Check your project file');
|
|
50
|
+
process.exit(0);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
40
53
|
let messageToSend = undefined;
|
|
41
54
|
if (filesFound.length === 1) {
|
|
42
55
|
switch (Object.keys(filesFound[0])[0]) {
|
|
@@ -45,7 +58,7 @@ const processSca = async (config) => {
|
|
|
45
58
|
config.language = JAVA;
|
|
46
59
|
break;
|
|
47
60
|
case JAVASCRIPT:
|
|
48
|
-
messageToSend = await
|
|
61
|
+
messageToSend = await jsAnalysis.jsAnalysis(config, filesFound[0]);
|
|
49
62
|
config.language = NODE;
|
|
50
63
|
break;
|
|
51
64
|
case PYTHON:
|
|
@@ -57,11 +70,11 @@ const processSca = async (config) => {
|
|
|
57
70
|
config.language = RUBY;
|
|
58
71
|
break;
|
|
59
72
|
case PHP:
|
|
60
|
-
messageToSend = phpAnalysis
|
|
73
|
+
messageToSend = phpAnalysis(config, filesFound[0]);
|
|
61
74
|
config.language = PHP;
|
|
62
75
|
break;
|
|
63
76
|
case GO:
|
|
64
|
-
messageToSend = goAnalysis
|
|
77
|
+
messageToSend = goAnalysis(config, filesFound[0]);
|
|
65
78
|
config.language = GO;
|
|
66
79
|
break;
|
|
67
80
|
case DOTNET:
|
|
@@ -75,19 +88,35 @@ const processSca = async (config) => {
|
|
|
75
88
|
if (!config.applicationId) {
|
|
76
89
|
config.applicationId = await auditController.dealWithNoAppId(config);
|
|
77
90
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
91
|
+
if (config.experimental) {
|
|
92
|
+
console.log('');
|
|
93
|
+
const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'));
|
|
94
|
+
startSpinner(reportSpinner);
|
|
95
|
+
const [reports, reportId] = await scaUpload.scaTreeUpload(messageToSend, config);
|
|
96
|
+
auditReport.processAuditReport(config, reports[0]);
|
|
97
|
+
succeedSpinner(reportSpinner, i18n.__('auditSCAAnalysisComplete'));
|
|
98
|
+
if (config.save !== undefined) {
|
|
99
|
+
await auditSave.auditSave(config, reportId);
|
|
100
|
+
}
|
|
101
|
+
const endTime = performance.now() - startTime;
|
|
102
|
+
const scanDurationMs = endTime - startTime;
|
|
103
|
+
console.log(`----- completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
console.log('');
|
|
107
|
+
const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'));
|
|
108
|
+
startSpinner(reportSpinner);
|
|
109
|
+
const snapshotResponse = await treeUpload.commonSendSnapShot(messageToSend, config);
|
|
110
|
+
await pollForSnapshotCompletion(config, snapshotResponse.id, reportSpinner);
|
|
111
|
+
succeedSpinner(reportSpinner, i18n.__('auditSCAAnalysisComplete'));
|
|
112
|
+
await vulnerabilityReportV2(config, snapshotResponse.id);
|
|
113
|
+
if (config.save !== undefined) {
|
|
114
|
+
await auditSave.auditSave(config);
|
|
115
|
+
}
|
|
116
|
+
const endTime = performance.now() - startTime;
|
|
117
|
+
const scanDurationMs = endTime - startTime;
|
|
118
|
+
console.log(`----- completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`);
|
|
87
119
|
}
|
|
88
|
-
const endTime = performance.now() - startTime;
|
|
89
|
-
const scanDurationMs = endTime - startTime;
|
|
90
|
-
console.log(`----- completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`);
|
|
91
120
|
}
|
|
92
121
|
else {
|
|
93
122
|
if (filesFound.length === 0) {
|
|
@@ -96,9 +125,11 @@ const processSca = async (config) => {
|
|
|
96
125
|
throw new Error();
|
|
97
126
|
}
|
|
98
127
|
else {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
128
|
+
console.log(chalk.bold(`\nMultiple language files detected \n`));
|
|
129
|
+
filesFound.forEach(file => {
|
|
130
|
+
console.log(`${Object.keys(file)[0]} : `, Object.values(file)[0]);
|
|
131
|
+
});
|
|
132
|
+
throw new Error(`Please use --file to audit one language only. \nExample: contrast audit --file package-lock.json`);
|
|
102
133
|
}
|
|
103
134
|
}
|
|
104
135
|
};
|
|
@@ -34,7 +34,7 @@ HTTPClient.prototype.maybeAddCertsToRequest = function (config) {
|
|
|
34
34
|
if (caCertFilePath) {
|
|
35
35
|
const caFileContent = fs.readFileSync(caCertFilePath);
|
|
36
36
|
if (caFileContent instanceof Error) {
|
|
37
|
-
throw new Error(`Unable to read CA from
|
|
37
|
+
throw new Error(`Unable to read CA from ${caCertFilePath}, msg: ${caFileContent.message}`);
|
|
38
38
|
}
|
|
39
39
|
this.requestOptions.ca = caFileContent;
|
|
40
40
|
}
|
|
@@ -185,6 +185,12 @@ HTTPClient.prototype.scaServiceReportStatus = function scaServiceReport(config,
|
|
|
185
185
|
options.url = url;
|
|
186
186
|
return requestUtils.sendRequest({ method: 'get', options });
|
|
187
187
|
};
|
|
188
|
+
HTTPClient.prototype.scaServiceIngests = function scaServiceIngests(config) {
|
|
189
|
+
const options = _.cloneDeep(this.requestOptions);
|
|
190
|
+
let url = createScaServiceIngestsURL(config);
|
|
191
|
+
options.url = url;
|
|
192
|
+
return requestUtils.sendRequest({ method: 'get', options });
|
|
193
|
+
};
|
|
188
194
|
HTTPClient.prototype.getReportById = function getReportById(config, reportId) {
|
|
189
195
|
const options = _.cloneDeep(this.requestOptions);
|
|
190
196
|
if (config.ignoreDev) {
|
|
@@ -266,6 +272,11 @@ HTTPClient.prototype.getSbom = function getSbom(config, type) {
|
|
|
266
272
|
options.url = createSbomUrl(config, type);
|
|
267
273
|
return requestUtils.sendRequest({ method: 'get', options });
|
|
268
274
|
};
|
|
275
|
+
HTTPClient.prototype.getSCASbom = function getSbom(config, type, reportId) {
|
|
276
|
+
const options = _.cloneDeep(this.requestOptions);
|
|
277
|
+
options.url = createSCASbomUrl(config, type, reportId);
|
|
278
|
+
return requestUtils.sendRequest({ method: 'get', options });
|
|
279
|
+
};
|
|
269
280
|
HTTPClient.prototype.getLatestVersion = function getLatestVersion() {
|
|
270
281
|
const options = _.cloneDeep(this.requestOptions);
|
|
271
282
|
options.url =
|
|
@@ -321,13 +332,20 @@ function createSnapshotURL(config) {
|
|
|
321
332
|
return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/${config.applicationId}/snapshots`;
|
|
322
333
|
}
|
|
323
334
|
function createScaServiceReportURL(config, reportId) {
|
|
324
|
-
|
|
335
|
+
let baseUrl = `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/libraries/applications/${config.applicationId}/reports/${reportId}`;
|
|
336
|
+
baseUrl = config.ignoreDev ? baseUrl.concat('?nodesToInclude=PROD') : baseUrl;
|
|
337
|
+
return baseUrl;
|
|
325
338
|
}
|
|
326
339
|
function createScaServiceReportStatusURL(config, reportId) {
|
|
327
|
-
return
|
|
340
|
+
return `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/libraries/ingests/${reportId}/status`;
|
|
341
|
+
}
|
|
342
|
+
function createScaServiceIngestsURL(config) {
|
|
343
|
+
return `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/libraries/ingests`;
|
|
328
344
|
}
|
|
329
345
|
function createScaServiceIngestURL(config) {
|
|
330
|
-
|
|
346
|
+
let baseUrl = `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/libraries/ingests/tree`;
|
|
347
|
+
baseUrl = config.track ? baseUrl.concat('?persist=true') : baseUrl;
|
|
348
|
+
return baseUrl;
|
|
331
349
|
}
|
|
332
350
|
const createAppCreateURL = config => {
|
|
333
351
|
return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/create`;
|
|
@@ -353,6 +371,9 @@ function createDataUrl() {
|
|
|
353
371
|
function createSbomUrl(config, type) {
|
|
354
372
|
return `${config.host}/Contrast/api/ng/${config.organizationId}/applications/${config.applicationId}/libraries/sbom/${type}`;
|
|
355
373
|
}
|
|
374
|
+
function createSCASbomUrl(config, type, reportId) {
|
|
375
|
+
return `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/libraries/applications/${config.applicationId}/sbom/${reportId}?toolType=${type}`;
|
|
376
|
+
}
|
|
356
377
|
function createTelemetryEventUrl(config) {
|
|
357
378
|
return `${config.host}/Contrast/api/sast/organizations/${config.organizationId}/cli`;
|
|
358
379
|
}
|
|
@@ -12,7 +12,7 @@ const MEDIUM = 'MEDIUM';
|
|
|
12
12
|
const HIGH = 'HIGH';
|
|
13
13
|
const CRITICAL = 'CRITICAL';
|
|
14
14
|
const APP_NAME = 'contrast';
|
|
15
|
-
const APP_VERSION = '1.0.
|
|
15
|
+
const APP_VERSION = '1.0.16';
|
|
16
16
|
const TIMEOUT = 120000;
|
|
17
17
|
const HIGH_COLOUR = '#ff9900';
|
|
18
18
|
const CRITICAL_COLOUR = '#e35858';
|
|
@@ -30,6 +30,10 @@ const SARIF_FILE = 'SARIF';
|
|
|
30
30
|
const SBOM_CYCLONE_DX_FILE = 'cyclonedx';
|
|
31
31
|
const SBOM_SPDX_FILE = 'spdx';
|
|
32
32
|
const CE_URL = 'https://ce.contrastsecurity.com';
|
|
33
|
+
const SAAS = 'SAAS';
|
|
34
|
+
const EOP = 'EOP';
|
|
35
|
+
const MODE_BUILD = 'BUILD';
|
|
36
|
+
const MODE_REPO = 'REPO';
|
|
33
37
|
module.exports = {
|
|
34
38
|
supportedLanguages: { NODE, DOTNET, JAVA, RUBY, PYTHON, GO, PHP, JAVASCRIPT },
|
|
35
39
|
supportedLanguagesScan: { JAVASCRIPT, DOTNET, JAVA },
|
|
@@ -55,5 +59,9 @@ module.exports = {
|
|
|
55
59
|
LOW_PRIORITY,
|
|
56
60
|
NOTE_PRIORITY,
|
|
57
61
|
SBOM_CYCLONE_DX_FILE,
|
|
58
|
-
SBOM_SPDX_FILE
|
|
62
|
+
SBOM_SPDX_FILE,
|
|
63
|
+
SAAS,
|
|
64
|
+
EOP,
|
|
65
|
+
MODE_BUILD,
|
|
66
|
+
MODE_REPO
|
|
59
67
|
};
|
|
@@ -90,7 +90,7 @@ const en_locales = () => {
|
|
|
90
90
|
constantsHelp: 'Display this usage guide.',
|
|
91
91
|
constantsGradleMultiProject: 'Specify the sub project within your gradle application.',
|
|
92
92
|
constantsScan: 'Upload java binaries to the static scan service',
|
|
93
|
-
|
|
93
|
+
constantsDoNotWaitForScan: 'Do not wait for the result of the scan',
|
|
94
94
|
constantsProjectName: 'Contrast project name. If not specified, Contrast uses contrast.settings to identify the project or creates a project.',
|
|
95
95
|
constantsProjectId: 'The ID associated with a scan project. Replace <ProjectID> with the ID for the scan project. To find the ID, select a scan project in Contrast and locate the last number in the URL.',
|
|
96
96
|
constantsReport: 'Display vulnerability information for this application',
|
|
@@ -133,38 +133,15 @@ const en_locales = () => {
|
|
|
133
133
|
constantsHowToRunDev1: 'Begin with contrast auth to authenticate the CLI to perform actions',
|
|
134
134
|
constantsHowToRunDev2: 'After successful auth try the following command: contrast scan -f "<file>"',
|
|
135
135
|
constantsHowToRunDev3: 'Allowable languages are java (.jar and .war) and javascript (.js or .zip), if the language is not autodetected please use --language to specify',
|
|
136
|
-
constantsHowToRunContent1: 'You can run the tool on the command line and manually add the parameters, or you can put the parameters in a YAML file.',
|
|
137
|
-
constantsHowToRunContent2: 'If you are assessing an application that has not been instrumented by a Contrast agent you must first use the tool to register the application (Catalogue command). This will give you an application ID that you can then use in the Run Command.',
|
|
138
|
-
constantsHowToRunContent3: 'Allowable language values are JAVA, NODE, PYTHON, RUBY and GO.',
|
|
139
|
-
constantsManualInputHeader: 'Manual Input of Command:',
|
|
140
|
-
constantsManualInputCatalogue: 'Catalogue Command:',
|
|
141
|
-
constantsManualInputCatalogueInstruction: 'To analyse a new application not already instrumented by Contrast, run the following command:',
|
|
142
|
-
constantsManualInputCatalogueRun: 'After you run this command, you are provided a new application ID in the console. Use this ID in the Run command:',
|
|
143
|
-
constantsManualInputCatalogueRunTitle: 'Run Command:',
|
|
144
|
-
constantsManualInputCatalogueRunInstruction: 'To analyse an application catalogued by Contrast, run the following command:',
|
|
145
|
-
constantsYaml: 'Yaml:',
|
|
146
|
-
constantsYamlRunCommand: 'After you catalogue your application go to Run Command above.',
|
|
147
136
|
constantsOptions: 'Options',
|
|
148
|
-
constantsCatalogueCommand: '%s YourApiKey %s YourAuthorizationKey %s YourOrganizationId %s YourHost %s YourApplicationName %s YourApplicationLanguage',
|
|
149
|
-
constantsRunCommand: '%s YourApiKey %s YourAuthorizationKey %s YourOrganizationId %s YourHost %s YourApplicationId',
|
|
150
137
|
constantsSpecialCharacterWarning: 'Please Note: Parameters may need to be quoted to avoid issues with special characters.',
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
TlsHeader: 'TLS',
|
|
155
|
-
TlsBody: 'To enable TLS please use the YAML file with the following parameters:',
|
|
156
|
-
TlsKey: 'key: pathToKey',
|
|
157
|
-
TlsCert: 'cert: pathToCert',
|
|
158
|
-
TlsCaCert: 'cacert: pathToCaCert',
|
|
138
|
+
constantsProxyKey: 'Path to the Certificate Key',
|
|
139
|
+
constantsProxyCert: 'Path to the Cert file',
|
|
140
|
+
constantsProxyCaCert: 'Path to the CaCert file',
|
|
159
141
|
goReadProjectFile: 'Failed to read the project file @ "%s" because: "%s"',
|
|
160
|
-
goAnalysisError: 'GO analysis failed because: ',
|
|
161
|
-
goParseProjectFile: 'Failed to parse go mod graph output because: ',
|
|
162
|
-
mavenNotInstalledError: "'mvn' is not available. Please ensure you have Maven installed and available on your path.",
|
|
163
142
|
mavenDependencyTreeNonZero: 'Building maven dependancy tree failed with a non 0 exit code',
|
|
164
143
|
gradleWrapperUnavailable: 'Gradle wrapper not found in root of project. Please ensure gradlew or gradlew.bat is in root of the project.',
|
|
165
144
|
gradleDependencyTreeNonZero: "Building gradle dependancy tree failed with a non 0 exit code. \n Please check you have the correct version of Java installed to compile your project? \n If running against a muti module project ensure you are using the '--sub-project' flag",
|
|
166
|
-
yamlPathCamelCaseError: 'Warning: The "yamlPath" parameter will be deprecated in a future release. Please look at our documentation for further guidance.',
|
|
167
|
-
constantsSbom: 'Generate the Software Bill of Materials (SBOM) for the given application',
|
|
168
145
|
constantsMetadata: 'Define a set of key=value pairs (which conforms to RFC 2253) for specifying user-defined metadata associated with the application.',
|
|
169
146
|
constantsTags: 'Apply labels to an application. Labels must be formatted as a comma-delimited list. Example - label1,label2,label3',
|
|
170
147
|
constantsCode: 'Add the application code this application should use in the Contrast UI',
|
|
@@ -174,9 +151,7 @@ const en_locales = () => {
|
|
|
174
151
|
constantsIgnoreDev: 'Excludes developer dependencies from the results. All dependencies are included by default.',
|
|
175
152
|
constantsCommands: 'Commands',
|
|
176
153
|
constantsScanOptions: 'Scan Options',
|
|
177
|
-
sbomError: 'All required parameters are not present.',
|
|
178
154
|
sbomRetrievalError: 'Unable to retrieve Software Bill of Materials (SBOM)',
|
|
179
|
-
ignoreDevDep: 'No private libraries that are not scoped detected',
|
|
180
155
|
foundExistingProjectScan: 'Found existing project...',
|
|
181
156
|
projectCreatedScan: 'Project created',
|
|
182
157
|
uploadingScan: 'Uploading file to scan.',
|
|
@@ -190,7 +165,6 @@ const en_locales = () => {
|
|
|
190
165
|
specifyFileAuditNotFound: 'No files found for library analysis',
|
|
191
166
|
populateProjectIdMessage: 'project ID is %s',
|
|
192
167
|
genericServiceError: 'returned with status code %s',
|
|
193
|
-
projectIdError: 'Your project ID is %s please check this is correct',
|
|
194
168
|
permissionsError: 'You do not have the correct permissions here. \n Contact support@contrastsecurity.com to get this fixed.',
|
|
195
169
|
scanErrorFileMessage: 'We only accept the following file types: \nJava - .jar, .war \nJavaScript - .js or .zip files',
|
|
196
170
|
helpAuthSummary: 'Authenticate Contrast using your Github or Google account',
|
|
@@ -213,6 +187,8 @@ const en_locales = () => {
|
|
|
213
187
|
scanOptionsTimeoutSummary: 'Time in seconds to wait for scan to complete. Default value is 300 seconds.',
|
|
214
188
|
scanOptionsFileNameSummary: 'Path of the file you want to scan. If no file is specified, Contrast searches for a .jar, .war, .exe or .zip file in the working directory.',
|
|
215
189
|
scanOptionsVerboseSummary: ' Returns extended information to the terminal.',
|
|
190
|
+
auditOptionsTrackSummary: ' Save the results to the UI.',
|
|
191
|
+
auditOptionsBranchSummary: ' Set the branch name to associate the library results to.',
|
|
216
192
|
authSuccessMessage: 'Authentication successful',
|
|
217
193
|
runAuthSuccessMessage: chalk.bold('CodeSec by Contrast') +
|
|
218
194
|
'\nScan, secure and ship your code in minutes for FREE. \n' +
|
|
@@ -297,6 +273,7 @@ const en_locales = () => {
|
|
|
297
273
|
auditSBOMSaveSuccess: '\n Software Bill of Materials (SBOM) saved successfully',
|
|
298
274
|
auditNoFiletypeSpecifiedForSave: `\n ${chalk.yellow.bold('No file type specified for --save option to save audit results to. Use audit --help to see valid --save options.')}`,
|
|
299
275
|
auditBadFiletypeSpecifiedForSave: `\n ${chalk.yellow.bold('Bad file type specified for --save option. Use audit --help to see valid --save options.')}`,
|
|
276
|
+
auditServicesMessageForTS: 'View your vulnerable library list or full dependency tree in Contrast:',
|
|
300
277
|
auditReportWaiting: 'Waiting for report...',
|
|
301
278
|
auditReportFail: 'Report Retrieval Failed, please try again',
|
|
302
279
|
auditReportSuccessMessage: 'Report successfully retrieved',
|