@contrast/contrast 1.0.5 → 1.0.8
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 +0 -5
- package/dist/audit/autodetection/autoDetectLanguage.js +3 -3
- package/dist/audit/catalogueApplication/catalogueApplication.js +23 -5
- package/dist/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +4 -2
- package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +2 -1
- package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +2 -1
- package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +2 -1
- package/dist/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +5 -5
- package/dist/audit/languageAnalysisEngine/getProjectRootFilenames.js +9 -9
- package/dist/audit/languageAnalysisEngine/index.js +2 -2
- package/dist/audit/languageAnalysisEngine/languageAnalysisFactory.js +6 -27
- package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +25 -5
- package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +99 -20
- package/dist/audit/languageAnalysisEngine/report/models/reportListModel.js +2 -1
- package/dist/audit/languageAnalysisEngine/report/models/reportOutputModel.js +24 -0
- package/dist/audit/languageAnalysisEngine/report/models/reportSeverityModel.js +3 -1
- package/dist/audit/languageAnalysisEngine/report/models/severityCountModel.js +16 -0
- package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +35 -14
- package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +58 -47
- package/dist/audit/languageAnalysisEngine/sendSnapshot.js +65 -3
- package/dist/audit/save.js +29 -0
- package/dist/commands/audit/auditController.js +22 -6
- package/dist/commands/audit/help.js +24 -1
- package/dist/commands/audit/processAudit.js +8 -2
- package/dist/commands/audit/saveFile.js +7 -3
- package/dist/commands/scan/processScan.js +1 -1
- package/dist/commands/scan/sca/scaAnalysis.js +48 -11
- package/dist/common/HTTPClient.js +56 -15
- package/dist/common/errorHandling.js +6 -1
- package/dist/common/versionChecker.js +20 -5
- package/dist/constants/constants.js +13 -3
- package/dist/constants/locales.js +15 -12
- package/dist/constants.js +9 -4
- package/dist/index.js +4 -3
- package/dist/lambda/analytics.js +11 -0
- package/dist/lambda/lambda.js +35 -4
- package/dist/lambda/types.js +13 -0
- package/dist/sbom/generateSbom.js +4 -3
- package/dist/scaAnalysis/common/formatMessage.js +46 -1
- package/dist/scaAnalysis/common/treeUpload.js +1 -3
- package/dist/scaAnalysis/go/goAnalysis.js +17 -0
- package/dist/scaAnalysis/go/goParseDeps.js +158 -0
- package/dist/scaAnalysis/go/goReadDepFile.js +21 -0
- package/dist/scaAnalysis/java/analysis.js +11 -22
- package/dist/scaAnalysis/java/index.js +6 -6
- package/dist/scaAnalysis/java/javaBuildDepsParser.js +14 -1
- package/dist/scaAnalysis/javascript/analysis.js +110 -0
- package/dist/scaAnalysis/javascript/index.js +41 -0
- package/dist/scaAnalysis/php/analysis.js +89 -0
- package/dist/scaAnalysis/php/index.js +10 -0
- package/dist/scaAnalysis/python/analysis.js +42 -0
- package/dist/scaAnalysis/python/index.js +10 -0
- package/dist/scaAnalysis/ruby/analysis.js +226 -0
- package/dist/scaAnalysis/ruby/index.js +10 -0
- package/dist/scan/autoDetection.js +8 -4
- package/dist/scan/fileUtils.js +26 -8
- package/dist/scan/formatScanOutput.js +18 -17
- package/dist/scan/models/groupedResultsModel.js +1 -1
- package/dist/scan/models/scanResultsModel.js +3 -1
- package/dist/scan/populateProjectIdAndProjectName.js +2 -1
- package/dist/scan/scan.js +5 -3
- package/dist/scan/scanConfig.js +6 -1
- package/dist/scan/scanController.js +26 -6
- package/dist/scan/scanResults.js +20 -6
- package/dist/utils/commonApi.js +4 -1
- package/dist/utils/filterProjectPath.js +7 -2
- package/dist/utils/oraWrapper.js +5 -1
- package/package.json +13 -9
- package/src/audit/autodetection/autoDetectLanguage.ts +3 -3
- package/src/audit/catalogueApplication/catalogueApplication.js +28 -7
- package/src/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +11 -8
- package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +2 -1
- package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +2 -1
- package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +2 -1
- package/src/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +5 -5
- package/src/audit/languageAnalysisEngine/getProjectRootFilenames.js +11 -11
- package/src/audit/languageAnalysisEngine/index.js +2 -2
- package/src/audit/languageAnalysisEngine/languageAnalysisFactory.js +11 -31
- package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +35 -32
- package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +179 -25
- package/src/audit/languageAnalysisEngine/report/models/reportLibraryModel.ts +3 -3
- package/src/audit/languageAnalysisEngine/report/models/reportListModel.ts +18 -11
- package/src/audit/languageAnalysisEngine/report/models/reportOutputModel.ts +29 -0
- package/src/audit/languageAnalysisEngine/report/models/reportSeverityModel.ts +12 -3
- package/src/audit/languageAnalysisEngine/report/models/severityCountModel.ts +20 -0
- package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +50 -18
- package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +88 -66
- package/src/audit/languageAnalysisEngine/sendSnapshot.js +78 -3
- package/src/audit/save.js +32 -0
- package/src/commands/audit/auditController.ts +23 -15
- package/src/commands/audit/help.ts +24 -1
- package/src/commands/audit/processAudit.ts +7 -4
- package/src/commands/audit/saveFile.ts +5 -1
- package/src/commands/scan/processScan.js +2 -1
- package/src/commands/scan/sca/scaAnalysis.js +70 -29
- package/src/common/HTTPClient.js +72 -25
- package/src/common/errorHandling.ts +10 -1
- package/src/common/versionChecker.ts +24 -5
- package/src/constants/constants.js +13 -3
- package/src/constants/locales.js +15 -12
- package/src/constants.js +9 -4
- package/src/index.ts +5 -3
- package/src/lambda/analytics.ts +9 -0
- package/src/lambda/arn.ts +2 -1
- package/src/lambda/lambda.ts +37 -17
- package/src/lambda/types.ts +35 -0
- package/src/lambda/utils.ts +2 -7
- package/src/sbom/generateSbom.ts +1 -1
- package/src/scaAnalysis/common/formatMessage.js +51 -1
- package/src/scaAnalysis/common/treeUpload.js +1 -6
- package/src/scaAnalysis/go/goAnalysis.js +19 -0
- package/src/scaAnalysis/go/goParseDeps.js +203 -0
- package/src/scaAnalysis/go/goReadDepFile.js +30 -0
- package/src/scaAnalysis/java/analysis.js +15 -32
- package/src/scaAnalysis/java/index.js +6 -6
- package/src/scaAnalysis/java/javaBuildDepsParser.js +15 -2
- package/src/scaAnalysis/javascript/analysis.js +127 -0
- package/src/scaAnalysis/javascript/index.js +56 -0
- package/src/scaAnalysis/php/analysis.js +98 -0
- package/src/scaAnalysis/php/index.js +11 -0
- package/src/scaAnalysis/python/analysis.js +49 -0
- package/src/scaAnalysis/python/index.js +11 -0
- package/src/scaAnalysis/ruby/analysis.js +282 -0
- package/src/scaAnalysis/ruby/index.js +11 -0
- package/src/scan/autoDetection.js +11 -7
- package/src/scan/fileUtils.js +27 -8
- package/src/scan/formatScanOutput.ts +26 -18
- package/src/scan/models/groupedResultsModel.ts +3 -3
- package/src/scan/models/resultContentModel.ts +1 -1
- package/src/scan/models/scanResultsModel.ts +5 -2
- package/src/scan/populateProjectIdAndProjectName.js +3 -1
- package/src/scan/scan.ts +8 -6
- package/src/scan/scanConfig.js +5 -1
- package/src/scan/scanController.js +30 -9
- package/src/scan/scanResults.js +31 -10
- package/src/utils/commonApi.js +4 -1
- package/src/utils/filterProjectPath.js +6 -2
- package/src/utils/oraWrapper.js +6 -1
|
@@ -4,14 +4,29 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.isCorrectNodeVersion = exports.findLatestCLIVersion = void 0;
|
|
7
|
-
const latest_version_1 = __importDefault(require("latest-version"));
|
|
8
7
|
const constants_1 = require("../constants/constants");
|
|
9
8
|
const boxen_1 = __importDefault(require("boxen"));
|
|
10
9
|
const chalk_1 = __importDefault(require("chalk"));
|
|
11
10
|
const semver_1 = __importDefault(require("semver"));
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
const commonApi_1 = __importDefault(require("../utils/commonApi"));
|
|
12
|
+
const http2_1 = require("http2");
|
|
13
|
+
const getLatestVersion = async (config) => {
|
|
14
|
+
const client = commonApi_1.default.getHttpClient(config);
|
|
15
|
+
try {
|
|
16
|
+
const res = await client.getLatestVersion();
|
|
17
|
+
if (res.statusCode === http2_1.constants.HTTP_STATUS_OK) {
|
|
18
|
+
return res.body;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
async function findLatestCLIVersion(config) {
|
|
26
|
+
const messageHidden = config.get('updateMessageHidden');
|
|
27
|
+
if (!messageHidden) {
|
|
28
|
+
let latestCLIVersion = await getLatestVersion(config);
|
|
29
|
+
latestCLIVersion = latestCLIVersion.substring(8);
|
|
15
30
|
if (semver_1.default.lt(constants_1.APP_VERSION, latestCLIVersion)) {
|
|
16
31
|
const updateAvailableMessage = `Update available ${chalk_1.default.yellow(constants_1.APP_VERSION)} → ${chalk_1.default.green(latestCLIVersion)}`;
|
|
17
32
|
const npmUpdateAvailableCommand = `Run ${chalk_1.default.cyan('npm i @contrast/contrast -g')} to update via npm`;
|
|
@@ -27,6 +42,6 @@ async function findLatestCLIVersion(updateMessageHidden) {
|
|
|
27
42
|
}
|
|
28
43
|
exports.findLatestCLIVersion = findLatestCLIVersion;
|
|
29
44
|
async function isCorrectNodeVersion(currentVersion) {
|
|
30
|
-
return semver_1.default.satisfies(currentVersion, '>=16
|
|
45
|
+
return semver_1.default.satisfies(currentVersion, '>=16');
|
|
31
46
|
}
|
|
32
47
|
exports.isCorrectNodeVersion = isCorrectNodeVersion;
|
|
@@ -12,13 +12,18 @@ 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.8';
|
|
16
16
|
const TIMEOUT = 120000;
|
|
17
17
|
const HIGH_COLOUR = '#ff9900';
|
|
18
18
|
const CRITICAL_COLOUR = '#e35858';
|
|
19
19
|
const MEDIUM_COLOUR = '#f1c232';
|
|
20
|
-
const LOW_COLOUR = '#
|
|
20
|
+
const LOW_COLOUR = '#b7b7b7';
|
|
21
21
|
const NOTE_COLOUR = '#999999';
|
|
22
|
+
const CRITICAL_PRIORITY = 1;
|
|
23
|
+
const HIGH_PRIORITY = 2;
|
|
24
|
+
const MEDIUM_PRIORITY = 3;
|
|
25
|
+
const LOW_PRIORITY = 4;
|
|
26
|
+
const NOTE_PRIORITY = 5;
|
|
22
27
|
const AUTH_UI_URL = 'https://cli-auth.contrastsecurity.com';
|
|
23
28
|
const AUTH_CALLBACK_URL = 'https://cli-auth-api.contrastsecurity.com';
|
|
24
29
|
const SARIF_FILE = 'SARIF';
|
|
@@ -40,5 +45,10 @@ module.exports = {
|
|
|
40
45
|
MEDIUM_COLOUR,
|
|
41
46
|
LOW_COLOUR,
|
|
42
47
|
NOTE_COLOUR,
|
|
43
|
-
CE_URL
|
|
48
|
+
CE_URL,
|
|
49
|
+
CRITICAL_PRIORITY,
|
|
50
|
+
HIGH_PRIORITY,
|
|
51
|
+
MEDIUM_PRIORITY,
|
|
52
|
+
LOW_PRIORITY,
|
|
53
|
+
NOTE_PRIORITY
|
|
44
54
|
};
|
|
@@ -12,7 +12,7 @@ const en_locales = () => {
|
|
|
12
12
|
vulnerabilitiesFailureMessage: 'Unable to retrieve library vulnerabilities',
|
|
13
13
|
catchErrorMessage: 'Contrast UI error: ',
|
|
14
14
|
dependenciesNote: 'Please Note: We currently only support projects with one .csproj AND *.package.lock.json',
|
|
15
|
-
languageAnalysisFailureMessage: 'SCA
|
|
15
|
+
languageAnalysisFailureMessage: 'SCA audit Failure',
|
|
16
16
|
languageAnalysisFactoryFailureHeader: 'FAIL',
|
|
17
17
|
libraryAnalysisError: 'Please ensure the language parameter is set in accordance to the language specified on the project path.\nContrast CLI must be run in the same directory as the project manifest file OR the project_path parameter must be used to identify the directory containing the project manifest file.\n\nFor further information please read our usage guide, which can be accessed with the following command:\n\ncontrast-cli --help',
|
|
18
18
|
yamlMissingParametersHeader: 'Missing Parameters',
|
|
@@ -78,7 +78,7 @@ const en_locales = () => {
|
|
|
78
78
|
constantsApplicationName: 'The name of the application cataloged by Contrast UI',
|
|
79
79
|
constantsCatalogueApplication: 'Provide this if you want to catalogue an application',
|
|
80
80
|
constantsLanguage: 'Valid values are JAVA, DOTNET, NODE, PYTHON and RUBY. If there are multiple project configuration files in the project_path, language is also required. Also, provide this when cataloguing an application',
|
|
81
|
-
|
|
81
|
+
constantsFilePath: 'The directory root of a project/application that you would like analyzed. Defaults to current directory.',
|
|
82
82
|
constantsSilent: 'Silences JSON output.',
|
|
83
83
|
constantsAppGroups: 'Assign your application to one or more pre-existing groups when using the catalogue command. Group lists should be comma separated.',
|
|
84
84
|
constantsVersion: 'Displays CLI Version you are currently on.',
|
|
@@ -90,13 +90,13 @@ const en_locales = () => {
|
|
|
90
90
|
constantsProjectName: 'Contrast project name. If not specified, Contrast uses contrast.settings to identify the project or creates a project.',
|
|
91
91
|
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.',
|
|
92
92
|
constantsReport: 'Display vulnerability information for this application',
|
|
93
|
-
constantsFail: 'Set the process to fail if this option is set in combination with
|
|
94
|
-
failOptionErrorMessage:
|
|
95
|
-
constantsSeverity: '
|
|
96
|
-
constantsCount:
|
|
93
|
+
constantsFail: 'Set the process to fail if this option is set in combination with --cve_severity.',
|
|
94
|
+
failOptionErrorMessage: ' FAIL - CVEs have been detected that match at least the cve_severity or cve_threshold option specified.',
|
|
95
|
+
constantsSeverity: 'Allows the user to report libraries with vulnerabilities above a chosen severity level. For example, cve_severity medium only reports libraries with vulnerabilities at medium or higher severity. Values for level are high, medium or low.',
|
|
96
|
+
constantsCount: 'The number of CVEs that must be exceeded to fail a build',
|
|
97
97
|
constantsHeader: 'CodeSec by Contrast Security',
|
|
98
98
|
constantsPrerequisitesContentScanLanguages: 'Java & JavaScript supported',
|
|
99
|
-
constantsContrastContent:
|
|
99
|
+
constantsContrastContent: "Use the 'contrast' command for fast and accurate security analysis of your applications and APIs (Java, JavaScript and .NET ) as well as serverless functions (AWS lambda, Java and Python).",
|
|
100
100
|
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.',
|
|
101
101
|
constantsPrerequisitesHeader: 'Pre-requisites',
|
|
102
102
|
constantsAuthUsageHeader: 'Usage',
|
|
@@ -162,7 +162,7 @@ const en_locales = () => {
|
|
|
162
162
|
constantsIgnoreCertErrors: 'For EOP users with a local Teamserver install, this will bypass the SSL certificate and recognise a self signed certificate.',
|
|
163
163
|
constantsSave: 'Saves the Scan Results SARIF to file.',
|
|
164
164
|
scanLabel: "adds a label to the scan - defaults to 'Started by CLI tool at current date'",
|
|
165
|
-
constantsIgnoreDev: '
|
|
165
|
+
constantsIgnoreDev: 'Excludes developer dependencies from the output. By default all dependencies are included.',
|
|
166
166
|
constantsCommands: 'Commands',
|
|
167
167
|
constantsScanOptions: 'Scan Options',
|
|
168
168
|
sbomError: 'All required parameters are not present.',
|
|
@@ -247,6 +247,7 @@ const en_locales = () => {
|
|
|
247
247
|
redirectAuth: '\nOpening the authentication page in your web browser.\nSign in and complete the steps.\nReturn here to start using Contrast.\n\nIf your browser has trouble loading, try this:\n%s \n',
|
|
248
248
|
scanZipError: 'A .zip archive can be used for Javascript Scan. Archive found %s does not contain .JS files for Scan.',
|
|
249
249
|
fileNotExist: 'File specified does not exist, please check and try again.',
|
|
250
|
+
scanFileIsEmpty: 'File specified is empty. Please choose another.',
|
|
250
251
|
fileHasWhiteSpacesError: 'File cannot have spaces, please rename or choose another file to Scan.',
|
|
251
252
|
zipFileException: 'Error reading zip file',
|
|
252
253
|
connectionError: 'An error has occurred when trying to get the Project Id please check your internet connection or provide the Project Id manually',
|
|
@@ -276,11 +277,12 @@ const en_locales = () => {
|
|
|
276
277
|
auditOptionsIgnoreDevDependencies: '-igd, --ignore-dev',
|
|
277
278
|
auditOptionsIgnoreDevDependenciesDescription: 'ignores DevDependencies',
|
|
278
279
|
auditOptionsSave: '-s, --save',
|
|
279
|
-
auditOptionsSaveDescription: 'saves the output in specified format
|
|
280
|
+
auditOptionsSaveDescription: 'saves the output in specified format, options: sbom',
|
|
280
281
|
scanNotCompleted: 'Scan not completed. Check for framework and language support here: %s',
|
|
281
|
-
|
|
282
|
+
auditNotCompleted: 'audit not completed. Please try again',
|
|
283
|
+
scanNoVulnerabilitiesFound: '🎉 No vulnerabilities found.',
|
|
282
284
|
scanNoVulnerabilitiesFoundSecureCode: '👍 Your code looks secure.',
|
|
283
|
-
scanNoVulnerabilitiesFoundGoodWork: '
|
|
285
|
+
scanNoVulnerabilitiesFoundGoodWork: ' Keep up the good work.',
|
|
284
286
|
scanNoFiletypeSpecifiedForSave: 'Please specify file type to save results to, accepted value is SARIF',
|
|
285
287
|
auditSBOMSaveSuccess: '\n Software Bill of Materials (SBOM) saved successfully',
|
|
286
288
|
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.')}`,
|
|
@@ -289,7 +291,8 @@ const en_locales = () => {
|
|
|
289
291
|
auditReportFail: 'Report Retrieval Failed, please try again',
|
|
290
292
|
auditReportSuccessMessage: 'Report successfully retrieved',
|
|
291
293
|
auditReportFailureMessage: 'Unable to generate library report',
|
|
292
|
-
auditSCAAnalysisBegins: 'Contrast SCA
|
|
294
|
+
auditSCAAnalysisBegins: 'Contrast SCA audit started',
|
|
295
|
+
auditSCAAnalysisComplete: 'Contrast SCA audit complete',
|
|
293
296
|
...lambda
|
|
294
297
|
};
|
|
295
298
|
};
|
package/dist/constants.js
CHANGED
|
@@ -43,7 +43,6 @@ const scanOptionDefinitions = [
|
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
name: 'project-path',
|
|
46
|
-
alias: 'i',
|
|
47
46
|
description: '{bold ' +
|
|
48
47
|
i18n.__('constantsOptional') +
|
|
49
48
|
'}: ' +
|
|
@@ -188,12 +187,13 @@ const auditOptionDefinitions = [
|
|
|
188
187
|
i18n.__('constantsApplicationName')
|
|
189
188
|
},
|
|
190
189
|
{
|
|
191
|
-
name: '
|
|
192
|
-
|
|
190
|
+
name: 'file',
|
|
191
|
+
alias: 'f',
|
|
192
|
+
defaultValue: process.cwd(),
|
|
193
193
|
description: '{bold ' +
|
|
194
194
|
i18n.__('constantsOptional') +
|
|
195
195
|
'}: ' +
|
|
196
|
-
i18n.__('
|
|
196
|
+
i18n.__('constantsFilePath')
|
|
197
197
|
},
|
|
198
198
|
{
|
|
199
199
|
name: 'app-groups',
|
|
@@ -295,6 +295,11 @@ const auditOptionDefinitions = [
|
|
|
295
295
|
i18n.__('constantsOptional') +
|
|
296
296
|
'}: ' +
|
|
297
297
|
i18n.__('auditOptionsSaveDescription')
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
name: 'experimental',
|
|
301
|
+
alias: 'e',
|
|
302
|
+
type: Boolean
|
|
298
303
|
}
|
|
299
304
|
];
|
|
300
305
|
const mainUsageGuide = commandLineUsage([
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
"use strict";
|
|
2
3
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
4
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
@@ -36,12 +37,12 @@ const start = async () => {
|
|
|
36
37
|
argvMain.includes('--v') ||
|
|
37
38
|
argvMain.includes('--version')) {
|
|
38
39
|
console.log(constants_2.APP_VERSION);
|
|
39
|
-
await (0, versionChecker_1.findLatestCLIVersion)(config
|
|
40
|
+
await (0, versionChecker_1.findLatestCLIVersion)(config);
|
|
40
41
|
return;
|
|
41
42
|
}
|
|
42
43
|
config.set('numOfRuns', config.get('numOfRuns') + 1);
|
|
43
|
-
if (config.get('numOfRuns') >=
|
|
44
|
-
await (0, versionChecker_1.findLatestCLIVersion)(config
|
|
44
|
+
if (config.get('numOfRuns') >= 1) {
|
|
45
|
+
await (0, versionChecker_1.findLatestCLIVersion)(config);
|
|
45
46
|
config.set('numOfRuns', 0);
|
|
46
47
|
}
|
|
47
48
|
if (command === 'config') {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.postAnalytics = void 0;
|
|
4
|
+
const commonApi_1 = require("../utils/commonApi");
|
|
5
|
+
const paramHandler_1 = require("../utils/paramsUtil/paramHandler");
|
|
6
|
+
const postAnalytics = (data, provider = 'aws') => {
|
|
7
|
+
const config = (0, paramHandler_1.getAuth)();
|
|
8
|
+
const client = (0, commonApi_1.getHttpClient)(config);
|
|
9
|
+
return client.postAnalyticsFunction(config, provider, data);
|
|
10
|
+
};
|
|
11
|
+
exports.postAnalytics = postAnalytics;
|
package/dist/lambda/lambda.js
CHANGED
|
@@ -20,6 +20,8 @@ const utils_1 = require("./utils");
|
|
|
20
20
|
const lambdaUtils_1 = require("./lambdaUtils");
|
|
21
21
|
const requestUtils_1 = require("../utils/requestUtils");
|
|
22
22
|
const oraWrapper_1 = __importDefault(require("../utils/oraWrapper"));
|
|
23
|
+
const analytics_1 = require("./analytics");
|
|
24
|
+
const types_1 = require("./types");
|
|
23
25
|
const failedStates = [
|
|
24
26
|
'UNSUPPORTED',
|
|
25
27
|
'EXCLUDED',
|
|
@@ -57,9 +59,19 @@ const getLambdaOptions = (argv) => {
|
|
|
57
59
|
}
|
|
58
60
|
};
|
|
59
61
|
const processLambda = async (argv) => {
|
|
62
|
+
let errorMsg;
|
|
63
|
+
let scanInfo;
|
|
64
|
+
const commandSessionId = Date.now().toString(36);
|
|
60
65
|
try {
|
|
61
66
|
const lambdaOptions = getLambdaOptions(argv);
|
|
62
67
|
const { help } = lambdaOptions;
|
|
68
|
+
const startCommandAnalytics = {
|
|
69
|
+
arguments: lambdaOptions,
|
|
70
|
+
sessionId: commandSessionId,
|
|
71
|
+
eventType: types_1.EventType.START
|
|
72
|
+
};
|
|
73
|
+
(0, analytics_1.postAnalytics)(startCommandAnalytics).catch((error) => {
|
|
74
|
+
});
|
|
63
75
|
if (help) {
|
|
64
76
|
return handleLambdaHelp();
|
|
65
77
|
}
|
|
@@ -68,17 +80,35 @@ const processLambda = async (argv) => {
|
|
|
68
80
|
await getAvailableFunctions(lambdaOptions);
|
|
69
81
|
}
|
|
70
82
|
else {
|
|
71
|
-
await actualProcessLambda(lambdaOptions);
|
|
83
|
+
scanInfo = await actualProcessLambda(lambdaOptions);
|
|
72
84
|
}
|
|
73
85
|
}
|
|
74
86
|
catch (error) {
|
|
75
87
|
if (error instanceof cliError_1.CliError) {
|
|
76
|
-
|
|
88
|
+
errorMsg = error.getErrorMessage();
|
|
77
89
|
}
|
|
78
90
|
else if (error instanceof Error) {
|
|
79
|
-
|
|
91
|
+
errorMsg = error.message;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
const endCommandAnalytics = {
|
|
96
|
+
sessionId: commandSessionId,
|
|
97
|
+
eventType: types_1.EventType.END,
|
|
98
|
+
status: errorMsg ? types_1.StatusType.FAILED : types_1.StatusType.SUCCESS
|
|
99
|
+
};
|
|
100
|
+
if (errorMsg) {
|
|
101
|
+
endCommandAnalytics.errorMsg = errorMsg;
|
|
102
|
+
console.error(errorMsg);
|
|
103
|
+
}
|
|
104
|
+
if (scanInfo) {
|
|
105
|
+
endCommandAnalytics.scanFunctionData = scanInfo;
|
|
106
|
+
}
|
|
107
|
+
await (0, analytics_1.postAnalytics)(endCommandAnalytics).catch((error) => {
|
|
108
|
+
});
|
|
109
|
+
if (errorMsg) {
|
|
110
|
+
process.exit(1);
|
|
80
111
|
}
|
|
81
|
-
process.exit(1);
|
|
82
112
|
}
|
|
83
113
|
};
|
|
84
114
|
exports.processLambda = processLambda;
|
|
@@ -127,6 +157,7 @@ const actualProcessLambda = async (lambdaOptions) => {
|
|
|
127
157
|
if (results?.length) {
|
|
128
158
|
(0, utils_1.printResults)(results);
|
|
129
159
|
}
|
|
160
|
+
return { functionArn, scanId };
|
|
130
161
|
};
|
|
131
162
|
const validateRequiredLambdaParams = (options) => {
|
|
132
163
|
if (options._unknown?.length) {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EventType = exports.StatusType = void 0;
|
|
4
|
+
var StatusType;
|
|
5
|
+
(function (StatusType) {
|
|
6
|
+
StatusType["FAILED"] = "failed";
|
|
7
|
+
StatusType["SUCCESS"] = "success";
|
|
8
|
+
})(StatusType = exports.StatusType || (exports.StatusType = {}));
|
|
9
|
+
var EventType;
|
|
10
|
+
(function (EventType) {
|
|
11
|
+
EventType["START"] = "start_command_session";
|
|
12
|
+
EventType["END"] = "end_command_session";
|
|
13
|
+
})(EventType = exports.EventType || (exports.EventType = {}));
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateSbom = void 0;
|
|
3
4
|
const commonApi_1 = require("../utils/commonApi");
|
|
4
|
-
|
|
5
|
+
const generateSbom = (config) => {
|
|
5
6
|
const client = (0, commonApi_1.getHttpClient)(config);
|
|
6
7
|
return client
|
|
7
8
|
.getSbom(config)
|
|
@@ -16,5 +17,5 @@ function generateSbom(config) {
|
|
|
16
17
|
.catch((err) => {
|
|
17
18
|
console.log(err);
|
|
18
19
|
});
|
|
19
|
-
}
|
|
20
|
-
exports.
|
|
20
|
+
};
|
|
21
|
+
exports.generateSbom = generateSbom;
|
|
@@ -6,6 +6,51 @@ const createJavaTSMessage = javaTree => {
|
|
|
6
6
|
}
|
|
7
7
|
};
|
|
8
8
|
};
|
|
9
|
+
const createJavaScriptTSMessage = js => {
|
|
10
|
+
let message = {
|
|
11
|
+
node: {
|
|
12
|
+
packageJSON: js.packageJSON
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
if (js.yarn !== undefined) {
|
|
16
|
+
message.node.yarnLockFile = js.yarn.yarnLockFile;
|
|
17
|
+
message.node.yarnVersion = js.yarn.yarnVersion;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
message.node.npmLockFile = js.npmLockFile;
|
|
21
|
+
}
|
|
22
|
+
return message;
|
|
23
|
+
};
|
|
24
|
+
const createGoTSMessage = goTree => {
|
|
25
|
+
return {
|
|
26
|
+
go: {
|
|
27
|
+
goDependencyTrees: goTree
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
const createRubyTSMessage = rubyTree => {
|
|
32
|
+
return {
|
|
33
|
+
ruby: rubyTree
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
const createPythonTSMessage = pythonTree => {
|
|
37
|
+
return {
|
|
38
|
+
python: pythonTree
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
const createPhpTSMessage = phpTree => {
|
|
42
|
+
return {
|
|
43
|
+
php: {
|
|
44
|
+
composerJSON: phpTree.composerJSON,
|
|
45
|
+
lockFile: phpTree.lockFile
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
};
|
|
9
49
|
module.exports = {
|
|
10
|
-
|
|
50
|
+
createJavaScriptTSMessage,
|
|
51
|
+
createJavaTSMessage,
|
|
52
|
+
createGoTSMessage,
|
|
53
|
+
createPhpTSMessage,
|
|
54
|
+
createRubyTSMessage,
|
|
55
|
+
createPythonTSMessage
|
|
11
56
|
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const { getHttpClient } = require('../../utils/commonApi');
|
|
3
|
-
const { handleResponseErrors } = require('../../common/errorHandling');
|
|
4
3
|
const { APP_VERSION } = require('../../constants/constants');
|
|
5
4
|
const commonSendSnapShot = async (analysis, config) => {
|
|
6
5
|
const requestBody = {
|
|
@@ -13,12 +12,11 @@ const commonSendSnapShot = async (analysis, config) => {
|
|
|
13
12
|
.sendSnapshot(requestBody, config)
|
|
14
13
|
.then(res => {
|
|
15
14
|
if (res.statusCode === 201) {
|
|
16
|
-
console.log('snapshot processed successfully');
|
|
17
15
|
return res.body;
|
|
18
16
|
}
|
|
19
17
|
else {
|
|
20
18
|
console.log(res.statusCode);
|
|
21
|
-
|
|
19
|
+
console.log('error processing dependencies');
|
|
22
20
|
}
|
|
23
21
|
})
|
|
24
22
|
.catch(err => {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const { createGoTSMessage } = require('../common/formatMessage');
|
|
3
|
+
const goReadDepFile = require('./goReadDepFile');
|
|
4
|
+
const goParseDeps = require('./goParseDeps');
|
|
5
|
+
const goAnalysis = (config, languageFiles) => {
|
|
6
|
+
try {
|
|
7
|
+
const rawGoDependencies = goReadDepFile.getGoDependencies(config);
|
|
8
|
+
const parsedGoDependencies = goParseDeps.parseGoDependencies(rawGoDependencies);
|
|
9
|
+
return createGoTSMessage(parsedGoDependencies);
|
|
10
|
+
}
|
|
11
|
+
catch (e) {
|
|
12
|
+
console.log(e.message.toString());
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
module.exports = {
|
|
16
|
+
goAnalysis
|
|
17
|
+
};
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const crypto = require('crypto');
|
|
3
|
+
const parseGoDependencies = goDeps => {
|
|
4
|
+
return parseGo(goDeps);
|
|
5
|
+
};
|
|
6
|
+
const parseGo = modGraphOutput => {
|
|
7
|
+
let splitLines = splitAllLinesIntoArray(modGraphOutput);
|
|
8
|
+
const directDepNames = getDirectDepNames(splitLines);
|
|
9
|
+
const uniqueTransitiveDepNames = getAllUniqueTransitiveDepNames(splitLines, directDepNames);
|
|
10
|
+
let rootNodes = createRootNodes(splitLines);
|
|
11
|
+
createTransitiveDeps(uniqueTransitiveDepNames, splitLines, rootNodes);
|
|
12
|
+
return rootNodes;
|
|
13
|
+
};
|
|
14
|
+
const splitAllLinesIntoArray = modGraphOutput => {
|
|
15
|
+
return modGraphOutput.split(/\r\n|\r|\n/);
|
|
16
|
+
};
|
|
17
|
+
const getAllDepsOfADepAsEdge = (dep, deps) => {
|
|
18
|
+
let edges = {};
|
|
19
|
+
const depRows = deps.filter(line => {
|
|
20
|
+
return line.startsWith(dep);
|
|
21
|
+
});
|
|
22
|
+
depRows.forEach(dep => {
|
|
23
|
+
const edgeName = dep.split(' ')[1];
|
|
24
|
+
edges[edgeName] = edgeName;
|
|
25
|
+
});
|
|
26
|
+
return edges;
|
|
27
|
+
};
|
|
28
|
+
const getAllDepsOfADepAsName = (dep, deps) => {
|
|
29
|
+
let edges = [];
|
|
30
|
+
const depRows = deps.filter(line => {
|
|
31
|
+
return line.startsWith(dep);
|
|
32
|
+
});
|
|
33
|
+
depRows.forEach(dep => {
|
|
34
|
+
const edgeName = dep.split(' ')[1];
|
|
35
|
+
edges.push(edgeName);
|
|
36
|
+
});
|
|
37
|
+
return edges;
|
|
38
|
+
};
|
|
39
|
+
const createRootNodes = deps => {
|
|
40
|
+
let rootDep = {};
|
|
41
|
+
const rootDeps = getRootDeps(deps);
|
|
42
|
+
const edges = rootDeps.map(dep => {
|
|
43
|
+
return dep.split(' ')[1];
|
|
44
|
+
});
|
|
45
|
+
rootDep[rootDeps[0].split(' ')[0]] = {};
|
|
46
|
+
edges.forEach(edge => {
|
|
47
|
+
const splitEdge = edge.split('@');
|
|
48
|
+
const splitGroupName = splitEdge[0].split('/');
|
|
49
|
+
const name = splitGroupName.pop();
|
|
50
|
+
const lastSlash = splitEdge[0].lastIndexOf('/');
|
|
51
|
+
let group = splitEdge[0].substring(0, lastSlash);
|
|
52
|
+
const hash = getHash(splitEdge[0]);
|
|
53
|
+
group = checkGroupExists(group, name);
|
|
54
|
+
const edgesOfDep = getAllDepsOfADepAsEdge(edge, deps);
|
|
55
|
+
rootDep[rootDeps[0].split(' ')[0]][edge] = {
|
|
56
|
+
artifactID: name,
|
|
57
|
+
group: group,
|
|
58
|
+
version: splitEdge[1],
|
|
59
|
+
scope: '"compile',
|
|
60
|
+
type: 'direct',
|
|
61
|
+
hash: hash,
|
|
62
|
+
edges: edgesOfDep
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
return rootDep;
|
|
66
|
+
};
|
|
67
|
+
const getRootDeps = deps => {
|
|
68
|
+
const rootDeps = deps.filter(dep => {
|
|
69
|
+
const parentDep = dep.split(' ')[0];
|
|
70
|
+
if (parentDep.split('@v').length === 1) {
|
|
71
|
+
return dep;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
return rootDeps;
|
|
75
|
+
};
|
|
76
|
+
const getHash = library => {
|
|
77
|
+
let shaSum = crypto.createHash('sha1');
|
|
78
|
+
shaSum.update(library);
|
|
79
|
+
return shaSum.digest('hex');
|
|
80
|
+
};
|
|
81
|
+
const getDirectDepNames = deps => {
|
|
82
|
+
const directDepNames = [];
|
|
83
|
+
deps.forEach(dep => {
|
|
84
|
+
const parentDep = dep.split(' ')[0];
|
|
85
|
+
if (parentDep.split('@v').length === 1) {
|
|
86
|
+
dep.split(' ')[1] !== undefined
|
|
87
|
+
? directDepNames.push(dep.split(' ')[1])
|
|
88
|
+
: null;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
return directDepNames;
|
|
92
|
+
};
|
|
93
|
+
const getAllUniqueTransitiveDepNames = (deps, directDepNames) => {
|
|
94
|
+
let uniqueDeps = [];
|
|
95
|
+
deps.forEach(dep => {
|
|
96
|
+
const parentDep = dep.split(' ')[0];
|
|
97
|
+
if (parentDep.split('@v').length !== 1) {
|
|
98
|
+
if (!directDepNames.includes(parentDep)) {
|
|
99
|
+
if (!uniqueDeps.includes(parentDep)) {
|
|
100
|
+
parentDep.length > 1 ? uniqueDeps.push(parentDep) : null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
return uniqueDeps;
|
|
106
|
+
};
|
|
107
|
+
const checkGroupExists = (group, name) => {
|
|
108
|
+
if (group === null || group === '') {
|
|
109
|
+
return name;
|
|
110
|
+
}
|
|
111
|
+
return group;
|
|
112
|
+
};
|
|
113
|
+
const createTransitiveDeps = (transitiveDeps, splitLines, rootNodes) => {
|
|
114
|
+
transitiveDeps.forEach(dep => {
|
|
115
|
+
const splitEdge = dep.split('@');
|
|
116
|
+
const splitGroupName = splitEdge[0].split('/');
|
|
117
|
+
const name = splitGroupName.pop();
|
|
118
|
+
const lastSlash = splitEdge[0].lastIndexOf('/');
|
|
119
|
+
let group = splitEdge[0].substring(0, lastSlash);
|
|
120
|
+
const hash = getHash(splitEdge[0]);
|
|
121
|
+
group = checkGroupExists(group, name);
|
|
122
|
+
const transitiveDep = {
|
|
123
|
+
artifactID: name,
|
|
124
|
+
group: group,
|
|
125
|
+
version: splitEdge[1],
|
|
126
|
+
scope: 'compile',
|
|
127
|
+
type: 'transitive',
|
|
128
|
+
hash: hash,
|
|
129
|
+
edges: {}
|
|
130
|
+
};
|
|
131
|
+
const edges = getAllDepsOfADepAsEdge(dep, splitLines);
|
|
132
|
+
transitiveDep.edges = edges;
|
|
133
|
+
const edgesAsName = getAllDepsOfADepAsName(dep, splitLines);
|
|
134
|
+
edgesAsName.forEach(dep => {
|
|
135
|
+
const splitEdge = dep.split('@');
|
|
136
|
+
const splitGroupName = splitEdge[0].split('/');
|
|
137
|
+
const name = splitGroupName.pop();
|
|
138
|
+
const lastSlash = splitEdge[0].lastIndexOf('/');
|
|
139
|
+
let group = splitEdge[0].substring(0, lastSlash);
|
|
140
|
+
const hash = getHash(splitEdge[0]);
|
|
141
|
+
group = checkGroupExists(group, name);
|
|
142
|
+
const transitiveDep = {
|
|
143
|
+
artifactID: name,
|
|
144
|
+
group: group,
|
|
145
|
+
version: splitEdge[1],
|
|
146
|
+
scope: 'compile',
|
|
147
|
+
type: 'transitive',
|
|
148
|
+
hash: hash,
|
|
149
|
+
edges: {}
|
|
150
|
+
};
|
|
151
|
+
rootNodes[Object.keys(rootNodes)[0]][dep] = transitiveDep;
|
|
152
|
+
});
|
|
153
|
+
rootNodes[Object.keys(rootNodes)[0]][dep] = transitiveDep;
|
|
154
|
+
});
|
|
155
|
+
};
|
|
156
|
+
module.exports = {
|
|
157
|
+
parseGoDependencies
|
|
158
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const child_process = require('child_process');
|
|
3
|
+
const i18n = require('i18n');
|
|
4
|
+
const getGoDependencies = config => {
|
|
5
|
+
let cmdStdout;
|
|
6
|
+
let cwd = config.file ? config.file.replace('go.mod', '') : process.cwd();
|
|
7
|
+
try {
|
|
8
|
+
cmdStdout = child_process.execSync('go mod graph', { cwd });
|
|
9
|
+
return cmdStdout.toString();
|
|
10
|
+
}
|
|
11
|
+
catch (err) {
|
|
12
|
+
if (err.message === 'spawnSync /bin/sh ENOENT') {
|
|
13
|
+
err.message =
|
|
14
|
+
'\n\n*************** No transitive dependencies ***************\n\nWe are unable to build a dependency tree view from your repository as there were no transitive dependencies found.';
|
|
15
|
+
}
|
|
16
|
+
console.log(i18n.__('goReadProjectFile', cwd, `${err.message ? err.message : ''}`));
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
module.exports = {
|
|
20
|
+
getGoDependencies
|
|
21
|
+
};
|