@contrast/contrast 1.0.16 → 1.0.17
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/catalogueApplication/catalogueApplication.js +1 -1
- package/dist/cliConstants.js +6 -1
- package/dist/commands/audit/auditConfig.js +10 -12
- package/dist/commands/audit/auditController.js +12 -16
- package/dist/commands/audit/help.js +24 -26
- package/dist/commands/audit/processAudit.js +16 -22
- package/dist/commands/audit/saveFile.js +3 -9
- package/dist/commands/scan/processScan.js +5 -7
- package/dist/commands/scan/sca/scaAnalysis.js +104 -88
- package/dist/common/commonHelp.js +35 -17
- package/dist/common/errorHandling.js +28 -57
- package/dist/common/versionChecker.js +24 -27
- package/dist/constants/constants.js +1 -1
- package/dist/constants/locales.js +6 -3
- package/dist/lambda/help.js +2 -1
- package/dist/lambda/lambda.js +2 -7
- package/dist/scaAnalysis/java/analysis.js +40 -5
- package/dist/scaAnalysis/java/index.js +15 -2
- package/dist/scan/autoDetection.js +12 -3
- package/dist/scan/fileUtils.js +24 -1
- package/dist/scan/help.js +2 -1
- package/dist/scan/saveResults.js +1 -1
- package/dist/utils/commonApi.js +10 -1
- package/dist/utils/generalAPI.js +1 -2
- package/dist/utils/paramsUtil/configStoreParams.js +12 -1
- package/dist/utils/paramsUtil/paramHandler.js +7 -1
- package/dist/utils/saveFile.js +2 -1
- package/package.json +2 -1
- package/src/audit/catalogueApplication/catalogueApplication.js +1 -1
- package/src/cliConstants.js +6 -1
- package/src/commands/audit/auditConfig.js +19 -0
- package/src/commands/audit/{auditController.ts → auditController.js} +17 -12
- package/src/commands/audit/{help.ts → help.js} +10 -7
- package/src/commands/audit/processAudit.js +37 -0
- package/src/commands/audit/{saveFile.ts → saveFile.js} +2 -2
- package/src/commands/scan/processScan.js +4 -10
- package/src/commands/scan/sca/scaAnalysis.js +134 -116
- package/src/common/commonHelp.js +43 -0
- package/src/common/{errorHandling.ts → errorHandling.js} +6 -31
- package/src/common/{versionChecker.ts → versionChecker.js} +15 -10
- package/src/constants/constants.js +1 -1
- package/src/constants/locales.js +7 -3
- package/src/lambda/help.ts +2 -1
- package/src/lambda/lambda.ts +2 -10
- package/src/scaAnalysis/java/analysis.js +43 -10
- package/src/scaAnalysis/java/index.js +19 -2
- package/src/scan/autoDetection.js +14 -3
- package/src/scan/fileUtils.js +29 -1
- package/src/scan/help.js +2 -1
- package/src/scan/saveResults.js +1 -1
- package/src/utils/commonApi.js +13 -1
- package/src/utils/generalAPI.js +1 -2
- package/src/utils/getConfig.ts +1 -0
- package/src/utils/paramsUtil/configStoreParams.js +14 -1
- package/src/utils/paramsUtil/paramHandler.js +9 -1
- package/src/utils/saveFile.js +2 -1
- package/src/commands/audit/auditConfig.ts +0 -21
- package/src/commands/audit/processAudit.ts +0 -40
- package/src/common/commonHelp.ts +0 -13
|
@@ -1,107 +1,63 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.maxAppError = exports.reportFailureError = exports.vulnerabilitiesFailureError = exports.snapshotFailureError = exports.findCommandOnError = exports.libraryAnalysisError = exports.handleResponseErrors = exports.getErrorMessage = exports.generalError = exports.failOptionError = exports.proxyError = exports.forbiddenError = exports.badRequestError = exports.unauthenticatedError = exports.genericError = void 0;
|
|
7
|
-
const i18n_1 = __importDefault(require("i18n"));
|
|
8
|
-
const handleResponseErrors = (res, api) => {
|
|
9
|
-
if (res.statusCode === 400) {
|
|
10
|
-
api === 'catalogue' ? badRequestError(true) : badRequestError(false);
|
|
11
|
-
}
|
|
12
|
-
else if (res.statusCode === 401) {
|
|
13
|
-
unauthenticatedError();
|
|
14
|
-
}
|
|
15
|
-
else if (res.statusCode === 403) {
|
|
16
|
-
forbiddenError();
|
|
17
|
-
}
|
|
18
|
-
else if (res.statusCode === 407) {
|
|
19
|
-
proxyError();
|
|
20
|
-
}
|
|
21
|
-
else {
|
|
22
|
-
if (api === 'snapshot' || api === 'catalogue') {
|
|
23
|
-
snapshotFailureError();
|
|
24
|
-
}
|
|
25
|
-
if (api === 'vulnerabilities') {
|
|
26
|
-
vulnerabilitiesFailureError();
|
|
27
|
-
}
|
|
28
|
-
if (api === 'report') {
|
|
29
|
-
reportFailureError();
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
exports.handleResponseErrors = handleResponseErrors;
|
|
2
|
+
const i18n = require('i18n');
|
|
34
3
|
const libraryAnalysisError = () => {
|
|
35
|
-
console.log(
|
|
4
|
+
console.log(i18n.__('libraryAnalysisError'));
|
|
36
5
|
};
|
|
37
|
-
exports.libraryAnalysisError = libraryAnalysisError;
|
|
38
6
|
const snapshotFailureError = () => {
|
|
39
|
-
console.log(
|
|
7
|
+
console.log(i18n.__('snapshotFailureMessage'));
|
|
40
8
|
};
|
|
41
|
-
exports.snapshotFailureError = snapshotFailureError;
|
|
42
9
|
const vulnerabilitiesFailureError = () => {
|
|
43
|
-
console.log(
|
|
10
|
+
console.log(i18n.__('vulnerabilitiesFailureMessage'));
|
|
44
11
|
};
|
|
45
|
-
exports.vulnerabilitiesFailureError = vulnerabilitiesFailureError;
|
|
46
12
|
const reportFailureError = () => {
|
|
47
|
-
console.log(
|
|
13
|
+
console.log(i18n.__('auditReportFailureMessage'));
|
|
48
14
|
};
|
|
49
|
-
exports.reportFailureError = reportFailureError;
|
|
50
15
|
const genericError = () => {
|
|
51
|
-
console.error(
|
|
16
|
+
console.error(i18n.__('genericErrorMessage'));
|
|
52
17
|
process.exit(1);
|
|
53
18
|
};
|
|
54
|
-
exports.genericError = genericError;
|
|
55
19
|
const unauthenticatedError = () => {
|
|
56
20
|
generalError('unauthenticatedErrorHeader', 'unauthenticatedErrorMessage');
|
|
57
21
|
};
|
|
58
|
-
|
|
59
|
-
const badRequestError = (catalogue) => {
|
|
22
|
+
const badRequestError = catalogue => {
|
|
60
23
|
catalogue === true
|
|
61
24
|
? generalError('badRequestErrorHeader', 'badRequestCatalogueErrorMessage')
|
|
62
25
|
: generalError('badRequestErrorHeader', 'badRequestErrorMessage');
|
|
63
26
|
};
|
|
64
|
-
exports.badRequestError = badRequestError;
|
|
65
27
|
const forbiddenError = () => {
|
|
66
28
|
generalError('forbiddenRequestErrorHeader', 'forbiddenRequestErrorMessage');
|
|
67
29
|
process.exit(1);
|
|
68
30
|
};
|
|
69
|
-
exports.forbiddenError = forbiddenError;
|
|
70
31
|
const proxyError = () => {
|
|
71
32
|
generalError('proxyErrorHeader', 'proxyErrorMessage');
|
|
72
33
|
};
|
|
73
|
-
exports.proxyError = proxyError;
|
|
74
34
|
const maxAppError = () => {
|
|
75
35
|
generalError('No applications remaining', 'You have reached the maximum number of application you can create.');
|
|
76
36
|
process.exit(1);
|
|
77
37
|
};
|
|
78
|
-
exports.maxAppError = maxAppError;
|
|
79
38
|
const failOptionError = () => {
|
|
80
39
|
console.log('\n ******************************** ' +
|
|
81
|
-
|
|
40
|
+
i18n.__('snapshotFailureHeader') +
|
|
82
41
|
' ********************************\n' +
|
|
83
|
-
|
|
42
|
+
i18n.__('failOptionErrorMessage'));
|
|
84
43
|
};
|
|
85
|
-
exports.failOptionError = failOptionError;
|
|
86
44
|
const getErrorMessage = (header, message) => {
|
|
87
|
-
const title = `******************************** ${
|
|
45
|
+
const title = `******************************** ${i18n.__(header)} ********************************`;
|
|
88
46
|
const multiLine = message?.includes('\n');
|
|
89
47
|
let finalMessage = '';
|
|
90
48
|
if (multiLine) {
|
|
91
49
|
finalMessage = `\n${message}`;
|
|
92
50
|
}
|
|
93
51
|
else if (message) {
|
|
94
|
-
finalMessage = `\n${
|
|
52
|
+
finalMessage = `\n${i18n.__(message)}`;
|
|
95
53
|
}
|
|
96
54
|
return `${title}${finalMessage}`;
|
|
97
55
|
};
|
|
98
|
-
exports.getErrorMessage = getErrorMessage;
|
|
99
56
|
const generalError = (header, message) => {
|
|
100
57
|
const finalMessage = getErrorMessage(header, message);
|
|
101
58
|
console.log(finalMessage);
|
|
102
59
|
};
|
|
103
|
-
|
|
104
|
-
const findCommandOnError = (unknownOptions) => {
|
|
60
|
+
const findCommandOnError = unknownOptions => {
|
|
105
61
|
const commandKeywords = {
|
|
106
62
|
auth: 'auth',
|
|
107
63
|
audit: 'audit',
|
|
@@ -115,4 +71,19 @@ const findCommandOnError = (unknownOptions) => {
|
|
|
115
71
|
return foundCommands[0];
|
|
116
72
|
}
|
|
117
73
|
};
|
|
118
|
-
exports
|
|
74
|
+
module.exports = {
|
|
75
|
+
genericError,
|
|
76
|
+
unauthenticatedError,
|
|
77
|
+
badRequestError,
|
|
78
|
+
forbiddenError,
|
|
79
|
+
proxyError,
|
|
80
|
+
failOptionError,
|
|
81
|
+
generalError,
|
|
82
|
+
getErrorMessage,
|
|
83
|
+
libraryAnalysisError,
|
|
84
|
+
findCommandOnError,
|
|
85
|
+
snapshotFailureError,
|
|
86
|
+
vulnerabilitiesFailureError,
|
|
87
|
+
reportFailureError,
|
|
88
|
+
maxAppError
|
|
89
|
+
};
|
|
@@ -1,20 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
const boxen_1 = __importDefault(require("boxen"));
|
|
9
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
-
const semver_1 = __importDefault(require("semver"));
|
|
11
|
-
const commonApi_1 = __importDefault(require("../utils/commonApi"));
|
|
12
|
-
const http2_1 = require("http2");
|
|
2
|
+
const { APP_VERSION } = require('../constants/constants');
|
|
3
|
+
const boxen = require('boxen');
|
|
4
|
+
const chalk = require('chalk');
|
|
5
|
+
const semver = require('semver');
|
|
6
|
+
const commonApi = require('../utils/commonApi');
|
|
7
|
+
const { constants } = require('http2');
|
|
13
8
|
const getLatestVersion = async (config) => {
|
|
14
|
-
const client =
|
|
9
|
+
const client = commonApi.getHttpClient(config);
|
|
15
10
|
try {
|
|
16
11
|
const res = await client.getLatestVersion();
|
|
17
|
-
if (res.statusCode ===
|
|
12
|
+
if (res.statusCode === constants.HTTP_STATUS_OK) {
|
|
18
13
|
return res.body;
|
|
19
14
|
}
|
|
20
15
|
}
|
|
@@ -22,24 +17,23 @@ const getLatestVersion = async (config) => {
|
|
|
22
17
|
return undefined;
|
|
23
18
|
}
|
|
24
19
|
};
|
|
25
|
-
|
|
26
|
-
async function findLatestCLIVersion(config) {
|
|
20
|
+
const findLatestCLIVersion = async (config) => {
|
|
27
21
|
const isCI = process.env.CONTRAST_CODESEC_CI
|
|
28
22
|
? JSON.parse(process.env.CONTRAST_CODESEC_CI.toLowerCase())
|
|
29
23
|
: false;
|
|
30
24
|
if (!isCI) {
|
|
31
|
-
let latestCLIVersion = await
|
|
25
|
+
let latestCLIVersion = await getLatestVersion(config);
|
|
32
26
|
if (latestCLIVersion === undefined) {
|
|
33
27
|
config.set('numOfRuns', 0);
|
|
34
28
|
console.log('Failed to retrieve latest version info. Continuing execution.');
|
|
35
29
|
return;
|
|
36
30
|
}
|
|
37
31
|
latestCLIVersion = latestCLIVersion.substring(8).replace('\n', '');
|
|
38
|
-
if (
|
|
39
|
-
const updateAvailableMessage = `Update available ${
|
|
40
|
-
const npmUpdateAvailableCommand = `Run ${
|
|
41
|
-
const homebrewUpdateAvailableCommand = `Run ${
|
|
42
|
-
console.log((
|
|
32
|
+
if (semver.lt(APP_VERSION, latestCLIVersion)) {
|
|
33
|
+
const updateAvailableMessage = `Update available ${chalk.yellow(APP_VERSION)} → ${chalk.green(latestCLIVersion)}`;
|
|
34
|
+
const npmUpdateAvailableCommand = `Run ${chalk.cyan('npm i @contrast/contrast -g')} to update via npm`;
|
|
35
|
+
const homebrewUpdateAvailableCommand = `Run ${chalk.cyan('brew install contrastsecurity/tap/contrast')} to update via brew`;
|
|
36
|
+
console.log(boxen(`${updateAvailableMessage}\n${npmUpdateAvailableCommand}\n\n${homebrewUpdateAvailableCommand}`, {
|
|
43
37
|
titleAlignment: 'center',
|
|
44
38
|
margin: 1,
|
|
45
39
|
padding: 1,
|
|
@@ -47,9 +41,12 @@ async function findLatestCLIVersion(config) {
|
|
|
47
41
|
}));
|
|
48
42
|
}
|
|
49
43
|
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
44
|
+
};
|
|
45
|
+
const isCorrectNodeVersion = async (currentVersion) => {
|
|
46
|
+
return semver.satisfies(currentVersion, '>=16');
|
|
47
|
+
};
|
|
48
|
+
module.exports = {
|
|
49
|
+
getLatestVersion,
|
|
50
|
+
findLatestCLIVersion,
|
|
51
|
+
isCorrectNodeVersion
|
|
52
|
+
};
|
|
@@ -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.17';
|
|
16
16
|
const TIMEOUT = 120000;
|
|
17
17
|
const HIGH_COLOUR = '#ff9900';
|
|
18
18
|
const CRITICAL_COLOUR = '#e35858';
|
|
@@ -139,9 +139,9 @@ const en_locales = () => {
|
|
|
139
139
|
constantsProxyCert: 'Path to the Cert file',
|
|
140
140
|
constantsProxyCaCert: 'Path to the CaCert file',
|
|
141
141
|
goReadProjectFile: 'Failed to read the project file @ "%s" because: "%s"',
|
|
142
|
-
mavenDependencyTreeNonZero: 'Building maven
|
|
142
|
+
mavenDependencyTreeNonZero: 'Building maven dependency tree failed with a non 0 exit code',
|
|
143
143
|
gradleWrapperUnavailable: 'Gradle wrapper not found in root of project. Please ensure gradlew or gradlew.bat is in root of the project.',
|
|
144
|
-
gradleDependencyTreeNonZero: "Building gradle
|
|
144
|
+
gradleDependencyTreeNonZero: "Building gradle dependency 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",
|
|
145
145
|
constantsMetadata: 'Define a set of key=value pairs (which conforms to RFC 2253) for specifying user-defined metadata associated with the application.',
|
|
146
146
|
constantsTags: 'Apply labels to an application. Labels must be formatted as a comma-delimited list. Example - label1,label2,label3',
|
|
147
147
|
constantsCode: 'Add the application code this application should use in the Contrast UI',
|
|
@@ -281,10 +281,13 @@ const en_locales = () => {
|
|
|
281
281
|
auditSCAAnalysisBegins: 'Contrast SCA audit started',
|
|
282
282
|
auditSCAAnalysisComplete: 'Contrast audit complete',
|
|
283
283
|
commonHelpHeader: 'Need More Help?',
|
|
284
|
+
commonHelpEnterpriseHeader: 'Existing Contrast user?',
|
|
284
285
|
commonHelpCheckOutHeader: chalk.hex('#9DC184')('Check out:'),
|
|
285
286
|
commonHelpCheckOutText: ' https://support.contrastsecurity.com',
|
|
286
287
|
commonHelpLearnMoreHeader: chalk.hex('#9DC184')('Learn more at:'),
|
|
287
|
-
|
|
288
|
+
commonHelpLearnMoreEnterpriseHeader: chalk.hex('#9DC184')('Read our docs:'),
|
|
289
|
+
commonHelpLearnMoreText: ' https://www.contrastsecurity.com/developer ',
|
|
290
|
+
commonHelpLearnMoreEnterpriseText: ' https://docs.contrastsecurity.com/en/run-contrast-cli.html ',
|
|
288
291
|
commonHelpJoinDiscussionHeader: chalk.hex('#9DC184')('Join the discussion:'),
|
|
289
292
|
commonHelpJoinDiscussionText: ' https://dev.to/codesec',
|
|
290
293
|
...lambda
|
package/dist/lambda/help.js
CHANGED
|
@@ -81,6 +81,7 @@ const lambdaUsageGuide = (0, command_line_usage_1.default)([
|
|
|
81
81
|
{ name: i18n_1.default.__('lambdaHelpOption'), summary: i18n_1.default.__('helpSummary') }
|
|
82
82
|
]
|
|
83
83
|
},
|
|
84
|
-
(0, commonHelp_1.commonHelpLinks)()
|
|
84
|
+
(0, commonHelp_1.commonHelpLinks)()[0],
|
|
85
|
+
(0, commonHelp_1.commonHelpLinks)()[1]
|
|
85
86
|
]);
|
|
86
87
|
exports.lambdaUsageGuide = lambdaUsageGuide;
|
package/dist/lambda/lambda.js
CHANGED
|
@@ -23,7 +23,7 @@ const oraWrapper_1 = __importDefault(require("../utils/oraWrapper"));
|
|
|
23
23
|
const analytics_1 = require("./analytics");
|
|
24
24
|
const types_1 = require("./types");
|
|
25
25
|
const constants_2 = require("../constants/constants");
|
|
26
|
-
const
|
|
26
|
+
const commonHelp_1 = require("../common/commonHelp");
|
|
27
27
|
const failedStates = [
|
|
28
28
|
'UNSUPPORTED',
|
|
29
29
|
'EXCLUDED',
|
|
@@ -110,7 +110,7 @@ const processLambda = async (argv) => {
|
|
|
110
110
|
}
|
|
111
111
|
await (0, analytics_1.postAnalytics)(endCommandAnalytics).catch((error) => {
|
|
112
112
|
});
|
|
113
|
-
postRunMessage();
|
|
113
|
+
(0, commonHelp_1.postRunMessage)('lambda');
|
|
114
114
|
if (errorMsg) {
|
|
115
115
|
process.exit(1);
|
|
116
116
|
}
|
|
@@ -193,8 +193,3 @@ const handleLambdaHelp = () => {
|
|
|
193
193
|
printHelpMessage();
|
|
194
194
|
process.exit(0);
|
|
195
195
|
};
|
|
196
|
-
const postRunMessage = () => {
|
|
197
|
-
console.log('\n' + chalk_1.default.underline.bold('Other Codesec Features:'));
|
|
198
|
-
console.log("'contrast scan' to run CodeSec’s industry leading SAST scanner");
|
|
199
|
-
console.log("'contrast audit' to find vulnerabilities in your open source dependencies\n");
|
|
200
|
-
};
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const child_process = require('child_process');
|
|
3
|
+
const spawn = require('cross-spawn');
|
|
3
4
|
const path = require('path');
|
|
4
5
|
const i18n = require('i18n');
|
|
5
6
|
const fs = require('fs');
|
|
7
|
+
const readLine = require('readline');
|
|
8
|
+
const paramHandler = require('../../utils/paramsUtil/paramHandler');
|
|
6
9
|
const MAVEN = 'maven';
|
|
7
10
|
const GRADLE = 'gradle';
|
|
8
11
|
const determineProjectTypeAndCwd = (files, config) => {
|
|
@@ -23,15 +26,20 @@ const determineProjectTypeAndCwd = (files, config) => {
|
|
|
23
26
|
};
|
|
24
27
|
const buildMaven = (config, projectData, timeout) => {
|
|
25
28
|
let cmdStdout;
|
|
26
|
-
let mvn_settings = '';
|
|
27
29
|
try {
|
|
30
|
+
let command = 'mvn';
|
|
31
|
+
let args = ['dependency:tree', '-B'];
|
|
28
32
|
if (config.mavenSettingsPath) {
|
|
29
|
-
|
|
33
|
+
args.push('-s');
|
|
34
|
+
args.push(config.mavenSettingsPath);
|
|
30
35
|
}
|
|
31
|
-
cmdStdout =
|
|
36
|
+
cmdStdout = spawn
|
|
37
|
+
.sync(command, args, {
|
|
38
|
+
env: process.env,
|
|
32
39
|
cwd: projectData.cwd,
|
|
33
40
|
timeout
|
|
34
|
-
})
|
|
41
|
+
})
|
|
42
|
+
.stdout.toString();
|
|
35
43
|
return cmdStdout.toString();
|
|
36
44
|
}
|
|
37
45
|
catch (err) {
|
|
@@ -103,7 +111,34 @@ const getJavaBuildDeps = (config, files) => {
|
|
|
103
111
|
console.log(err.message.toString());
|
|
104
112
|
}
|
|
105
113
|
};
|
|
114
|
+
const agreementPrompt = async (config) => {
|
|
115
|
+
const rl = readLine.createInterface({
|
|
116
|
+
input: process.stdin,
|
|
117
|
+
output: process.stdout
|
|
118
|
+
});
|
|
119
|
+
return new Promise((resolve, reject) => {
|
|
120
|
+
rl.question('❔ Do you want to continue? Type Y or N', async (input) => {
|
|
121
|
+
if (input.toLowerCase() === 'yes' || input.toLowerCase() === 'y') {
|
|
122
|
+
config.javaAgreement = paramHandler.setAgreement(true);
|
|
123
|
+
rl.close();
|
|
124
|
+
resolve(config);
|
|
125
|
+
}
|
|
126
|
+
else if (input.toLowerCase() === 'no' || input.toLowerCase() === 'n') {
|
|
127
|
+
rl.close();
|
|
128
|
+
resolve(process.exit(1));
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
rl.close();
|
|
132
|
+
console.log('Invalid Input: Exiting');
|
|
133
|
+
resolve(process.exit(1));
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}).catch(e => {
|
|
137
|
+
throw e;
|
|
138
|
+
});
|
|
139
|
+
};
|
|
106
140
|
module.exports = {
|
|
107
141
|
getJavaBuildDeps,
|
|
108
|
-
determineProjectTypeAndCwd
|
|
142
|
+
determineProjectTypeAndCwd,
|
|
143
|
+
agreementPrompt
|
|
109
144
|
};
|
|
@@ -3,10 +3,13 @@ const analysis = require('./analysis');
|
|
|
3
3
|
const { parseBuildDeps } = require('./javaBuildDepsParser');
|
|
4
4
|
const { createJavaTSMessage } = require('../common/formatMessage');
|
|
5
5
|
const { parseDependenciesForSCAServices } = require('../common/scaParserForGoAndJava');
|
|
6
|
-
const
|
|
6
|
+
const chalk = require('chalk');
|
|
7
|
+
const _ = require('lodash');
|
|
8
|
+
const javaAnalysis = async (config, languageFiles) => {
|
|
7
9
|
languageFiles.JAVA.forEach(file => {
|
|
8
10
|
file.replace('build.gradle.kts', 'build.gradle');
|
|
9
11
|
});
|
|
12
|
+
await getAgreement(config);
|
|
10
13
|
const javaDeps = buildJavaTree(config, languageFiles.JAVA);
|
|
11
14
|
if (config.experimental) {
|
|
12
15
|
return parseDependenciesForSCAServices(javaDeps);
|
|
@@ -15,10 +18,20 @@ const javaAnalysis = (config, languageFiles) => {
|
|
|
15
18
|
return createJavaTSMessage(javaDeps);
|
|
16
19
|
}
|
|
17
20
|
};
|
|
21
|
+
const getAgreement = async (config) => {
|
|
22
|
+
console.log(chalk.bold('Java project detected'));
|
|
23
|
+
console.log('Java analysis uses maven / gradle which are potentially susceptible to command injection. Be sure that the code you are running Contrast CLI on is trusted before continuing.');
|
|
24
|
+
if (_.isNil(!process.env.CI) && _.isNil(!config.javaAgreement)) {
|
|
25
|
+
console.log('should print');
|
|
26
|
+
return await analysis.agreementPrompt(config);
|
|
27
|
+
}
|
|
28
|
+
return config;
|
|
29
|
+
};
|
|
18
30
|
const buildJavaTree = (config, files) => {
|
|
19
31
|
const javaBuildDeps = analysis.getJavaBuildDeps(config, files);
|
|
20
32
|
return parseBuildDeps(config, javaBuildDeps);
|
|
21
33
|
};
|
|
22
34
|
module.exports = {
|
|
23
|
-
javaAnalysis
|
|
35
|
+
javaAnalysis,
|
|
36
|
+
getAgreement
|
|
24
37
|
};
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const i18n = require('i18n');
|
|
3
3
|
const fileFinder = require('./fileUtils');
|
|
4
|
-
const
|
|
5
|
-
|
|
4
|
+
const autoDetectFingerprintInfo = async (filePath) => {
|
|
5
|
+
let complexObj = await fileFinder.findAllFiles(filePath);
|
|
6
|
+
let result = [];
|
|
7
|
+
let count = 0;
|
|
8
|
+
complexObj.forEach(i => {
|
|
9
|
+
count++;
|
|
10
|
+
result.push({ filePath: i, id: count.toString() });
|
|
11
|
+
});
|
|
12
|
+
return result;
|
|
13
|
+
};
|
|
6
14
|
const autoDetectFileAndLanguage = async (configToUse) => {
|
|
7
15
|
const entries = await fileFinder.findFile();
|
|
8
16
|
if (entries.length === 1) {
|
|
@@ -78,5 +86,6 @@ module.exports = {
|
|
|
78
86
|
autoDetectFileAndLanguage,
|
|
79
87
|
errorOnFileDetection,
|
|
80
88
|
autoDetectAuditFilesAndLanguages,
|
|
81
|
-
errorOnAuditFileDetection
|
|
89
|
+
errorOnAuditFileDetection,
|
|
90
|
+
autoDetectFingerprintInfo
|
|
82
91
|
};
|
package/dist/scan/fileUtils.js
CHANGED
|
@@ -10,6 +10,28 @@ const findFile = async () => {
|
|
|
10
10
|
onlyFiles: true
|
|
11
11
|
});
|
|
12
12
|
};
|
|
13
|
+
const findAllFiles = async (filePath) => {
|
|
14
|
+
const result = await fg([
|
|
15
|
+
'**/pom.xml',
|
|
16
|
+
'**/build.gradle',
|
|
17
|
+
'**/build.gradle.kts',
|
|
18
|
+
'**/package.json',
|
|
19
|
+
'**/Pipfile',
|
|
20
|
+
'**/*.csproj',
|
|
21
|
+
'**/Gemfile',
|
|
22
|
+
'**/go.mod'
|
|
23
|
+
], {
|
|
24
|
+
dot: false,
|
|
25
|
+
deep: 2,
|
|
26
|
+
onlyFiles: true,
|
|
27
|
+
absolute: true,
|
|
28
|
+
cwd: filePath ? filePath : process.cwd()
|
|
29
|
+
});
|
|
30
|
+
if (result.length > 0) {
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
return [];
|
|
34
|
+
};
|
|
13
35
|
const findFilesJava = async (languagesFound, filePath) => {
|
|
14
36
|
const result = await fg(['**/pom.xml', '**/build.gradle', '**/build.gradle.kts'], {
|
|
15
37
|
dot: false,
|
|
@@ -136,5 +158,6 @@ module.exports = {
|
|
|
136
158
|
findFilesPhp,
|
|
137
159
|
findFilesRuby,
|
|
138
160
|
findFilesDotNet,
|
|
139
|
-
fileIsEmpty
|
|
161
|
+
fileIsEmpty,
|
|
162
|
+
findAllFiles
|
|
140
163
|
};
|
package/dist/scan/help.js
CHANGED
package/dist/scan/saveResults.js
CHANGED
|
@@ -3,7 +3,7 @@ const fs = require('fs');
|
|
|
3
3
|
const writeResultsToFile = async (responseBody, name = 'results.sarif') => {
|
|
4
4
|
try {
|
|
5
5
|
fs.writeFileSync(name, JSON.stringify(responseBody, null, 2));
|
|
6
|
-
|
|
6
|
+
return name;
|
|
7
7
|
}
|
|
8
8
|
catch (err) {
|
|
9
9
|
console.log('Error writing Scan Results to file');
|
package/dist/utils/commonApi.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const HttpClient = require('./../common/HTTPClient');
|
|
3
|
-
const { badRequestError, unauthenticatedError, forbiddenError, proxyError, genericError, maxAppError } = require('../common/errorHandling');
|
|
3
|
+
const { badRequestError, unauthenticatedError, forbiddenError, proxyError, genericError, maxAppError, snapshotFailureError, vulnerabilitiesFailureError, reportFailureError } = require('../common/errorHandling');
|
|
4
4
|
const handleResponseErrors = (res, api) => {
|
|
5
5
|
if (res.statusCode === 400) {
|
|
6
6
|
api === 'catalogue' ? badRequestError(true) : badRequestError(false);
|
|
@@ -18,6 +18,15 @@ const handleResponseErrors = (res, api) => {
|
|
|
18
18
|
maxAppError();
|
|
19
19
|
}
|
|
20
20
|
else {
|
|
21
|
+
if (api === 'snapshot' || api === 'catalogue') {
|
|
22
|
+
snapshotFailureError();
|
|
23
|
+
}
|
|
24
|
+
if (api === 'vulnerabilities') {
|
|
25
|
+
vulnerabilitiesFailureError();
|
|
26
|
+
}
|
|
27
|
+
if (api === 'report') {
|
|
28
|
+
reportFailureError();
|
|
29
|
+
}
|
|
21
30
|
console.log(res.statusCode);
|
|
22
31
|
genericError(res);
|
|
23
32
|
}
|
package/dist/utils/generalAPI.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const { featuresTeamServer } = require('./capabilities');
|
|
3
3
|
const semver = require('semver');
|
|
4
|
-
const { handleResponseErrors } = require('../common/errorHandling');
|
|
5
4
|
const commonApi = require('./commonApi');
|
|
6
5
|
const { isNil } = require('lodash');
|
|
7
6
|
const getGlobalProperties = async (config) => {
|
|
@@ -13,7 +12,7 @@ const getGlobalProperties = async (config) => {
|
|
|
13
12
|
return res.body;
|
|
14
13
|
}
|
|
15
14
|
else {
|
|
16
|
-
handleResponseErrors(res, 'globalProperties');
|
|
15
|
+
commonApi.handleResponseErrors(res, 'globalProperties');
|
|
17
16
|
}
|
|
18
17
|
})
|
|
19
18
|
.catch(err => {
|
|
@@ -15,4 +15,15 @@ const getAuth = () => {
|
|
|
15
15
|
}
|
|
16
16
|
return ContrastConfToUse;
|
|
17
17
|
};
|
|
18
|
-
|
|
18
|
+
const getAgreement = () => {
|
|
19
|
+
const ContrastConf = config.localConfig(APP_NAME, APP_VERSION);
|
|
20
|
+
let ContrastConfToUse = {};
|
|
21
|
+
ContrastConfToUse.javaAgreement = ContrastConf.get('javaAgreement');
|
|
22
|
+
return ContrastConfToUse;
|
|
23
|
+
};
|
|
24
|
+
const setAgreement = agreement => {
|
|
25
|
+
const ContrastConf = config.localConfig(APP_NAME, APP_VERSION);
|
|
26
|
+
ContrastConf.set('javaAgreement', agreement);
|
|
27
|
+
return agreement;
|
|
28
|
+
};
|
|
29
|
+
module.exports = { getAuth, getAgreement, setAgreement };
|
|
@@ -22,4 +22,10 @@ const getAuth = params => {
|
|
|
22
22
|
process.exit(1);
|
|
23
23
|
}
|
|
24
24
|
};
|
|
25
|
-
|
|
25
|
+
const getAgreement = () => {
|
|
26
|
+
return configStoreParams.getAgreement();
|
|
27
|
+
};
|
|
28
|
+
const setAgreement = answer => {
|
|
29
|
+
return configStoreParams.setAgreement(answer);
|
|
30
|
+
};
|
|
31
|
+
module.exports = { getAuth, getAgreement, setAgreement };
|
package/dist/utils/saveFile.js
CHANGED
|
@@ -8,7 +8,8 @@ const saveScanFile = async (config, scanResults) => {
|
|
|
8
8
|
const scanId = scanResults.scanDetail.id;
|
|
9
9
|
const client = commonApi.getHttpClient(config);
|
|
10
10
|
const rawResults = await client.getSpecificScanResultSarif(config, scanId);
|
|
11
|
-
await saveResults.writeResultsToFile(rawResults?.body);
|
|
11
|
+
const name = await saveResults.writeResultsToFile(rawResults?.body);
|
|
12
|
+
console.log(`Scan Results saved to ${name}`);
|
|
12
13
|
}
|
|
13
14
|
else {
|
|
14
15
|
console.log(i18n.__('scanNoFiletypeSpecifiedForSave'));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contrast/contrast",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.17",
|
|
4
4
|
"description": "Contrast Security's command line tool",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
"command-line-args": "^5.2.1",
|
|
55
55
|
"command-line-usage": "^6.1.3",
|
|
56
56
|
"conf": "^10.1.2",
|
|
57
|
+
"cross-spawn": "^7.0.3",
|
|
57
58
|
"dotenv": "^16.0.0",
|
|
58
59
|
"fast-glob": "^3.2.11",
|
|
59
60
|
"gradle-to-js": "^2.0.1",
|
package/src/cliConstants.js
CHANGED
|
@@ -334,6 +334,10 @@ const auditOptionDefinitions = [
|
|
|
334
334
|
{
|
|
335
335
|
name: 'maven-settings-path'
|
|
336
336
|
},
|
|
337
|
+
{
|
|
338
|
+
name: 'fingerprint',
|
|
339
|
+
type: Boolean
|
|
340
|
+
},
|
|
337
341
|
{
|
|
338
342
|
name: 'organization-id',
|
|
339
343
|
alias: 'o',
|
|
@@ -461,7 +465,8 @@ const mainUsageGuide = commandLineUsage([
|
|
|
461
465
|
{ name: i18n.__('clearHeader'), summary: i18n.__('clearContent') }
|
|
462
466
|
]
|
|
463
467
|
},
|
|
464
|
-
commonHelpLinks()
|
|
468
|
+
commonHelpLinks()[0],
|
|
469
|
+
commonHelpLinks()[1]
|
|
465
470
|
])
|
|
466
471
|
|
|
467
472
|
const mainDefinition = [{ name: 'command', defaultOption: true }]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const { getCommandLineArgsCustom } = require('../../utils/parsedCLIOptions')
|
|
2
|
+
const constants = require('../../cliConstants')
|
|
3
|
+
const paramHandler = require('../../utils/paramsUtil/paramHandler')
|
|
4
|
+
|
|
5
|
+
const getAuditConfig = async (contrastConf, command, argv) => {
|
|
6
|
+
const auditParameters = await getCommandLineArgsCustom(
|
|
7
|
+
contrastConf,
|
|
8
|
+
command,
|
|
9
|
+
argv,
|
|
10
|
+
constants.commandLineDefinitions.auditOptionDefinitions
|
|
11
|
+
)
|
|
12
|
+
const paramsAuth = paramHandler.getAuth(auditParameters)
|
|
13
|
+
const javaAgreement = paramHandler.getAgreement()
|
|
14
|
+
return { ...paramsAuth, ...auditParameters, ...javaAgreement }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = {
|
|
18
|
+
getAuditConfig
|
|
19
|
+
}
|