@contrast/contrast 1.0.4 → 1.0.5

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.
Files changed (62) hide show
  1. package/.prettierignore +2 -0
  2. package/dist/audit/autodetection/autoDetectLanguage.js +32 -0
  3. package/dist/audit/catalogueApplication/catalogueApplication.js +2 -11
  4. package/dist/audit/languageAnalysisEngine/languageAnalysisFactory.js +4 -2
  5. package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +25 -0
  6. package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +3 -17
  7. package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +1 -1
  8. package/dist/audit/languageAnalysisEngine/sendSnapshot.js +2 -16
  9. package/dist/commands/audit/auditConfig.js +8 -2
  10. package/dist/commands/audit/auditController.js +8 -2
  11. package/dist/commands/scan/processScan.js +6 -3
  12. package/dist/commands/scan/sca/scaAnalysis.js +44 -0
  13. package/dist/common/HTTPClient.js +0 -1
  14. package/dist/common/errorHandling.js +7 -17
  15. package/dist/constants/constants.js +14 -2
  16. package/dist/constants/locales.js +28 -35
  17. package/dist/constants.js +20 -0
  18. package/dist/scaAnalysis/common/formatMessage.js +11 -0
  19. package/dist/scaAnalysis/common/treeUpload.js +30 -0
  20. package/dist/scaAnalysis/java/analysis.js +116 -0
  21. package/dist/scaAnalysis/java/index.js +18 -0
  22. package/dist/scaAnalysis/java/javaBuildDepsParser.js +326 -0
  23. package/dist/scan/autoDetection.js +46 -1
  24. package/dist/scan/fileUtils.js +73 -1
  25. package/dist/scan/formatScanOutput.js +212 -0
  26. package/dist/scan/help.js +3 -1
  27. package/dist/scan/models/groupedResultsModel.js +2 -1
  28. package/dist/scan/scan.js +1 -96
  29. package/dist/scan/scanController.js +1 -2
  30. package/dist/scan/scanResults.js +3 -17
  31. package/package.json +2 -1
  32. package/src/audit/autodetection/autoDetectLanguage.ts +40 -0
  33. package/src/audit/catalogueApplication/catalogueApplication.js +4 -16
  34. package/src/audit/languageAnalysisEngine/languageAnalysisFactory.js +9 -5
  35. package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +71 -0
  36. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +3 -25
  37. package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +1 -1
  38. package/src/audit/languageAnalysisEngine/sendSnapshot.js +2 -24
  39. package/src/commands/audit/auditConfig.ts +12 -3
  40. package/src/commands/audit/auditController.ts +9 -2
  41. package/src/commands/audit/processAudit.ts +3 -0
  42. package/src/commands/scan/processScan.js +8 -3
  43. package/src/commands/scan/sca/scaAnalysis.js +73 -0
  44. package/src/common/HTTPClient.js +1 -1
  45. package/src/common/errorHandling.ts +7 -24
  46. package/src/constants/constants.js +14 -2
  47. package/src/constants/locales.js +30 -49
  48. package/src/constants.js +22 -0
  49. package/src/scaAnalysis/common/formatMessage.js +10 -0
  50. package/src/scaAnalysis/common/treeUpload.js +34 -0
  51. package/src/scaAnalysis/java/analysis.js +159 -0
  52. package/src/scaAnalysis/java/index.js +21 -0
  53. package/src/scaAnalysis/java/javaBuildDepsParser.js +391 -0
  54. package/src/scan/autoDetection.js +54 -1
  55. package/src/scan/fileUtils.js +91 -1
  56. package/src/scan/formatScanOutput.ts +241 -0
  57. package/src/scan/help.js +3 -1
  58. package/src/scan/models/groupedResultsModel.ts +7 -5
  59. package/src/scan/models/resultContentModel.ts +2 -2
  60. package/src/scan/scan.ts +0 -130
  61. package/src/scan/scanController.js +1 -2
  62. package/src/scan/scanResults.js +9 -17
package/.prettierignore CHANGED
@@ -2,3 +2,5 @@ test/commands/**
2
2
  dist/**
3
3
  test/errorHandling.spec.ts
4
4
  **/models
