@contrast/contrast 1.0.3 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierignore +1 -0
- package/README.md +20 -14
- package/dist/audit/languageAnalysisEngine/{langugageAnalysisFactory.js → languageAnalysisFactory.js} +2 -12
- package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +62 -234
- package/dist/audit/languageAnalysisEngine/report/models/reportLibraryModel.js +19 -0
- package/dist/audit/languageAnalysisEngine/report/models/reportListModel.js +24 -0
- package/dist/audit/languageAnalysisEngine/report/models/reportSeverityModel.js +10 -0
- package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +24 -129
- package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +85 -0
- package/dist/audit/languageAnalysisEngine/sendSnapshot.js +3 -1
- package/dist/commands/audit/auditController.js +6 -3
- package/dist/commands/scan/processScan.js +4 -3
- package/dist/common/HTTPClient.js +19 -26
- package/dist/common/versionChecker.js +14 -12
- package/dist/constants/constants.js +1 -1
- package/dist/constants/lambda.js +3 -1
- package/dist/constants/locales.js +17 -10
- package/dist/constants.js +5 -1
- package/dist/index.js +2 -2
- package/dist/lambda/help.js +22 -14
- package/dist/lambda/lambda.js +6 -0
- package/dist/scan/models/groupedResultsModel.js +10 -0
- package/dist/scan/models/resultContentModel.js +2 -0
- package/dist/scan/models/scanResultsModel.js +11 -0
- package/dist/scan/scan.js +90 -95
- package/dist/scan/scanConfig.js +1 -1
- package/dist/utils/getConfig.js +3 -0
- package/package.json +2 -2
- package/src/audit/languageAnalysisEngine/{langugageAnalysisFactory.js → languageAnalysisFactory.js} +2 -16
- package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +127 -0
- package/src/audit/languageAnalysisEngine/report/models/reportLibraryModel.ts +30 -0
- package/src/audit/languageAnalysisEngine/report/models/reportListModel.ts +32 -0
- package/src/audit/languageAnalysisEngine/report/models/reportSeverityModel.ts +9 -0
- package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +56 -0
- package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +110 -0
- package/src/audit/languageAnalysisEngine/sendSnapshot.js +3 -1
- package/src/commands/audit/auditController.ts +12 -3
- package/src/commands/scan/processScan.js +4 -6
- package/src/common/HTTPClient.js +31 -38
- package/src/common/errorHandling.ts +0 -1
- package/src/common/versionChecker.ts +24 -22
- package/src/constants/constants.js +1 -1
- package/src/constants/lambda.js +3 -1
- package/src/constants/locales.js +20 -10
- package/src/constants.js +7 -1
- package/src/index.ts +2 -3
- package/src/lambda/help.ts +22 -14
- package/src/lambda/lambda.ts +8 -0
- package/src/scan/models/groupedResultsModel.ts +18 -0
- package/src/scan/models/resultContentModel.ts +86 -0
- package/src/scan/models/scanResultsModel.ts +52 -0
- package/src/scan/scan.ts +192 -0
- package/src/scan/scanConfig.js +1 -1
- package/src/scan/scanController.js +2 -0
- package/src/utils/getConfig.ts +10 -0
- package/dist/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +0 -17
- package/dist/audit/languageAnalysisEngine/report/newReportingFeature.js +0 -81
- package/src/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +0 -27
- package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.js +0 -303
- package/src/audit/languageAnalysisEngine/report/newReportingFeature.js +0 -124
- package/src/audit/languageAnalysisEngine/report/reportingFeature.js +0 -190
- package/src/scan/scan.js +0 -195
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.findNameAndVersion = exports.severityCount = exports.convertGenericToTypedLibraries = exports.findHighestSeverityCVE = void 0;
|
|
7
|
+
const reportLibraryModel_1 = require("../models/reportLibraryModel");
|
|
8
|
+
const reportSeverityModel_1 = require("../models/reportSeverityModel");
|
|
9
|
+
const constants_1 = __importDefault(require("../../../languageAnalysisEngine/constants"));
|
|
10
|
+
const { supportedLanguages: { GO } } = constants_1.default;
|
|
11
|
+
function findHighestSeverityCVE(cveArray) {
|
|
12
|
+
if (cveArray.find(cve => cve.cvss3SeverityCode === 'CRITICAL' || cve.severityCode === 'CRITICAL')) {
|
|
13
|
+
return new reportSeverityModel_1.ReportSeverityModel('CRITICAL', 1);
|
|
14
|
+
}
|
|
15
|
+
else if (cveArray.find(cve => cve.cvss3SeverityCode === 'HIGH' || cve.severityCode === 'HIGH')) {
|
|
16
|
+
return new reportSeverityModel_1.ReportSeverityModel('HIGH', 2);
|
|
17
|
+
}
|
|
18
|
+
else if (cveArray.find(cve => cve.cvss3SeverityCode === 'MEDIUM' || cve.severityCode === 'MEDIUM')) {
|
|
19
|
+
return new reportSeverityModel_1.ReportSeverityModel('MEDIUM', 3);
|
|
20
|
+
}
|
|
21
|
+
else if (cveArray.find(cve => cve.cvss3SeverityCode === 'LOW' || cve.severityCode === 'LOW')) {
|
|
22
|
+
return new reportSeverityModel_1.ReportSeverityModel('LOW', 4);
|
|
23
|
+
}
|
|
24
|
+
else if (cveArray.find(cve => cve.cvss3SeverityCode === 'NOTE' || cve.severityCode === 'NOTE')) {
|
|
25
|
+
return new reportSeverityModel_1.ReportSeverityModel('NOTE', 5);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.findHighestSeverityCVE = findHighestSeverityCVE;
|
|
29
|
+
function convertGenericToTypedLibraries(libraries) {
|
|
30
|
+
return Object.entries(libraries).map(([name, cveArray]) => {
|
|
31
|
+
return new reportLibraryModel_1.ReportLibraryModel(name, cveArray);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
exports.convertGenericToTypedLibraries = convertGenericToTypedLibraries;
|
|
35
|
+
function severityCount(vulnerableLibraries) {
|
|
36
|
+
const severityCount = {
|
|
37
|
+
critical: 0,
|
|
38
|
+
high: 0,
|
|
39
|
+
medium: 0,
|
|
40
|
+
low: 0,
|
|
41
|
+
note: 0
|
|
42
|
+
};
|
|
43
|
+
vulnerableLibraries.forEach(lib => {
|
|
44
|
+
lib.cveArray.forEach(cve => {
|
|
45
|
+
if (cve.cvss3SeverityCode === 'CRITICAL' ||
|
|
46
|
+
cve.severityCode === 'CRITICAL') {
|
|
47
|
+
severityCount['critical'] += 1;
|
|
48
|
+
}
|
|
49
|
+
else if (cve.cvss3SeverityCode === 'HIGH' ||
|
|
50
|
+
cve.severityCode === 'HIGH') {
|
|
51
|
+
severityCount['high'] += 1;
|
|
52
|
+
}
|
|
53
|
+
else if (cve.cvss3SeverityCode === 'MEDIUM' ||
|
|
54
|
+
cve.severityCode === 'MEDIUM') {
|
|
55
|
+
severityCount['medium'] += 1;
|
|
56
|
+
}
|
|
57
|
+
else if (cve.cvss3SeverityCode === 'LOW' ||
|
|
58
|
+
cve.severityCode === 'LOW') {
|
|
59
|
+
severityCount['low'] += 1;
|
|
60
|
+
}
|
|
61
|
+
else if (cve.cvss3SeverityCode === 'NOTE' ||
|
|
62
|
+
cve.severityCode === 'NOTE') {
|
|
63
|
+
severityCount['note'] += 1;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
return severityCount;
|
|
68
|
+
}
|
|
69
|
+
exports.severityCount = severityCount;
|
|
70
|
+
function findNameAndVersion(library, config) {
|
|
71
|
+
if (config.language.toUpperCase() === GO) {
|
|
72
|
+
const nameVersion = library.name.split('@');
|
|
73
|
+
const name = nameVersion[0];
|
|
74
|
+
const version = nameVersion[1];
|
|
75
|
+
return { name, version };
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
const splitLibraryName = library.name.split('/');
|
|
79
|
+
const nameVersion = splitLibraryName[1].split('@');
|
|
80
|
+
const name = nameVersion[0];
|
|
81
|
+
const version = nameVersion[1];
|
|
82
|
+
return { name, version };
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.findNameAndVersion = findNameAndVersion;
|
|
@@ -24,7 +24,9 @@ const newSendSnapShot = async (analysis, applicationId) => {
|
|
|
24
24
|
.sendSnapshot(requestBody, analysis.config)
|
|
25
25
|
.then(res => {
|
|
26
26
|
if (res.statusCode === 201) {
|
|
27
|
-
|
|
27
|
+
if (analysis.config.host !== 'https://ce.contrastsecurity.com/') {
|
|
28
|
+
displaySnapshotSuccessMessage(analysis.config);
|
|
29
|
+
}
|
|
28
30
|
return res.body;
|
|
29
31
|
}
|
|
30
32
|
else {
|
|
@@ -7,7 +7,7 @@ exports.startAudit = void 0;
|
|
|
7
7
|
const catalogueApplication_1 = require("../../audit/catalogueApplication/catalogueApplication");
|
|
8
8
|
const commonApi_1 = __importDefault(require("../../audit/languageAnalysisEngine/commonApi"));
|
|
9
9
|
const identifyLanguageAE = require('./../../audit/languageAnalysisEngine');
|
|
10
|
-
const languageFactory = require('
|
|
10
|
+
const languageFactory = require('../../audit/languageAnalysisEngine/languageAnalysisFactory');
|
|
11
11
|
const dealWithNoAppId = async (config) => {
|
|
12
12
|
let appID;
|
|
13
13
|
try {
|
|
@@ -17,9 +17,12 @@ const dealWithNoAppId = async (config) => {
|
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
catch (e) {
|
|
20
|
-
|
|
20
|
+
if (e.toString().includes('tunneling socket could not be established')) {
|
|
21
|
+
console.log(e.message);
|
|
22
|
+
console.log('There seems to be an issue with your proxy, please check and try again');
|
|
23
|
+
}
|
|
24
|
+
process.exit(1);
|
|
21
25
|
}
|
|
22
|
-
console.log(appID);
|
|
23
26
|
return appID;
|
|
24
27
|
};
|
|
25
28
|
const startAudit = async (config) => {
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const { startScan } = require('../../scan/scanController');
|
|
3
|
-
const { formatScanOutput } = require('../../scan/scan');
|
|
4
3
|
const { scanUsageGuide } = require('../../scan/help');
|
|
5
4
|
const scanConfig = require('../../scan/scanConfig');
|
|
6
5
|
const { saveScanFile } = require('../../utils/saveFile');
|
|
6
|
+
const { ScanResultsModel } = require('../../scan/models/scanResultsModel');
|
|
7
|
+
const { formatScanOutput } = require('../../scan/scan');
|
|
7
8
|
const processScan = async (argvMain) => {
|
|
8
9
|
let config = scanConfig.getScanConfig(argvMain);
|
|
9
|
-
let scanResults = await startScan(config);
|
|
10
|
+
let scanResults = new ScanResultsModel(await startScan(config));
|
|
10
11
|
if (scanResults) {
|
|
11
|
-
formatScanOutput(scanResults
|
|
12
|
+
formatScanOutput(scanResults);
|
|
12
13
|
}
|
|
13
14
|
if (config.save !== undefined) {
|
|
14
15
|
await saveScanFile(config, scanResults);
|
|
@@ -77,7 +77,9 @@ HTTPClient.prototype.getScanId = function getScanId(config, codeArtifactId) {
|
|
|
77
77
|
options.url = url;
|
|
78
78
|
options.body = {
|
|
79
79
|
codeArtifactId: codeArtifactId,
|
|
80
|
-
label:
|
|
80
|
+
label: config.label
|
|
81
|
+
? config.label
|
|
82
|
+
: `Started by CLI tool at ${new Date().toString()}`
|
|
81
83
|
};
|
|
82
84
|
return requestUtils.sendRequest({ method: 'post', options });
|
|
83
85
|
};
|
|
@@ -143,28 +145,28 @@ HTTPClient.prototype.catalogueCommand = function catalogueCommand(config) {
|
|
|
143
145
|
return requestUtils.sendRequest({ method: 'post', options });
|
|
144
146
|
};
|
|
145
147
|
HTTPClient.prototype.sendSnapshot = function sendSnapshot(requestBody, config) {
|
|
148
|
+
if (config.language.toUpperCase() === 'RUBY') {
|
|
149
|
+
console.log('sendSnapshot requestBody', requestBody.snapshot.ruby);
|
|
150
|
+
}
|
|
146
151
|
const options = _.cloneDeep(this.requestOptions);
|
|
147
152
|
let url = createSnapshotURL(config);
|
|
148
153
|
options.url = url;
|
|
149
154
|
options.body = requestBody;
|
|
150
155
|
return requestUtils.sendRequest({ method: 'post', options });
|
|
151
156
|
};
|
|
152
|
-
HTTPClient.prototype.
|
|
153
|
-
const options = _.cloneDeep(this.requestOptions);
|
|
154
|
-
let url = createReportUrl(config);
|
|
155
|
-
options.url = url;
|
|
156
|
-
return requestUtils.sendRequest({ method: 'get', options });
|
|
157
|
-
};
|
|
158
|
-
HTTPClient.prototype.getSpecificReport = function getSpecificReport(config, reportId) {
|
|
157
|
+
HTTPClient.prototype.getReportById = function getReportById(config, reportId) {
|
|
159
158
|
const options = _.cloneDeep(this.requestOptions);
|
|
160
|
-
|
|
161
|
-
|
|
159
|
+
if (config.ignoreDev) {
|
|
160
|
+
options.url = createSpecificReportWithProdUrl(config, reportId);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
options.url = createSpecificReportUrl(config, reportId);
|
|
164
|
+
}
|
|
162
165
|
return requestUtils.sendRequest({ method: 'get', options });
|
|
163
166
|
};
|
|
164
|
-
HTTPClient.prototype.getLibraryVulnerabilities = function getLibraryVulnerabilities(
|
|
167
|
+
HTTPClient.prototype.getLibraryVulnerabilities = function getLibraryVulnerabilities(config, requestBody) {
|
|
165
168
|
const options = _.cloneDeep(this.requestOptions);
|
|
166
|
-
|
|
167
|
-
options.url = url;
|
|
169
|
+
options.url = createLibraryVulnerabilitiesUrl(config);
|
|
168
170
|
options.body = requestBody;
|
|
169
171
|
return requestUtils.sendRequest({ method: 'put', options });
|
|
170
172
|
};
|
|
@@ -174,12 +176,6 @@ HTTPClient.prototype.getAppId = function getAppId(config) {
|
|
|
174
176
|
options.url = url;
|
|
175
177
|
return requestUtils.sendRequest({ method: 'get', options });
|
|
176
178
|
};
|
|
177
|
-
HTTPClient.prototype.getDependencyTree = function getReport(orgUuid, appId, reportId) {
|
|
178
|
-
const options = _.cloneDeep(this.requestOptions);
|
|
179
|
-
let url = createGetDependencyTree(options.uri, orgUuid, appId, reportId);
|
|
180
|
-
options.url = url;
|
|
181
|
-
return requestUtils.sendRequest({ method: 'get', options });
|
|
182
|
-
};
|
|
183
179
|
function getServerlessHost(config = {}) {
|
|
184
180
|
const originalHost = config?.host || config?.get('host');
|
|
185
181
|
const host = originalHost?.endsWith('/')
|
|
@@ -271,18 +267,15 @@ const createAppNameUrl = config => {
|
|
|
271
267
|
function createLibraryVulnerabilitiesUrl(config) {
|
|
272
268
|
return `${config.host}/Contrast/api/ng/${config.organizationId}/libraries/artifactsByGroupNameVersion`;
|
|
273
269
|
}
|
|
274
|
-
function createReportUrl(config) {
|
|
275
|
-
return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/${config.applicationId}/reports`;
|
|
276
|
-
}
|
|
277
270
|
function createSpecificReportUrl(config, reportId) {
|
|
278
|
-
return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/${config.applicationId}/reports/${reportId}
|
|
271
|
+
return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/${config.applicationId}/reports/${reportId}`;
|
|
272
|
+
}
|
|
273
|
+
function createSpecificReportWithProdUrl(config, reportId) {
|
|
274
|
+
return createSpecificReportUrl(config, reportId).concat(`?nodesToInclude=PROD`);
|
|
279
275
|
}
|
|
280
276
|
function createDataUrl() {
|
|
281
277
|
return `https://ardy.contrastsecurity.com/production`;
|
|
282
278
|
}
|
|
283
|
-
const createGetDependencyTree = (protocol, orgUuid, appId, reportId) => {
|
|
284
|
-
return `${protocol}/Contrast/api/ng/sca/organizations/${orgUuid}/applications/${appId}/reports/${reportId}`;
|
|
285
|
-
};
|
|
286
279
|
function createSbomCycloneDXUrl(config) {
|
|
287
280
|
return `${config.host}/Contrast/api/ng/${config.organizationId}/applications/${config.applicationId}/libraries/sbom/cyclonedx`;
|
|
288
281
|
}
|
|
@@ -9,18 +9,20 @@ const constants_1 = require("../constants/constants");
|
|
|
9
9
|
const boxen_1 = __importDefault(require("boxen"));
|
|
10
10
|
const chalk_1 = __importDefault(require("chalk"));
|
|
11
11
|
const semver_1 = __importDefault(require("semver"));
|
|
12
|
-
async function findLatestCLIVersion() {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
12
|
+
async function findLatestCLIVersion(updateMessageHidden) {
|
|
13
|
+
if (!updateMessageHidden) {
|
|
14
|
+
const latestCLIVersion = await (0, latest_version_1.default)('@contrast/contrast');
|
|
15
|
+
if (semver_1.default.lt(constants_1.APP_VERSION, latestCLIVersion)) {
|
|
16
|
+
const updateAvailableMessage = `Update available ${chalk_1.default.yellow(constants_1.APP_VERSION)} → ${chalk_1.default.green(latestCLIVersion)}`;
|
|
17
|
+
const npmUpdateAvailableCommand = `Run ${chalk_1.default.cyan('npm i @contrast/contrast -g')} to update via npm`;
|
|
18
|
+
const homebrewUpdateAvailableCommand = `Run ${chalk_1.default.cyan('brew install contrastsecurity/tap/contrast')} to update via brew`;
|
|
19
|
+
console.log((0, boxen_1.default)(`${updateAvailableMessage}\n${npmUpdateAvailableCommand}\n\n${homebrewUpdateAvailableCommand}`, {
|
|
20
|
+
titleAlignment: 'center',
|
|
21
|
+
margin: 1,
|
|
22
|
+
padding: 1,
|
|
23
|
+
align: 'center'
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
28
|
exports.findLatestCLIVersion = findLatestCLIVersion;
|
|
@@ -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.4';
|
|
16
16
|
const TIMEOUT = 120000;
|
|
17
17
|
const AUTH_UI_URL = 'https://cli-auth.contrastsecurity.com';
|
|
18
18
|
const AUTH_CALLBACK_URL = 'https://cli-auth-api.contrastsecurity.com';
|
package/dist/constants/lambda.js
CHANGED
|
@@ -25,9 +25,11 @@ const lambda = {
|
|
|
25
25
|
loadingFunctionList: 'Loading lambda function list',
|
|
26
26
|
functionsFound: '{{count}} functions found',
|
|
27
27
|
noFunctionsFound: 'No functions found',
|
|
28
|
-
failedToLoadFunctions: '
|
|
28
|
+
failedToLoadFunctions: 'Failed to load lambda functions',
|
|
29
29
|
availableForScan: '{{icon}} {{count}} available for scan',
|
|
30
30
|
runtimeCount: '----- {{runtime}} ({{count}}) -----',
|
|
31
|
+
gatherResults: 'Gathering results...',
|
|
32
|
+
doneGatherResults: 'Done gathering results',
|
|
31
33
|
whatHappenedTitle: 'What happened:',
|
|
32
34
|
whatHappenedItem: '{{policy}} have:\n{{comments}}\n',
|
|
33
35
|
recommendation: 'Recommendation:',
|
|
@@ -10,8 +10,6 @@ const en_locales = () => {
|
|
|
10
10
|
snapshotHostMessage: " No host supplied. Using default host 'app.contrastsecurity.com'. Please ensure this is correct.",
|
|
11
11
|
vulnerabilitiesSuccessMessage: ' Vulnerability data successfully retrieved',
|
|
12
12
|
vulnerabilitiesFailureMessage: ' Unable to retrieve library vulnerabilities from Team Server.',
|
|
13
|
-
reportSuccessMessage: ' Report successfully retrieved',
|
|
14
|
-
reportFailureMessage: ' Unable to generate library report.',
|
|
15
13
|
catchErrorMessage: 'Contrast UI error: ',
|
|
16
14
|
dependenciesNote: 'Please Note: We currently only support projects with one .csproj AND *.package.lock.json',
|
|
17
15
|
languageAnalysisFailureMessage: 'LANGUAGE ANALYSIS FAILED',
|
|
@@ -111,7 +109,7 @@ const en_locales = () => {
|
|
|
111
109
|
constantsCount: "The number of CVE's that must be exceeded to fail a build",
|
|
112
110
|
constantsHeader: 'CodeSec by Contrast Security',
|
|
113
111
|
constantsPrerequisitesContentScanLanguages: 'Java & JavaScript supported',
|
|
114
|
-
constantsContrastContent: 'Use the Contrast CLI to run a scan(Java, JavaScript and .NET ) or lambda command (Java and Python) to find your vulnerabilities and start securing your code.',
|
|
112
|
+
constantsContrastContent: 'Use the Contrast CLI to run a scan (Java, JavaScript and .NET ) or lambda command (Java and Python) to find your vulnerabilities and start securing your code.',
|
|
115
113
|
constantsUsageGuideContentRecommendation: 'Our recommendation is that this is invoked as part of a CI pipeline so that running the cli is automated as part of your build process.',
|
|
116
114
|
constantsPrerequisitesHeader: 'Pre-requisites',
|
|
117
115
|
constantsAuthUsageHeader: 'Usage',
|
|
@@ -175,7 +173,8 @@ const en_locales = () => {
|
|
|
175
173
|
constantsTags: 'Apply labels to an application. Labels must be formatted as a comma-delimited list. Example - label1,label2,label3',
|
|
176
174
|
constantsCode: 'Add the application code this application should use in the Contrast UI',
|
|
177
175
|
constantsIgnoreCertErrors: ' For EOP users with a local Teamserver install, this will bypass the SSL certificate and recognise a self signed certificate.',
|
|
178
|
-
constantsSave: ' Saves the Scan Results
|
|
176
|
+
constantsSave: ' Saves the Scan Results SARIF to file.',
|
|
177
|
+
scanLabel: "adds a label to the scan - defaults to 'Started by CLI tool at current date'",
|
|
179
178
|
constantsIgnoreDev: 'Combined with the --report command excludes developer dependencies from the vulnerabilities report. By default all dependencies are included in a report.',
|
|
180
179
|
constantsCommands: 'Commands',
|
|
181
180
|
constantsScanOptions: 'Scan Options',
|
|
@@ -184,7 +183,7 @@ const en_locales = () => {
|
|
|
184
183
|
ignoreDevDep: 'No private libraries that are not scoped detected',
|
|
185
184
|
foundExistingProjectScan: 'Found existing project...',
|
|
186
185
|
projectCreatedScan: 'Project created',
|
|
187
|
-
uploadingScan: 'Uploading
|
|
186
|
+
uploadingScan: 'Uploading file to scan.',
|
|
188
187
|
uploadingScanSuccessful: 'Uploaded file successfully.',
|
|
189
188
|
uploadingScanFail: 'Unable to upload the file.',
|
|
190
189
|
waitingTimedOut: 'Timed out.',
|
|
@@ -194,6 +193,7 @@ const en_locales = () => {
|
|
|
194
193
|
specifyFileScanError: 'Java Scan requires a .war or .jar file. Javascript Scan requires a .js or .zip file.\nTo start a Scan enter "contrast scan -f <path-to-file>"',
|
|
195
194
|
populateProjectIdMessage: 'project ID is %s',
|
|
196
195
|
genericServiceError: 'returned with status code %s',
|
|
196
|
+
projectIdError: 'Your project ID is %s please check this is correct',
|
|
197
197
|
permissionsError: 'You do not have the correct permissions here. \n Contact support@contrastsecurity.com to get this fixed.',
|
|
198
198
|
scanErrorFileMessage: 'We only accept the following file types: \nJava - .jar, .war \nJavaScript - .js or .zip files',
|
|
199
199
|
helpAuthSummary: 'Authenticate Contrast using your Github or Google account',
|
|
@@ -231,13 +231,16 @@ const en_locales = () => {
|
|
|
231
231
|
searchingScanFileDirectory: 'Searching for file to scan from %s...',
|
|
232
232
|
scanHeader: 'Contrast Scan CLI',
|
|
233
233
|
authHeader: 'Auth',
|
|
234
|
-
lambdaHeader: 'Contrast
|
|
234
|
+
lambdaHeader: 'Contrast Lambda CLI',
|
|
235
235
|
lambdaSummary: 'Performs static security scan on an AWS Lambda Function.\nProduces CVE (Vulnerable Dependencies) and Least Privilege violations/remediation results.',
|
|
236
236
|
lambdaUsage: 'contrast lambda --function-name <function> [options]',
|
|
237
|
-
lambdaPrerequisitesContent: '
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
237
|
+
lambdaPrerequisitesContent: '',
|
|
238
|
+
lambdaPrerequisitesContentLambdaLanguages: 'Supported runtimes: Java & Python',
|
|
239
|
+
lambdaPrerequisitesContentLambdaDescriptionTitle: 'AWS Requirements\n',
|
|
240
|
+
lambdaPrerequisitesContentLambdaDescription: 'Make sure you have the AWS credentials configured on your local environment. \nYou need the following AWS permissions configured on your IAM user:\n - Lambda: GetFunction, GetLayerVersionֿ\n - IAM: GetRolePolicy, GetPolicy, GetPolicyVersion, ListRolePolicies, ListAttachedRolePolicies',
|
|
241
|
+
scanFileNameOption: '-f, --file',
|
|
242
|
+
lambdaFunctionNameOption: '-f, --function-name',
|
|
243
|
+
lambdaListFunctionsOption: '-l, --list-functions',
|
|
241
244
|
lambdaEndpointOption: '-e, --endpoint-url',
|
|
242
245
|
lambdaRegionOption: '-r, --region',
|
|
243
246
|
lambdaProfileOption: '-p, --profile',
|
|
@@ -290,6 +293,10 @@ const en_locales = () => {
|
|
|
290
293
|
auditSBOMSaveSuccess: '\n Software Bill of Materials (SBOM) saved successfully',
|
|
291
294
|
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.')}`,
|
|
292
295
|
auditBadFiletypeSpecifiedForSave: `\n ${chalk.yellow.bold('Bad file type specified for --save option. Use audit --help to see valid --save options.')}`,
|
|
296
|
+
auditReportWaiting: 'Waiting for report...',
|
|
297
|
+
auditReportFail: 'Report Retrieval Failed, please try again',
|
|
298
|
+
auditReportSuccessMessage: ' Report successfully retrieved',
|
|
299
|
+
auditReportFailureMessage: ' Unable to generate library report.',
|
|
293
300
|
...lambda
|
|
294
301
|
};
|
|
295
302
|
};
|
package/dist/constants.js
CHANGED
|
@@ -116,6 +116,10 @@ const scanOptionDefinitions = [
|
|
|
116
116
|
alias: 's',
|
|
117
117
|
description: '{bold ' + i18n.__('constantsOptional') + '}:' + i18n.__('constantsSave')
|
|
118
118
|
},
|
|
119
|
+
{
|
|
120
|
+
name: 'label',
|
|
121
|
+
description: '{bold ' + i18n.__('constantsOptional') + '}:' + i18n.__('scanLabel')
|
|
122
|
+
},
|
|
119
123
|
{
|
|
120
124
|
name: 'help',
|
|
121
125
|
alias: 'h',
|
|
@@ -294,7 +298,7 @@ const mainUsageGuide = commandLineUsage([
|
|
|
294
298
|
]
|
|
295
299
|
},
|
|
296
300
|
{
|
|
297
|
-
content: '{underline https://
|
|
301
|
+
content: '{underline https://developer.contrastsecurity.com/} \n For technical support head to {underline https://support.contrastsecurity.com}'
|
|
298
302
|
}
|
|
299
303
|
]);
|
|
300
304
|
const mainDefinition = [{ name: 'command', defaultOption: true }];
|
package/dist/index.js
CHANGED
|
@@ -36,12 +36,12 @@ const start = async () => {
|
|
|
36
36
|
argvMain.includes('--v') ||
|
|
37
37
|
argvMain.includes('--version')) {
|
|
38
38
|
console.log(constants_2.APP_VERSION);
|
|
39
|
-
await (0, versionChecker_1.findLatestCLIVersion)();
|
|
39
|
+
await (0, versionChecker_1.findLatestCLIVersion)(config.get('updateMessageHidden'));
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
42
|
config.set('numOfRuns', config.get('numOfRuns') + 1);
|
|
43
43
|
if (config.get('numOfRuns') >= 5) {
|
|
44
|
-
await (0, versionChecker_1.findLatestCLIVersion)();
|
|
44
|
+
await (0, versionChecker_1.findLatestCLIVersion)(config.get('updateMessageHidden'));
|
|
45
45
|
config.set('numOfRuns', 0);
|
|
46
46
|
}
|
|
47
47
|
if (command === 'config') {
|
package/dist/lambda/help.js
CHANGED
|
@@ -13,7 +13,15 @@ const lambdaUsageGuide = (0, command_line_usage_1.default)([
|
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
15
|
header: i18n_1.default.__('constantsPrerequisitesHeader'),
|
|
16
|
-
content: [
|
|
16
|
+
content: [
|
|
17
|
+
'{bold ' +
|
|
18
|
+
i18n_1.default.__('lambdaPrerequisitesContentLambdaLanguages') +
|
|
19
|
+
'}\n\n' +
|
|
20
|
+
'{bold ' +
|
|
21
|
+
i18n_1.default.__('lambdaPrerequisitesContentLambdaDescriptionTitle') +
|
|
22
|
+
'}' +
|
|
23
|
+
i18n_1.default.__('lambdaPrerequisitesContentLambdaDescription')
|
|
24
|
+
]
|
|
17
25
|
},
|
|
18
26
|
{
|
|
19
27
|
header: i18n_1.default.__('constantsUsage'),
|
|
@@ -23,44 +31,44 @@ const lambdaUsageGuide = (0, command_line_usage_1.default)([
|
|
|
23
31
|
header: i18n_1.default.__('constantsOptions'),
|
|
24
32
|
content: [
|
|
25
33
|
{
|
|
26
|
-
name: i18n_1.default.__('lambdaFunctionNameOption'),
|
|
34
|
+
name: '{bold ' + i18n_1.default.__('lambdaFunctionNameOption') + '}',
|
|
27
35
|
summary: i18n_1.default.__('lambdaFunctionNameSummery')
|
|
28
36
|
},
|
|
29
37
|
{
|
|
30
|
-
name: i18n_1.default.__('lambdaListFunctionsOption'),
|
|
38
|
+
name: '{bold ' + i18n_1.default.__('lambdaListFunctionsOption') + '}',
|
|
31
39
|
summary: i18n_1.default.__('lambdaListFunctionsSummery')
|
|
32
40
|
},
|
|
33
41
|
{
|
|
34
|
-
name: i18n_1.default.__('lambdaEndpointOption'),
|
|
35
|
-
summary: '{
|
|
42
|
+
name: '{bold ' + i18n_1.default.__('lambdaEndpointOption') + '}',
|
|
43
|
+
summary: '{bold ' +
|
|
36
44
|
i18n_1.default.__('constantsOptional') +
|
|
37
45
|
'}: ' +
|
|
38
46
|
i18n_1.default.__('lambdaEndpointSummery')
|
|
39
47
|
},
|
|
40
48
|
{
|
|
41
|
-
name: i18n_1.default.__('lambdaRegionOption'),
|
|
42
|
-
summary: '{
|
|
49
|
+
name: '{bold ' + i18n_1.default.__('lambdaRegionOption') + '}',
|
|
50
|
+
summary: '{bold ' +
|
|
43
51
|
i18n_1.default.__('constantsOptional') +
|
|
44
52
|
'}: ' +
|
|
45
53
|
i18n_1.default.__('lambdaRegionSummery')
|
|
46
54
|
},
|
|
47
55
|
{
|
|
48
|
-
name: i18n_1.default.__('lambdaProfileOption'),
|
|
49
|
-
summary: '{
|
|
56
|
+
name: '{bold ' + i18n_1.default.__('lambdaProfileOption') + '}',
|
|
57
|
+
summary: '{bold ' +
|
|
50
58
|
i18n_1.default.__('constantsOptional') +
|
|
51
59
|
'}: ' +
|
|
52
60
|
i18n_1.default.__('lambdaProfileSummery')
|
|
53
61
|
},
|
|
54
62
|
{
|
|
55
|
-
name: i18n_1.default.__('lambdaJsonOption'),
|
|
56
|
-
summary: '{
|
|
63
|
+
name: '{bold ' + i18n_1.default.__('lambdaJsonOption') + '}',
|
|
64
|
+
summary: '{bold ' +
|
|
57
65
|
i18n_1.default.__('constantsOptional') +
|
|
58
66
|
'}: ' +
|
|
59
67
|
i18n_1.default.__('lambdaJsonSummery')
|
|
60
68
|
},
|
|
61
69
|
{
|
|
62
|
-
name: i18n_1.default.__('lambdaVerboseOption'),
|
|
63
|
-
summary: '{
|
|
70
|
+
name: '{bold ' + i18n_1.default.__('lambdaVerboseOption') + '}',
|
|
71
|
+
summary: '{bold ' +
|
|
64
72
|
i18n_1.default.__('constantsOptional') +
|
|
65
73
|
'}: ' +
|
|
66
74
|
i18n_1.default.__('lambdaVerbosSummery')
|
|
@@ -73,7 +81,7 @@ const lambdaUsageGuide = (0, command_line_usage_1.default)([
|
|
|
73
81
|
]
|
|
74
82
|
},
|
|
75
83
|
{
|
|
76
|
-
content: '{underline https://www.contrastsecurity.com}'
|
|
84
|
+
content: '{underline https://www.contrastsecurity.com/developer/codesec}'
|
|
77
85
|
}
|
|
78
86
|
]);
|
|
79
87
|
exports.lambdaUsageGuide = lambdaUsageGuide;
|
package/dist/lambda/lambda.js
CHANGED
|
@@ -18,6 +18,8 @@ const scanRequest_1 = require("./scanRequest");
|
|
|
18
18
|
const scanResults_1 = require("./scanResults");
|
|
19
19
|
const utils_1 = require("./utils");
|
|
20
20
|
const lambdaUtils_1 = require("./lambdaUtils");
|
|
21
|
+
const requestUtils_1 = require("../utils/requestUtils");
|
|
22
|
+
const oraWrapper_1 = __importDefault(require("../utils/oraWrapper"));
|
|
21
23
|
const failedStates = [
|
|
22
24
|
'UNSUPPORTED',
|
|
23
25
|
'EXCLUDED',
|
|
@@ -101,6 +103,10 @@ const actualProcessLambda = async (lambdaOptions) => {
|
|
|
101
103
|
description: failedScan.stateReasonText
|
|
102
104
|
});
|
|
103
105
|
}
|
|
106
|
+
const startGetherResultsSpinner = oraWrapper_1.default.returnOra(i18n_1.default.__('gatherResults'));
|
|
107
|
+
oraWrapper_1.default.startSpinner(startGetherResultsSpinner);
|
|
108
|
+
await (0, requestUtils_1.sleep)(15 * 1000);
|
|
109
|
+
oraWrapper_1.default.succeedSpinner(startGetherResultsSpinner, 'Done gathering results');
|
|
104
110
|
const resultsResponse = await (0, scanResults_1.getScanResults)(auth, params, scanId, functionArn);
|
|
105
111
|
if (jsonOutput) {
|
|
106
112
|
console.log(JSON.stringify(resultsResponse?.data?.results, null, 2));
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GroupedResultsModel = void 0;
|
|
4
|
+
class GroupedResultsModel {
|
|
5
|
+
constructor(ruleId) {
|
|
6
|
+
this.ruleId = ruleId;
|
|
7
|
+
this.lineInfoSet = new Set;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.GroupedResultsModel = GroupedResultsModel;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ScanResultsModel = void 0;
|
|
4
|
+
class ScanResultsModel {
|
|
5
|
+
constructor(scan) {
|
|
6
|
+
this.projectOverview = scan.projectOverview;
|
|
7
|
+
this.scanDetail = scan.scanDetail;
|
|
8
|
+
this.scanResultsInstances = scan.scanResultsInstances;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
exports.ScanResultsModel = ScanResultsModel;
|