5
+ **/audit/autodetection/autoDetectLanguage.ts
6
+ **/commands/audit/auditConfig.ts
@@ -0,0 +1,32 @@
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.determineProjectLanguage = exports.identifyLanguages = void 0;
7
+ const i18n_1 = __importDefault(require("i18n"));
8
+ const reduceIdentifiedLanguages_1 = require("../languageAnalysisEngine/reduceIdentifiedLanguages");
9
+ const getProjectRootFilenames_1 = require("../languageAnalysisEngine/getProjectRootFilenames");
10
+ function identifyLanguages(config) {
11
+ const { projectPath } = config;
12
+ const projectRootFilenames = (0, getProjectRootFilenames_1.getProjectRootFilenames)(projectPath);
13
+ const identifiedLanguages = projectRootFilenames.reduce((accumulator, filename) => {
14
+ const deducedLanguages = (0, reduceIdentifiedLanguages_1.deduceLanguage)(filename);
15
+ return [...accumulator, ...deducedLanguages];
16
+ }, []);
17
+ if (Object.keys(identifiedLanguages).length === 0) {
18
+ throw new Error(i18n_1.default.__('languageAnalysisNoLanguage', projectPath));
19
+ }
20
+ return (0, reduceIdentifiedLanguages_1.reduceIdentifiedLanguages)(identifiedLanguages);
21
+ }
22
+ exports.identifyLanguages = identifyLanguages;
23
+ function determineProjectLanguage(reducedLanguages) {
24
+ const reducedLanguagesKeys = Object.keys(reducedLanguages);
25
+ if (reducedLanguagesKeys.length === 1) {
26
+ return reducedLanguagesKeys[0];
27
+ }
28
+ else {
29
+ throw new Error('Detected multiple languages. Please specify a single language using --language');
30
+ }
31
+ }
32
+ exports.determineProjectLanguage = determineProjectLanguage;
@@ -1,16 +1,8 @@
1
1
  "use strict";
2
2
  const i18n = require('i18n');
3
3
  const { getHttpClient, handleResponseErrors } = require('../../utils/commonApi');
4
- const locationOfApp = (config, appId) => {
5
- return `${config.host}/Contrast/static/ng/index.html#/${config.organizationId}/applications/${appId}`;
6
- };
7
- const displaySuccessMessage = (config, appId) => {
8
- console.log('\n **************************' +
9
- i18n.__('successHeader') +
10
- '************************** \n');
11
- console.log('\n' + i18n.__('catalogueSuccessCommand') + appId + '\n');
12
- console.log(locationOfApp(config, appId));
13
- console.log('\n *********************************************************** \n');
4
+ const displaySuccessMessage = () => {
5
+ console.log(i18n.__('catalogueSuccessCommand'));
14
6
  };
15
7
  const catalogueApplication = async (config) => {
16
8
  const client = getHttpClient(config);
@@ -19,7 +11,6 @@ const catalogueApplication = async (config) => {
19
11
  .catalogueCommand(config)
20
12
  .then(res => {
21
13
  if (res.statusCode === 201) {
22
- displaySuccessMessage(config, res.body.application.app_id);
23
14
  appId = res.body.application.app_id;
24
15
  }
25
16
  else {
@@ -14,6 +14,7 @@ const fs = require('fs');
14
14
  const chalk = require('chalk');
15
15
  const saveFile = require('../../commands/audit/saveFile').default;
16
16
  const generateSbom = require('../../sbom/generateSbom').default;
17
+ const { failSpinner, returnOra, startSpinner, succeedSpinner } = require('../../utils/oraWrapper');
17
18
  module.exports = exports = (err, analysis) => {
18
19
  const { identifiedLanguageInfo } = analysis.languageAnalysis;
19
20
  const catalogueAppId = analysis.languageAnalysis.appId;
@@ -35,11 +36,12 @@ module.exports = exports = (err, analysis) => {
35
36
  err);
36
37
  return process.exit(5);
37
38
  }
38
- console.log('\n **************CONTRAST OSS ANALYSIS BEGINS**************');
39
+ const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'));
40
+ startSpinner(reportSpinner);
39
41
  const snapshotResponse = await newSendSnapShot(analysis, catalogueAppId);
42
+ succeedSpinner(reportSpinner, 'Contrast SCA analysis complete');
40
43
  await vulnerabilityReport(analysis, catalogueAppId, snapshotResponse.id);
41
44
  await auditSave(config);
42
- console.log('\n ***************CONTRAST OSS ANALYSIS COMPLETE************** \n');
43
45
  };
44
46
  if (identifiedLanguageInfo.language === DOTNET) {
45
47
  dotnetAE(identifiedLanguageInfo, analysis.config, langCallback);
@@ -22,6 +22,30 @@ function isNodeLockFilename(filename) {
22
22
  const isRubyLockFilename = filename => filename === 'Gemfile.lock';
23
23
  const isPipfileLockLockFilename = filename => filename === 'Pipfile.lock';
24
24
  const isGoProjectFilename = filename => filename === 'go.mod';
25
+ const deduceLanguageScaAnalysis = filenames => {
26
+ const deducedLanguages = [];
27
+ let language = '';
28
+ filenames.forEach(filename => {
29
+ if (isJavaMavenProjectFilename(filename)) {
30
+ deducedLanguages.push(filename);
31
+ language = JAVA;
32
+ }
33
+ if (isJavaGradleProjectFilename(filename)) {
34
+ deducedLanguages.push(filename);
35
+ language = JAVA;
36
+ }
37
+ if (isNodeProjectFilename(filename)) {
38
+ deducedLanguages.push(filename);
39
+ language = NODE;
40
+ }
41
+ if (isNodeLockFilename(filename)) {
42
+ deducedLanguages.push(filename);
43
+ language = node;
44
+ }
45
+ });
46
+ let identifiedLanguages = { [language]: deducedLanguages };
47
+ return identifiedLanguages;
48
+ };
25
49
  const deduceLanguage = filename => {
26
50
  const deducedLanguages = [];
27
51
  if (isJavaMavenProjectFilename(filename)) {
@@ -119,3 +143,4 @@ exports.isPhpProjectFilename = isPhpProjectFilename;
119
143
  exports.isPhpLockFilename = isPhpLockFilename;
120
144
  exports.deduceLanguage = deduceLanguage;
121
145
  exports.reduceIdentifiedLanguages = reduceIdentifiedLanguages;
146
+ exports.deduceLanguageScaAnalysis = deduceLanguageScaAnalysis;
@@ -4,40 +4,26 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.printFormattedOutput = exports.printVulnerabilityResponse = exports.getReport = exports.createLibraryHeader = void 0;
7
- const i18n_1 = __importDefault(require("i18n"));
8
7
  const commonApi_1 = require("../../../utils/commonApi");
9
8
  const reportListModel_1 = require("./models/reportListModel");
10
9
  const lodash_1 = require("lodash");
11
10
  const chalk_1 = __importDefault(require("chalk"));
12
11
  const reportUtils_1 = require("./utils/reportUtils");
13
- const oraWrapper_1 = require("../../../utils/oraWrapper");
14
- const createLibraryHeader = (id, numberOfVulnerableLibraries, numberOfCves, name) => {
15
- name
16
- ? console.log(`\n Application Name: ${name} | Application ID: ${id}`)
17
- : console.log(` Application ID: ${id}`);
12
+ const createLibraryHeader = (id, numberOfVulnerableLibraries, numberOfCves) => {
18
13
  numberOfVulnerableLibraries === 1
19
- ? console.log('\n **************************' +
20
- ` Found 1 vulnerable library containing ${numberOfCves} CVE's` +
21
- '************************** ')
22
- : console.log('\n **************************' +
23
- ` Found ${numberOfVulnerableLibraries} vulnerable libraries containing ${numberOfCves} CVE's ` +
24
- '************************** ');
14
+ ? console.log(` Found 1 vulnerable library containing ${numberOfCves} CVE's`)
15
+ : console.log(` Found ${numberOfVulnerableLibraries} vulnerable libraries containing ${numberOfCves} CVE's `);
25
16
  };
26
17
  exports.createLibraryHeader = createLibraryHeader;
27
18
  const getReport = async (config, reportId) => {
28
19
  const client = (0, commonApi_1.getHttpClient)(config);
29
- const reportSpinner = (0, oraWrapper_1.returnOra)(i18n_1.default.__('auditReportWaiting'));
30
- reportSpinner.indent = 1;
31
- (0, oraWrapper_1.startSpinner)(reportSpinner);
32
20
  return client
33
21
  .getReportById(config, reportId)
34
22
  .then((res) => {
35
23
  if (res.statusCode === 200) {
36
- (0, oraWrapper_1.succeedSpinner)(reportSpinner, i18n_1.default.__('auditReportSuccessMessage'));
37
24
  return res.body;
38
25
  }
39
26
  else {
40
- (0, oraWrapper_1.failSpinner)(reportSpinner, i18n_1.default.__('auditReportFail'));
41
27
  console.log('config-------------------');
42
28
  console.log(config);
43
29
  console.log('reportId----------------');
@@ -17,7 +17,7 @@ function formatVulnerabilityOutput(libraryVulnerabilityResponse, id, name, confi
17
17
  const numberOfVulnerableLibraries = vulnerableLibraries.length;
18
18
  let numberOfCves = 0;
19
19
  vulnerableLibraries.forEach(lib => (numberOfCves += lib.cveArray.length));
20
- (0, commonReportingFunctions_1.createLibraryHeader)(id, numberOfVulnerableLibraries, numberOfCves, name);
20
+ (0, commonReportingFunctions_1.createLibraryHeader)(id, numberOfVulnerableLibraries, numberOfCves);
21
21
  const hasSomeVulnerabilitiesReported = (0, commonReportingFunctions_1.printVulnerabilityResponse)(vulnerableLibraries, config);
22
22
  return [
23
23
  hasSomeVulnerabilitiesReported,
@@ -1,18 +1,8 @@
1
1
  "use strict";
2
- const prettyjson = require('prettyjson');
3
- const i18n = require('i18n');
4
2
  const { getHttpClient } = require('../../utils/commonApi');
5
3
  const { handleResponseErrors } = require('../../common/errorHandling');
6
4
  const { APP_VERSION } = require('../../constants/constants');
7
- function displaySnapshotSuccessMessage(config) {
8
- console.log('\n **************************' +
9
- i18n.__('successHeader') +
10
- '************************** ');
11
- console.log('\n' + i18n.__('snapshotSuccessMessage') + '\n');
12
- console.log(` ${config.host}/Contrast/static/ng/index.html#/${config.organizationId}/applications/${config.applicationId}/libs/dependency-tree`);
13
- console.log('\n ***********************************************************');
14
- }
15
- const newSendSnapShot = async (analysis, applicationId) => {
5
+ const newSendSnapShot = async (analysis) => {
16
6
  const analysisLanguage = analysis.config.language.toLowerCase();
17
7
  const requestBody = {
18
8
  appID: analysis.config.applicationId,
@@ -24,9 +14,6 @@ const newSendSnapShot = async (analysis, applicationId) => {
24
14
  .sendSnapshot(requestBody, analysis.config)
25
15
  .then(res => {
26
16
  if (res.statusCode === 201) {
27
- if (analysis.config.host !== 'https://ce.contrastsecurity.com/') {
28
- displaySnapshotSuccessMessage(analysis.config);
29
- }
30
17
  return res.body;
31
18
  }
32
19
  else {
@@ -38,6 +25,5 @@ const newSendSnapShot = async (analysis, applicationId) => {
38
25
  });
39
26
  };
40
27
  module.exports = {
41
- newSendSnapShot: newSendSnapShot,
42
- displaySnapshotSuccessMessage: displaySnapshotSuccessMessage
28
+ newSendSnapShot: newSendSnapShot
43
29
  };
@@ -8,14 +8,20 @@ const paramHandler_1 = __importDefault(require("../../utils/paramsUtil/paramHand
8
8
  const constants_1 = __importDefault(require("../../constants"));
9
9
  const parsedCLIOptions_1 = __importDefault(require("../../utils/parsedCLIOptions"));
10
10
  const constants_2 = __importDefault(require("../../audit/languageAnalysisEngine/constants"));
11
+ const autoDetectLanguage_1 = require("../../audit/autodetection/autoDetectLanguage");
11
12
  const { supportedLanguages: { NODE, JAVASCRIPT } } = constants_2.default;
12
13
  const getAuditConfig = (argv) => {
13
14
  const auditParameters = parsedCLIOptions_1.default.getCommandLineArgsCustom(argv, constants_1.default.commandLineDefinitions.auditOptionDefinitions);
14
15
  const paramsAuth = paramHandler_1.default.getAuth(auditParameters);
15
16
  if (auditParameters.language === undefined ||
16
17
  auditParameters.language === null) {
17
- console.log('error, --language parameter is required');
18
- process.exit(1);
18
+ try {
19
+ auditParameters.language = (0, autoDetectLanguage_1.determineProjectLanguage)((0, autoDetectLanguage_1.identifyLanguages)(auditParameters));
20
+ }
21
+ catch (err) {
22
+ console.log(err.message);
23
+ process.exit(1);
24
+ }
19
25
  }
20
26
  else if (auditParameters.language.toUpperCase() === JAVASCRIPT) {
21
27
  auditParameters.language = NODE.toLowerCase();
@@ -3,11 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.startAudit = void 0;
6
+ exports.startAudit = exports.dealWithNoAppId = 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
10
  const languageFactory = require('../../audit/languageAnalysisEngine/languageAnalysisFactory');
11
+ const { v4: uuidv4 } = require('uuid');
11
12
  const dealWithNoAppId = async (config) => {
12
13
  let appID;
13
14
  try {
@@ -15,6 +16,10 @@ const dealWithNoAppId = async (config) => {
15
16
  if (!appID && config.applicationName) {
16
17
  return await (0, catalogueApplication_1.catalogueApplication)(config);
17
18
  }
19
+ if (!appID && !config.applicationName) {
20
+ config.applicationName = uuidv4();
21
+ return await (0, catalogueApplication_1.catalogueApplication)(config);
22
+ }
18
23
  }
19
24
  catch (e) {
20
25
  if (e.toString().includes('tunneling socket could not be established')) {
@@ -25,9 +30,10 @@ const dealWithNoAppId = async (config) => {
25
30
  }
26
31
  return appID;
27
32
  };
33
+ exports.dealWithNoAppId = dealWithNoAppId;
28
34
  const startAudit = async (config) => {
29
35
  if (!config.applicationId) {
30
- config.applicationId = await dealWithNoAppId(config);
36
+ config.applicationId = await (0, exports.dealWithNoAppId)(config);
31
37
  }
32
38
  identifyLanguageAE(config.projectPath, languageFactory, config.applicationId, config);
33
39
  };
@@ -1,12 +1,15 @@
1
1
  "use strict";
2
- const { startScan } = require('../../scan/scanController');
3
- const { scanUsageGuide } = require('../../scan/help');
4
2
  const scanConfig = require('../../scan/scanConfig');
3
+ const { startScan } = require('../../scan/scanController');
5
4
  const { saveScanFile } = require('../../utils/saveFile');
6
5
  const { ScanResultsModel } = require('../../scan/models/scanResultsModel');
7
- const { formatScanOutput } = require('../../scan/scan');
6
+ const { formatScanOutput } = require('../../scan/formatScanOutput');
7
+ const { processSca } = require('./sca/scaAnalysis');
8
8
  const processScan = async (argvMain) => {
9
9
  let config = scanConfig.getScanConfig(argvMain);
10
+ if (config.experimental) {
11
+ await processSca(config);
12
+ }
10
13
  let scanResults = new ScanResultsModel(await startScan(config));
11
14
  if (scanResults) {
12
15
  formatScanOutput(scanResults);
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ const autoDetection = require('../../../scan/autoDetection');
3
+ const { javaAnalysis } = require('../../../scaAnalysis/java');
4
+ const { commonSendSnapShot } = require('../../../scaAnalysis/common/treeUpload');
5
+ const { manualDetectAuditFilesAndLanguages } = require('../../../scan/autoDetection');
6
+ const { dealWithNoAppId } = require('../../audit/auditController');
7
+ const { supportedLanguages: { JAVA } } = require('../../../audit/languageAnalysisEngine/constants');
8
+ const processSca = async (config) => {
9
+ let filesFound;
10
+ if (config.projectPath) {
11
+ filesFound = await manualDetectAuditFilesAndLanguages(config.projectPath);
12
+ }
13
+ else {
14
+ filesFound = await autoDetection.autoDetectAuditFilesAndLanguages(config);
15
+ }
16
+ let messageToSend = undefined;
17
+ if (filesFound.length === 1) {
18
+ switch (Object.keys(filesFound[0])[0]) {
19
+ case JAVA:
20
+ messageToSend = await javaAnalysis(config, filesFound[0]);
21
+ config.language = JAVA;
22
+ break;
23
+ default:
24
+ console.log('language detected not supported');
25
+ return;
26
+ }
27
+ if (!config.applicationId) {
28
+ config.applicationId = await dealWithNoAppId(config);
29
+ }
30
+ console.log('processing dependencies');
31
+ const response = await commonSendSnapShot(messageToSend, config);
32
+ }
33
+ else {
34
+ if (filesFound.length === 0) {
35
+ console.log('no compatible dependency files detected. Continuing...');
36
+ }
37
+ else {
38
+ console.log('multiple language files detected, please use --project-path to specify a directory or the file where dependencies are declared');
39
+ }
40
+ }
41
+ };
42
+ module.exports = {
43
+ processSca
44
+ };
@@ -146,7 +146,6 @@ HTTPClient.prototype.catalogueCommand = function catalogueCommand(config) {
146
146
  };
147
147
  HTTPClient.prototype.sendSnapshot = function sendSnapshot(requestBody, config) {
148
148
  if (config.language.toUpperCase() === 'RUBY') {
149
- console.log('sendSnapshot requestBody', requestBody.snapshot.ruby);
150
149
  }
151
150
  const options = _.cloneDeep(this.requestOptions);
152
151
  let url = createSnapshotURL(config);
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.findCommandOnError = exports.libraryAnalysisError = exports.handleResponseErrors = exports.getErrorMessage = exports.generalError = exports.hostWarningError = exports.failOptionError = exports.proxyError = exports.forbiddenError = exports.badRequestError = exports.unauthenticatedError = exports.genericError = void 0;
6
+ 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
7
  const i18n_1 = __importDefault(require("i18n"));
8
8
  const handleResponseErrors = (res, api) => {
9
9
  if (res.statusCode === 400) {
@@ -36,23 +36,17 @@ const libraryAnalysisError = () => {
36
36
  };
37
37
  exports.libraryAnalysisError = libraryAnalysisError;
38
38
  const snapshotFailureError = () => {
39
- console.log('\n ******************************** ' +
40
- i18n_1.default.__('snapshotFailureHeader') +
41
- ' *********************************\n' +
42
- i18n_1.default.__('snapshotFailureMessage'));
39
+ console.log(i18n_1.default.__('snapshotFailureMessage'));
43
40
  };
41
+ exports.snapshotFailureError = snapshotFailureError;
44
42
  const vulnerabilitiesFailureError = () => {
45
- console.log('\n ******************************** ' +
46
- i18n_1.default.__('snapshotFailureHeader') +
47
- ' *********************************\n' +
48
- i18n_1.default.__('vulnerabilitiesFailureMessage'));
43
+ console.log(i18n_1.default.__('vulnerabilitiesFailureMessage'));
49
44
  };
45
+ exports.vulnerabilitiesFailureError = vulnerabilitiesFailureError;
50
46
  const reportFailureError = () => {
51
- console.log('\n ******************************** ' +
52
- i18n_1.default.__('snapshotFailureHeader') +
53
- ' *********************************\n' +
54
- i18n_1.default.__('reportFailureMessage'));
47
+ console.log(i18n_1.default.__('auditReportFailureMessage'));
55
48
  };
49
+ exports.reportFailureError = reportFailureError;
56
50
  const genericError = (missingCliOption) => {
57
51
  console.log(`*************************** ${i18n_1.default.__('yamlMissingParametersHeader')} ***************************\n${missingCliOption}`);
58
52
  console.error(i18n_1.default.__('yamlMissingParametersMessage'));
@@ -78,10 +72,6 @@ const proxyError = () => {
78
72
  generalError('proxyErrorHeader', 'proxyErrorMessage');
79
73
  };
80
74
  exports.proxyError = proxyError;
81
- const hostWarningError = () => {
82
- console.log(i18n_1.default.__('snapshotHostMessage'));
83
- };
84
- exports.hostWarningError = hostWarningError;
85
75
  const failOptionError = () => {
86
76
  console.log('\n ******************************** ' +
87
77
  i18n_1.default.__('snapshotFailureHeader') +
@@ -12,11 +12,17 @@ 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.4';
15
+ const APP_VERSION = '1.0.5';
16
16
  const TIMEOUT = 120000;
17
+ const HIGH_COLOUR = '#ff9900';
18
+ const CRITICAL_COLOUR = '#e35858';
19
+ const MEDIUM_COLOUR = '#f1c232';
20
+ const LOW_COLOUR = '#ff9900';
21
+ const NOTE_COLOUR = '#999999';
17
22
  const AUTH_UI_URL = 'https://cli-auth.contrastsecurity.com';
18
23
  const AUTH_CALLBACK_URL = 'https://cli-auth-api.contrastsecurity.com';
19
24
  const SARIF_FILE = 'SARIF';
25
+ const CE_URL = 'https://ce.contrastsecurity.com/';
20
26
  module.exports = {
21
27
  supportedLanguages: { NODE, DOTNET, JAVA, RUBY, PYTHON, GO, PHP, JAVASCRIPT },
22
28
  LOW,
@@ -28,5 +34,11 @@ module.exports = {
28
34
  TIMEOUT,
29
35
  AUTH_UI_URL,
30
36
  AUTH_CALLBACK_URL,
31
- SARIF_FILE
37
+ SARIF_FILE,
38
+ HIGH_COLOUR,
39
+ CRITICAL_COLOUR,
40
+ MEDIUM_COLOUR,
41
+ LOW_COLOUR,
42
+ NOTE_COLOUR,
43
+ CE_URL
32
44
  };
@@ -4,41 +4,29 @@ const chalk = require('chalk');
4
4
  const en_locales = () => {
5
5
  return {
6
6
  successHeader: 'SUCCESS',
7
- snapshotSuccessMessage: ' Please go to the Contrast UI to view your dependency tree.',
7
+ snapshotSuccessMessage: 'Please go to the Contrast UI to view your dependency tree.',
8
8
  snapshotFailureHeader: 'FAIL',
9
- snapshotFailureMessage: ' Unable to send library analysis to your Contrast UI.',
10
- snapshotHostMessage: " No host supplied. Using default host 'app.contrastsecurity.com'. Please ensure this is correct.",
11
- vulnerabilitiesSuccessMessage: ' Vulnerability data successfully retrieved',
12
- vulnerabilitiesFailureMessage: ' Unable to retrieve library vulnerabilities from Team Server.',
9
+ snapshotFailureMessage: 'Library analysis failed',
10
+ snapshotHostMessage: "No host supplied. Using default host 'app.contrastsecurity.com'. Please ensure this is correct.",
11
+ vulnerabilitiesSuccessMessage: 'Vulnerability data successfully retrieved',
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: 'LANGUAGE ANALYSIS FAILED',
15
+ languageAnalysisFailureMessage: 'SCA Analysis Failure',
16
16
  languageAnalysisFactoryFailureHeader: 'FAIL',
17
- projectPathParameter: 'Please set the %s to locate the source code for the project',
18
- apiKeyParameter: 'Please set the %s to connect to the Contrast UI',
19
- applicationNameParameter: 'Please provide a value for %s, to appear in the Contrast UI',
20
- languageParameter: 'Please set the %s to the language of the source project. Allowable values are JAVA, DOTNET, NODE, PYTHON and RUBY.',
21
- hostParameter: 'Please set the %s to the hostname and (optionally) the port expressed as <host>:<port> of the Contrast UI',
22
- organizationIdParameter: 'Please set the %s to correctly identify your organization within the Contrast UI',
23
- authorizationParameter: 'Please set the %s to your authorization header, found in the Contrast UI',
24
- applicationIdParameter: 'Please set the %s to the value provided within the Contrast UI for the target application',
25
- libraryAnalysisError: 'Please ensure the language parameter is set in accordance to the language specified on the project path.\nThe Contrast-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',
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',
26
18
  yamlMissingParametersHeader: 'Missing Parameters',
27
- yamlMissingParametersMessage: 'The following parameters are required: \n \norganization_id \napi_key \nauthorization \nhost \napplication_name or application_id \nlanguage \n \nThey must be specified as a command line argument or within the yaml file. \nFor further information please read our usage guide, which can be accessed with the following command:\ncontrast-cli --help',
19
+ yamlMissingParametersMessage: 'The following parameters are required: \n \norganization-id \napi-key \nauthorization \nhost \nlanguage \n \nThey must be specified as a command line argument. \nFor further information please read our usage guide, which can be accessed with the following command:\ncontrast audit --help',
28
20
  unauthenticatedErrorHeader: '401 error - Unauthenticated',
29
- unauthenticatedErrorMessage: 'Please check the following keys are correct:\n--organization_id, --api_key or --authorization',
21
+ unauthenticatedErrorMessage: 'Please check the following keys are correct:\n--organization-id, --api-key or --authorization',
30
22
  badRequestErrorHeader: '400 error - Bad Request',
31
- badRequestErrorMessage: 'Please check the following key is correct: \n--application_id',
23
+ badRequestErrorMessage: 'Please check the following key is correct: \n--application-id',
32
24
  badRequestCatalogueErrorMessage: 'The application name already exists, please use a unique name',
33
25
  forbiddenRequestErrorHeader: '403 error - Forbidden',
34
26
  forbiddenRequestErrorMessage: 'You do not have permission to access this server.',
35
27
  proxyErrorHeader: '407 error - Proxy Authentication Required',
36
28
  proxyErrorMessage: 'Please provide valid authentication credentials for the proxy server.',
37
- downgradeHttpsHttp: 'Connection to ContrastUI using https failed. Attempting to connect using http...',
38
- setSpecifiedParameter: 'Please set the %s ',
39
- catalogueFailureCommand: 'Failed to catalogue a new application for reason: ',
40
- catalogueFailureHostCommand: 'Failed to catalogue a new application, please ensure you have the correct host and authentication. Error: ',
41
- catalogueSuccessCommand: 'This application ID can now be used to send dependency data to Contrast: ',
29
+ catalogueSuccessCommand: 'Application Created',
42
30
  dotnetAnalysisFailure: '.NET analysis failed because: ',
43
31
  dotnetReadLockfile: 'Failed to read the lock file @ %s because: ',
44
32
  dotnetParseLockfile: "Failed to parse .NET lock file @ '%s' because: ",
@@ -82,10 +70,9 @@ const en_locales = () => {
82
70
  constantsOptionalForCatalogue: '(optional for catalogue)',
83
71
  constantsRequired: '(required)',
84
72
  constantsRequiredCatalogue: '(required for catalogue)',
85
- constantsYamlPath: 'If you want to read params from the yaml file then enter the path to the file',
86
73
  constantsApiKey: 'An agent API key as provided by Contrast UI',
87
- constantsAuthorization: 'An agent Authorization credentials as provided by Contrast UI',
88
- constantsOrganizationId: 'The ID of your organization in Contrast UI',
74
+ constantsAuthorization: 'Authorization credentials as provided by Contrast UI',
75
+ constantsOrganizationId: 'The ID of your organization',
89
76
  constantsApplicationId: 'The ID of the application cataloged by Contrast UI',
90
77
  constantsHostId: 'Provide the name of the host and optionally the port expressed as "<host>:<port>".',
91
78
  constantsApplicationName: 'The name of the application cataloged by Contrast UI',
@@ -163,17 +150,17 @@ const en_locales = () => {
163
150
  goReadProjectFile: 'Failed to read the project file @ "%s" because: "%s"',
164
151
  goAnalysisError: 'GO analysis failed because: ',
165
152
  goParseProjectFile: 'Failed to parse go mod graph output because: ',
166
- mavenNotInstalledError: " 'mvn' is not available. Please ensure you have Maven installed and available on your path.",
153
+ mavenNotInstalledError: "'mvn' is not available. Please ensure you have Maven installed and available on your path.",
167
154
  mavenDependencyTreeNonZero: 'Building maven dependancy tree failed with a non 0 exit code',
168
- gradleWrapperUnavailable: ' Gradle wrapper not found in root of project. Please ensure gradlew or gradlew.bat is in root of the project.',
155
+ gradleWrapperUnavailable: 'Gradle wrapper not found in root of project. Please ensure gradlew or gradlew.bat is in root of the project.',
169
156
  gradleDependencyTreeNonZero: "Building gradle dependancy tree failed with a non 0 exit code. \n Please check you have the correct version of Java installed to compile your project? \n If running against a muti module project ensure you are using the '--sub-project' flag",
170
- yamlPathCamelCaseError: ' Warning: The "yamlPath" parameter will be deprecated in a future release. Please look at our documentation for further guidance.',
171
- constantsSbom: ' Generate the Software Bill of Materials (SBOM) for the given application',
157
+ yamlPathCamelCaseError: 'Warning: The "yamlPath" parameter will be deprecated in a future release. Please look at our documentation for further guidance.',
158
+ constantsSbom: 'Generate the Software Bill of Materials (SBOM) for the given application',
172
159
  constantsMetadata: 'Define a set of key=value pairs (which conforms to RFC 2253) for specifying user-defined metadata associated with the application.',
173
160
  constantsTags: 'Apply labels to an application. Labels must be formatted as a comma-delimited list. Example - label1,label2,label3',
174
161
  constantsCode: 'Add the application code this application should use in the Contrast UI',
175
- constantsIgnoreCertErrors: ' For EOP users with a local Teamserver install, this will bypass the SSL certificate and recognise a self signed certificate.',
176
- constantsSave: ' Saves the Scan Results SARIF to file.',
162
+ constantsIgnoreCertErrors: 'For EOP users with a local Teamserver install, this will bypass the SSL certificate and recognise a self signed certificate.',
163
+ constantsSave: 'Saves the Scan Results SARIF to file.',
177
164
  scanLabel: "adds a label to the scan - defaults to 'Started by CLI tool at current date'",
178
165
  constantsIgnoreDev: 'Combined with the --report command excludes developer dependencies from the vulnerabilities report. By default all dependencies are included in a report.',
179
166
  constantsCommands: 'Commands',
@@ -189,8 +176,9 @@ const en_locales = () => {
189
176
  waitingTimedOut: 'Timed out.',
190
177
  responseMessage: 'Response: %s',
191
178
  searchingDirectoryScan: 'Searched 3 directory levels & found: ',
192
- noFileFoundScan: "We could't find a suitable file in your directories (we go 3 deep)",
179
+ noFileFoundScan: "We couldn't find a suitable file in your directories (we go 3 deep)",
193
180
  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>"',
181
+ specifyFileAuditNotFound: 'No files found for library analysis',
194
182
  populateProjectIdMessage: 'project ID is %s',
195
183
  genericServiceError: 'returned with status code %s',
196
184
  projectIdError: 'Your project ID is %s please check this is correct',
@@ -229,6 +217,7 @@ const en_locales = () => {
229
217
  requiredParams: 'All required parameters are not present.',
230
218
  timeoutScan: 'Timeout set to 5 minutes.',
231
219
  searchingScanFileDirectory: 'Searching for file to scan from %s...',
220
+ searchingAuditFileDirectory: 'Searching for package manager files from %s...',
232
221
  scanHeader: 'Contrast Scan CLI',
233
222
  authHeader: 'Auth',
234
223
  lambdaHeader: 'Contrast Lambda CLI',
@@ -288,15 +277,19 @@ const en_locales = () => {
288
277
  auditOptionsIgnoreDevDependenciesDescription: 'ignores DevDependencies',
289
278
  auditOptionsSave: '-s, --save',
290
279
  auditOptionsSaveDescription: 'saves the output in specified format Txt text, sbom',
280
+ scanNotCompleted: 'Scan not completed. Check for framework and language support here: %s',
291
281
  scanNoVulnerabilitiesFound: '👏 No vulnerabilities found',
282
+ scanNoVulnerabilitiesFoundSecureCode: '👍 Your code looks secure.',
283
+ scanNoVulnerabilitiesFoundGoodWork: '👏 Keep up the good work.',
292
284
  scanNoFiletypeSpecifiedForSave: 'Please specify file type to save results to, accepted value is SARIF',
293
285
  auditSBOMSaveSuccess: '\n Software Bill of Materials (SBOM) saved successfully',
294
286
  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.')}`,
295
287
  auditBadFiletypeSpecifiedForSave: `\n ${chalk.yellow.bold('Bad file type specified for --save option. Use audit --help to see valid --save options.')}`,
296
288
  auditReportWaiting: 'Waiting for report...',
297
289
  auditReportFail: 'Report Retrieval Failed, please try again',
298
- auditReportSuccessMessage: ' Report successfully retrieved',
299
- auditReportFailureMessage: ' Unable to generate library report.',
290
+ auditReportSuccessMessage: 'Report successfully retrieved',
291
+ auditReportFailureMessage: 'Unable to generate library report',
292
+ auditSCAAnalysisBegins: 'Contrast SCA analysis begins',
300
293
  ...lambda
301
294
  };
302
295
  };
package/dist/constants.js CHANGED
@@ -41,6 +41,14 @@ const scanOptionDefinitions = [
41
41
  '}: ' +
42
42
  i18n.__('constantsProjectId')
43
43
  },
44
+ {
45
+ name: 'project-path',
46
+ alias: 'i',
47
+ description: '{bold ' +
48
+ i18n.__('constantsOptional') +
49
+ '}: ' +
50
+ i18n.__('constantsProjectPath')
51
+ },
44
52
  {
45
53
  name: 'timeout',
46
54
  alias: 't',
@@ -129,6 +137,18 @@ const scanOptionDefinitions = [
129
137
  name: 'debug',
130
138
  alias: 'd',
131
139
  type: Boolean
140
+ },
141
+ {
142
+ name: 'experimental',
143
+ alias: 'e',
144
+ type: Boolean
145
+ },
146
+ {
147
+ name: 'application-name',
148
+ description: '{bold ' +
149
+ i18n.__('constantsOptional') +
150
+ '}: ' +
151
+ i18n.__('constantsApplicationName')
132
152
  }
133
153
  ];
134
154
  const authOptionDefinitions = [
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ const createJavaTSMessage = javaTree => {
3
+ return {
4
+ java: {
5
+ mavenDependencyTrees: javaTree
6
+ }
7
+ };
8
+ };
9
+ module.exports = {
10
+ createJavaTSMessage
11
+ };