@contrast/contrast 1.0.3 → 1.0.6

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 (107) hide show
  1. package/.prettierignore +4 -0
  2. package/README.md +20 -14
  3. package/dist/audit/autodetection/autoDetectLanguage.js +32 -0
  4. package/dist/audit/catalogueApplication/catalogueApplication.js +2 -11
  5. package/dist/audit/languageAnalysisEngine/{langugageAnalysisFactory.js → languageAnalysisFactory.js} +6 -14
  6. package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +29 -0
  7. package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +101 -234
  8. package/dist/audit/languageAnalysisEngine/report/models/reportLibraryModel.js +19 -0
  9. package/dist/audit/languageAnalysisEngine/report/models/reportListModel.js +24 -0
  10. package/dist/audit/languageAnalysisEngine/report/models/reportOutputModel.js +24 -0
  11. package/dist/audit/languageAnalysisEngine/report/models/reportSeverityModel.js +12 -0
  12. package/dist/audit/languageAnalysisEngine/report/models/severityCountModel.js +13 -0
  13. package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +24 -129
  14. package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +99 -0
  15. package/dist/audit/languageAnalysisEngine/sendSnapshot.js +2 -14
  16. package/dist/commands/audit/auditConfig.js +8 -2
  17. package/dist/commands/audit/auditController.js +14 -5
  18. package/dist/commands/scan/processScan.js +10 -6
  19. package/dist/commands/scan/sca/scaAnalysis.js +49 -0
  20. package/dist/common/HTTPClient.js +18 -26
  21. package/dist/common/errorHandling.js +7 -17
  22. package/dist/common/versionChecker.js +14 -12
  23. package/dist/constants/constants.js +24 -2
  24. package/dist/constants/lambda.js +3 -1
  25. package/dist/constants/locales.js +42 -42
  26. package/dist/constants.js +25 -1
  27. package/dist/index.js +2 -2
  28. package/dist/lambda/help.js +22 -14
  29. package/dist/lambda/lambda.js +6 -0
  30. package/dist/scaAnalysis/common/formatMessage.js +19 -0
  31. package/dist/scaAnalysis/common/treeUpload.js +29 -0
  32. package/dist/scaAnalysis/go/goAnalysis.js +17 -0
  33. package/dist/scaAnalysis/go/goParseDeps.js +158 -0
  34. package/dist/scaAnalysis/go/goReadDepFile.js +23 -0
  35. package/dist/scaAnalysis/java/analysis.js +108 -0
  36. package/dist/scaAnalysis/java/index.js +18 -0
  37. package/dist/scaAnalysis/java/javaBuildDepsParser.js +339 -0
  38. package/dist/scan/autoDetection.js +46 -1
  39. package/dist/scan/fileUtils.js +73 -1
  40. package/dist/scan/formatScanOutput.js +215 -0
  41. package/dist/scan/help.js +3 -1
  42. package/dist/scan/models/groupedResultsModel.js +11 -0
  43. package/dist/scan/models/resultContentModel.js +2 -0
  44. package/dist/scan/models/scanResultsModel.js +11 -0
  45. package/dist/scan/scan.js +27 -126
  46. package/dist/scan/scanConfig.js +1 -1
  47. package/dist/scan/scanController.js +11 -5
  48. package/dist/scan/scanResults.js +15 -19
  49. package/dist/utils/getConfig.js +3 -0
  50. package/dist/utils/oraWrapper.js +5 -1
  51. package/package.json +3 -2
  52. package/src/audit/autodetection/autoDetectLanguage.ts +40 -0
  53. package/src/audit/catalogueApplication/catalogueApplication.js +4 -16
  54. package/src/audit/languageAnalysisEngine/{langugageAnalysisFactory.js → languageAnalysisFactory.js} +11 -21
  55. package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +72 -0
  56. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +204 -0
  57. package/src/audit/languageAnalysisEngine/report/models/reportLibraryModel.ts +30 -0
  58. package/src/audit/languageAnalysisEngine/report/models/reportListModel.ts +32 -0
  59. package/src/audit/languageAnalysisEngine/report/models/reportOutputModel.ts +29 -0
  60. package/src/audit/languageAnalysisEngine/report/models/reportSeverityModel.ts +13 -0
  61. package/src/audit/languageAnalysisEngine/report/models/severityCountModel.ts +16 -0
  62. package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +56 -0
  63. package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +116 -0
  64. package/src/audit/languageAnalysisEngine/sendSnapshot.js +2 -22
  65. package/src/commands/audit/auditConfig.ts +12 -3
  66. package/src/commands/audit/auditController.ts +20 -5
  67. package/src/commands/audit/processAudit.ts +3 -0
  68. package/src/commands/scan/processScan.js +13 -9
  69. package/src/commands/scan/sca/scaAnalysis.js +75 -0
  70. package/src/common/HTTPClient.js +31 -38
  71. package/src/common/errorHandling.ts +7 -25
  72. package/src/common/versionChecker.ts +24 -22
  73. package/src/constants/constants.js +24 -2
  74. package/src/constants/lambda.js +3 -1
  75. package/src/constants/locales.js +47 -56
  76. package/src/constants.js +29 -1
  77. package/src/index.ts +2 -3
  78. package/src/lambda/help.ts +22 -14
  79. package/src/lambda/lambda.ts +8 -0
  80. package/src/scaAnalysis/common/formatMessage.js +20 -0
  81. package/src/scaAnalysis/common/treeUpload.js +30 -0
  82. package/src/scaAnalysis/go/goAnalysis.js +20 -0
  83. package/src/scaAnalysis/go/goParseDeps.js +203 -0
  84. package/src/scaAnalysis/go/goReadDepFile.js +32 -0
  85. package/src/scaAnalysis/java/analysis.js +143 -0
  86. package/src/scaAnalysis/java/index.js +21 -0
  87. package/src/scaAnalysis/java/javaBuildDepsParser.js +404 -0
  88. package/src/scan/autoDetection.js +54 -1
  89. package/src/scan/fileUtils.js +91 -1
  90. package/src/scan/formatScanOutput.ts +250 -0
  91. package/src/scan/help.js +3 -1
  92. package/src/scan/models/groupedResultsModel.ts +20 -0
  93. package/src/scan/models/resultContentModel.ts +86 -0
  94. package/src/scan/models/scanResultsModel.ts +52 -0
  95. package/src/scan/scan.ts +63 -0
  96. package/src/scan/scanConfig.js +1 -1
  97. package/src/scan/scanController.js +15 -7
  98. package/src/scan/scanResults.js +21 -18
  99. package/src/utils/getConfig.ts +10 -0
  100. package/src/utils/oraWrapper.js +6 -1
  101. package/dist/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +0 -17
  102. package/dist/audit/languageAnalysisEngine/report/newReportingFeature.js +0 -81
  103. package/src/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +0 -27
  104. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.js +0 -303
  105. package/src/audit/languageAnalysisEngine/report/newReportingFeature.js +0 -124
  106. package/src/audit/languageAnalysisEngine/report/reportingFeature.js +0 -190
  107. package/src/scan/scan.js +0 -195
package/.prettierignore CHANGED
@@ -1,3 +1,7 @@
1
1
  test/commands/**
2
2
  dist/**
3
3
  test/errorHandling.spec.ts
4
+ **/models
5
+ **/audit/autodetection/autoDetectLanguage.ts
6
+ **/commands/audit/auditConfig.ts
7
+ **/audit/languageAnalysisEngine/report
package/README.md CHANGED
@@ -9,7 +9,7 @@ CodeSec delivers:
9
9
 
10
10
  ## Install
11
11
 
12
- ```
12
+ ```shell
13
13
  npm install -g @contrast/contrast
14
14
  ```
15
15
 
@@ -23,7 +23,8 @@ In the resulting browser window, log in and authenticate with your GitHub or Goo
23
23
 
24
24
  ### SAST scan
25
25
 
26
- ####Requirements
26
+ #### Scan Requirements
27
+
27
28
  Make sure you have the correct file types to scan.
28
29
 
29
30
  - Upload a .jar or .war file to scan a Java project for analysis
@@ -36,7 +37,7 @@ Use the Contrast scan command `contrast scan`
36
37
 
37
38
  ### Lambda function scan
38
39
 
39
- ####Requirements
40
+ #### Lambda Requirements
40
41
 
41
42
  - Currently supports Java and Python functions on AWS.
42
43
  Configure AWS credentials on your local environment by running the commands with your credentials:
@@ -85,19 +86,24 @@ Performs a security SAST scan.
85
86
 
86
87
  **Options:**
87
88
 
88
- - **contrast scan --file** Path of the file you want to scan. Contrast searches for a .jar, .war .exe or .zip file in the working directory (and 3 folders deep) if a file is not specified.
89
- Alias: **--f**
89
+ - **contrast scan --file**
90
+
91
+ - Path of the file you want to scan. Contrast searches for a .jar, .war, .js. or .zip file in the working directory if a file is not specified.
92
+ - Alias: **--f**
90
93
 
91
94
  - **contrast scan --name**
92
- Contrast project name. If not specified, Contrast creates a project from the name of the file
93
- Alias: **–n**
95
+
96
+ - Contrast project name. If not specified, Contrast uses contrast.settings to identify the project or creates a project.
97
+ - Alias: **–n**
98
+
94
99
  - **contrast scan --save**
95
- Download the results to a Static Analysis Results Interchange Format (SARIF) file.
96
- Alias: **-s**
100
+
101
+ - Download the results to a Static Analysis Results Interchange Format (SARIF) file. The file is downloaded to the current working directory with a default name of results.sarif. You can view the file with any text editor.
102
+ - Alias: **-s**
97
103
 
98
104
  - **contrast scan --timeout**
99
- Time in seconds to wait for the scan to complete. Default value is 300 seconds.
100
- Alias: **-t**
105
+ - Time in seconds to wait for the scan to complete. Default value is 300 seconds.
106
+ - Alias: **-t**
101
107
 
102
108
  ### lambda
103
109
 
@@ -107,6 +113,9 @@ Name of AWS lambda function to scan.
107
113
 
108
114
  **Options:**
109
115
 
116
+ - **contrast lambda --list-functions**
117
+ Lists all available lambda functions to scan.
118
+
110
119
  - **contrast lambda --function-name --endpoint-url**
111
120
  AWS Endpoint override. Similar to AWS CLI.
112
121
  Alias: **-e**
@@ -127,9 +136,6 @@ Name of AWS lambda function to scan.
127
136
  Returns extended information to the terminal.
128
137
  Alias: **-v**
129
138
 
130
- - **contrast lambda -–function-name --list-functions**
131
- Lists all available lambda functions to scan.
132
-
133
139
  - **contrast lambda --function-name -–help**
134
140
  Displays usage guide.
135
141
  Alias: **-h**
@@ -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 {
@@ -9,13 +9,12 @@ const pythonAE = require('../pythonAnalysisEngine');
9
9
  const phpAE = require('../phpAnalysisEngine');
10
10
  const goAE = require('../goAnalysisEngine');
11
11
  const { vulnerabilityReport } = require('./report/reportingFeature');
12
- const { vulnReportWithoutDevDep } = require('./report/newReportingFeature');
13
- const { checkDevDeps } = require('./report/checkIgnoreDevDep');
14
12
  const { newSendSnapShot } = require('../languageAnalysisEngine/sendSnapshot');
15
13
  const fs = require('fs');
16
14
  const chalk = require('chalk');
17
15
  const saveFile = require('../../commands/audit/saveFile').default;
18
16
  const generateSbom = require('../../sbom/generateSbom').default;
17
+ const { failSpinner, returnOra, startSpinner, succeedSpinner } = require('../../utils/oraWrapper');
19
18
  module.exports = exports = (err, analysis) => {
20
19
  const { identifiedLanguageInfo } = analysis.languageAnalysis;
21
20
  const catalogueAppId = analysis.languageAnalysis.appId;
@@ -37,19 +36,12 @@ module.exports = exports = (err, analysis) => {
37
36
  err);
38
37
  return process.exit(5);
39
38
  }
40
- console.log('\n **************CONTRAST OSS ANALYSIS BEGINS**************');
39
+ const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'));
40
+ startSpinner(reportSpinner);
41
41
  const snapshotResponse = await newSendSnapShot(analysis, catalogueAppId);
42
- if (config.report) {
43
- const ignoreDevUrl = await checkDevDeps(config);
44
- if (ignoreDevUrl) {
45
- await vulnReportWithoutDevDep(analysis, catalogueAppId, snapshotResponse.id, config);
46
- }
47
- else {
48
- await vulnerabilityReport(analysis, catalogueAppId, config);
49
- }
50
- }
42
+ succeedSpinner(reportSpinner, 'Contrast SCA analysis complete');
43
+ await vulnerabilityReport(analysis, catalogueAppId, snapshotResponse.id);
51
44
  await auditSave(config);
52
- console.log('\n ***************CONTRAST OSS ANALYSIS COMPLETE************** \n');
53
45
  };
54
46
  if (identifiedLanguageInfo.language === DOTNET) {
55
47
  dotnetAE(identifiedLanguageInfo, analysis.config, langCallback);
@@ -89,7 +81,7 @@ async function auditSave(config) {
89
81
  console.log(i18n.__('auditBadFiletypeSpecifiedForSave'));
90
82
  }
91
83
  }
92
- else {
84
+ else if (config.save === null) {
93
85
  console.log(i18n.__('auditNoFiletypeSpecifiedForSave'));
94
86
  }
95
87
  }
@@ -22,6 +22,34 @@ 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
+ if (isGoProjectFilename(filename)) {
46
+ deducedLanguages.push({ language: GO, projectFilename: filename });
47
+ language = GO;
48
+ }
49
+ });
50
+ let identifiedLanguages = { [language]: deducedLanguages };
51
+ return identifiedLanguages;
52
+ };
25
53
  const deduceLanguage = filename => {
26
54
  const deducedLanguages = [];
27
55
  if (isJavaMavenProjectFilename(filename)) {
@@ -119,3 +147,4 @@ exports.isPhpProjectFilename = isPhpProjectFilename;
119
147
  exports.isPhpLockFilename = isPhpLockFilename;
120
148
  exports.deduceLanguage = deduceLanguage;
121
149
  exports.reduceIdentifiedLanguages = reduceIdentifiedLanguages;
150
+ exports.deduceLanguageScaAnalysis = deduceLanguageScaAnalysis;
@@ -1,257 +1,124 @@
1
1
  "use strict";
2
- const i18n = require('i18n');
3
- const { getHttpClient } = require('../../../utils/commonApi');
4
- function displaySuccessMessageReport() {
5
- console.log('\n' + i18n.__('reportSuccessMessage'));
6
- }
7
- function getAllDependenciesArray(packageJson) {
8
- const { dependencies, optionalDependencies, devDependencies, peerDependencies } = packageJson;
9
- const allDep = {
10
- ...dependencies,
11
- ...devDependencies,
12
- ...optionalDependencies,
13
- ...peerDependencies
14
- };
15
- return Object.entries(allDep);
16
- }
17
- function checkIfDepIsScoped(arrDep) {
18
- let count = 0;
19
- arrDep.forEach(([key, value]) => {
20
- if (!key.startsWith('@')) {
21
- console.log(` WARNING not scoped: ${key}:${value}`);
22
- count++;
23
- }
24
- });
25
- return count;
26
- }
27
- const dependencyRiskReport = async (packageJson, config) => {
28
- const arrDep = getAllDependenciesArray(packageJson);
29
- const unRegisteredDeps = await checkIfDepIsRegisteredOnNPM(arrDep, config);
30
- let scopedCount = checkIfDepIsScoped(unRegisteredDeps);
31
- return {
32
- scopedCount: scopedCount,
33
- unRegisteredCount: unRegisteredDeps.length
34
- };
35
- };
36
- const checkIfDepIsRegisteredOnNPM = async (arrDep, config) => {
37
- let promises = [];
38
- let unRegisteredDeps = [];
39
- const client = getHttpClient(config);
40
- for (const [index, element] of arrDep) {
41
- const query = `query artifactByGAV($name: String!, $language: String!, $groupName: String, $version: String!, $nameCheck: Boolean) {
42
- artifact: exactVersion(name: $name, language: $language, groupName: $groupName, version: $version, nameCheck: $nameCheck) {
43
- version
44
- cves {
45
- baseScore
46
- }}}`;
47
- const data = {
48
- query: query,
49
- variables: {
50
- name: index,
51
- version: element,
52
- language: 'node',
53
- nameCheck: true
54
- }
55
- };
56
- promises.push(client.checkLibrary(data));
57
- }
58
- await Promise.all(promises).then(response => {
59
- response.forEach(res => {
60
- const libName = JSON.parse(res.request.body);
61
- if (res.statusCode === 200) {
62
- if (res.body.data.artifact == null) {
63
- unRegisteredDeps.push([
64
- libName.variables.name,
65
- libName.variables.version
66
- ]);
67
- }
68
- }
69
- });
70
- });
71
- if (unRegisteredDeps.length !== 0) {
72
- console.log('\n Dependencies Risk Report', '\n\n Private libraries that are not scoped. We recommend these libraries are reviewed and the scope claimed to prevent dependency confusion breaches');
73
- }
74
- return unRegisteredDeps;
75
- };
76
- const createLibraryHeader = (id, numberOfVulnerableLibraries, numberOfCves, name) => {
77
- name
78
- ? console.log(` Application Name: ${name} | Application ID: ${id}`)
79
- : console.log(` Application ID: ${id}`);
80
- console.log(` Found ${numberOfVulnerableLibraries} vulnerable libraries containing ${numberOfCves} CVE's`);
81
- };
82
- const breakPipeline = () => {
83
- failOptionError();
84
- process.exit(1);
85
- };
86
- const parameterOptions = hasSomeVulnerabilitiesReported => {
87
- const inputtedCLIOptions = cliOptions.getCommandLineArgs();
88
- let cveSeverityOption = inputtedCLIOptions['cve_severity'];
89
- let fail = inputtedCLIOptions['fail'];
90
- let cve_threshold = inputtedCLIOptions['cve_threshold'];
91
- let expr;
92
- if (cveSeverityOption && fail && cve_threshold) {
93
- expr = 'SeverityAndThreshold';
94
- }
95
- else if (!cveSeverityOption && fail && cve_threshold) {
96
- expr = 'ThresholdOnly';
97
- }
98
- else if (!cve_threshold && fail && hasSomeVulnerabilitiesReported[0]) {
99
- expr = 'FailOnly';
100
- }
101
- return expr;
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
102
4
  };
103
- const analyseReportOptions = hasSomeVulnerabilitiesReported => {
104
- const inputtedCLIOptions = cliOptions.getCommandLineArgs();
105
- let cve_threshold = inputtedCLIOptions['cve_threshold'];
106
- let cveSeverity;
107
- let criticalSeverity;
108
- let highSeverity;
109
- let mediumSeverity;
110
- let lowSeverity;
111
- switch (parameterOptions(hasSomeVulnerabilitiesReported)) {
112
- case 'SeverityAndThreshold':
113
- cveSeverity = inputtedCLIOptions['cve_severity'].severity;
114
- criticalSeverity = hasSomeVulnerabilitiesReported[2].critical;
115
- highSeverity = hasSomeVulnerabilitiesReported[2].high;
116
- mediumSeverity = hasSomeVulnerabilitiesReported[2].medium;
117
- lowSeverity = hasSomeVulnerabilitiesReported[2].low;
118
- if (cveSeverity === 'HIGH') {
119
- if (cve_threshold < highSeverity + criticalSeverity) {
120
- breakPipeline();
121
- }
122
- }
123
- if (cveSeverity === 'MEDIUM') {
124
- if (cve_threshold < mediumSeverity + highSeverity) {
125
- breakPipeline();
126
- }
127
- }
128
- if (cveSeverity === 'LOW') {
129
- if (cve_threshold < lowSeverity + mediumSeverity + highSeverity) {
130
- breakPipeline();
131
- }
132
- }
133
- break;
134
- case 'ThresholdOnly':
135
- if (cve_threshold < hasSomeVulnerabilitiesReported[1]) {
136
- breakPipeline();
137
- }
138
- break;
139
- case 'FailOnly':
140
- breakPipeline();
141
- break;
142
- }
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getNumOfAndSeverityType = exports.buildFormattedHeaderNum = exports.buildBody = exports.buildHeader = exports.printFormattedOutput = exports.printVulnerabilityResponse = exports.getReport = exports.createLibraryHeader = void 0;
7
+ const commonApi_1 = require("../../../utils/commonApi");
8
+ const reportListModel_1 = require("./models/reportListModel");
9
+ const lodash_1 = require("lodash");
10
+ const chalk_1 = __importDefault(require("chalk"));
11
+ const reportUtils_1 = require("./utils/reportUtils");
12
+ const severityCountModel_1 = require("./models/severityCountModel");
13
+ const reportOutputModel_1 = require("./models/reportOutputModel");
14
+ const createLibraryHeader = (id, numberOfVulnerableLibraries, numberOfCves) => {
15
+ numberOfVulnerableLibraries === 1
16
+ ? console.log(` Found 1 vulnerable library containing ${numberOfCves} CVE's`)
17
+ : console.log(` Found ${numberOfVulnerableLibraries} vulnerable libraries containing ${numberOfCves} CVE's `);
143
18
  };
144
- const getReport = async (applicationId) => {
145
- const userParams = await util.getParams(applicationId);
146
- const addParams = agent.getAdditionalParams();
147
- const protocol = getValidHost(userParams.host);
148
- const client = commonApi.getHttpClient(userParams, protocol, addParams);
19
+ exports.createLibraryHeader = createLibraryHeader;
20
+ const getReport = async (config, reportId) => {
21
+ const client = (0, commonApi_1.getHttpClient)(config);
149
22
  return client
150
- .getReport(userParams)
151
- .then(res => {
23
+ .getReportById(config, reportId)
24
+ .then((res) => {
152
25
  if (res.statusCode === 200) {
153
- displaySuccessMessageReport();
154
26
  return res.body;
155
27
  }
156
28
  else {
157
- handleResponseErrors(res, 'report');
29
+ console.log('config-------------------');
30
+ console.log(config);
31
+ console.log('reportId----------------');
32
+ console.log(reportId);
33
+ console.log(JSON.stringify(res));
34
+ (0, commonApi_1.handleResponseErrors)(res, 'report');
158
35
  }
159
36
  })
160
- .catch(err => {
37
+ .catch((err) => {
161
38
  console.log(err);
162
39
  });
163
40
  };
164
- const printVulnerabilityResponse = (severity, filteredVulns, vulnerabilities) => {
41
+ exports.getReport = getReport;
42
+ const printVulnerabilityResponse = (vulnerabilities, config) => {
165
43
  let hasSomeVulnerabilitiesReported = false;
166
- if (severity) {
167
- returnCveData(filteredVulns);
168
- if (Object.keys(filteredVulns).length > 0)
169
- hasSomeVulnerabilitiesReported = true;
170
- }
171
- else {
172
- returnCveData(vulnerabilities);
173
- if (Object.keys(vulnerabilities).length > 0)
174
- hasSomeVulnerabilitiesReported = true;
44
+ (0, exports.printFormattedOutput)(vulnerabilities, config);
45
+ if (Object.keys(vulnerabilities).length > 0) {
46
+ hasSomeVulnerabilitiesReported = true;
175
47
  }
176
48
  return hasSomeVulnerabilitiesReported;
177
49
  };
178
- const returnCveData = libraries => {
179
- console.log('\n ************************************************************');
180
- for (const [key, value] of Object.entries(libraries)) {
181
- const parts = key.split('/');
182
- const nameVersion = parts[1].split('@');
183
- const group = parts[0];
184
- const name = nameVersion[0];
185
- const version = nameVersion[1];
186
- const libName = group !== 'null'
187
- ? `${group}/${name}/${version} is vulnerable`
188
- : `${name}/${version} is vulnerable`;
189
- console.log('\n\n ' + libName);
190
- value.forEach(vuln => {
191
- let sevCode = vuln.severityCode || vuln.severity_code;
192
- console.log('\n ' + vuln.name + ' ' + sevCode + '\n ' + vuln.description);
193
- });
50
+ exports.printVulnerabilityResponse = printVulnerabilityResponse;
51
+ const printFormattedOutput = (libraries, config) => {
52
+ const report = new reportListModel_1.ReportList();
53
+ for (const library of libraries) {
54
+ const { name, version } = (0, reportUtils_1.findNameAndVersion)(library, config);
55
+ const newOutputModel = new reportListModel_1.ReportModelStructure(new reportListModel_1.ReportCompositeKey(name, version, (0, reportUtils_1.findHighestSeverityCVE)(library.cveArray)), library.cveArray);
56
+ report.reportOutputList.push(newOutputModel);
194
57
  }
195
- };
196
- function searchHighCVEs(vuln) {
197
- let sevCode = vuln.severityCode || vuln.severity_code;
198
- if (sevCode === 'HIGH') {
199
- return vuln;
58
+ const orderedOutputListLowestFirst = (0, lodash_1.orderBy)(report.reportOutputList, reportListItem => reportListItem.compositeKey.highestSeverity.priority, ['desc']);
59
+ let contrastHeaderNumCounter = 0;
60
+ for (const reportModel of orderedOutputListLowestFirst) {
61
+ contrastHeaderNumCounter++;
62
+ const { libraryName, libraryVersion, highestSeverity } = reportModel.compositeKey;
63
+ const numOfCVEs = reportModel.cveArray.length;
64
+ const header = buildHeader(highestSeverity, contrastHeaderNumCounter, libraryName, libraryVersion, numOfCVEs);
65
+ const body = buildBody(reportModel.cveArray);
66
+ const reportOutputModel = new reportOutputModel_1.ReportOutputModel(header, body);
67
+ console.log(reportOutputModel.header.vulnMessage, reportOutputModel.header.introducesMessage);
68
+ console.log(reportOutputModel.body.issueMessage);
69
+ console.log(reportOutputModel.body.adviceMessage);
200
70
  }
71
+ };
72
+ exports.printFormattedOutput = printFormattedOutput;
73
+ function buildHeader(highestSeverity, contrastHeaderNum, libraryName, version, numOfCVEs) {
74
+ const vulnerabilityPluralised = numOfCVEs > 1 ? 'Vulnerabilities' : 'Vulnerability';
75
+ const formattedHeaderNum = buildFormattedHeaderNum(contrastHeaderNum);
76
+ const vulnMessage = chalk_1.default
77
+ .hex(highestSeverity.outputColour)
78
+ .bold(`${formattedHeaderNum} - [${highestSeverity.severity}] ${libraryName}-${version}`);
79
+ const introducesMessage = chalk_1.default.bold(`introduces ${numOfCVEs} ${vulnerabilityPluralised}`);
80
+ return new reportOutputModel_1.ReportOutputHeaderModel(vulnMessage, introducesMessage);
201
81
  }
202
- function searchMediumCVEs(vuln) {
203
- let sevCode = vuln.severityCode || vuln.severity_code;
204
- if (sevCode === 'HIGH' || sevCode === 'MEDIUM') {
205
- return vuln;
206
- }
82
+ exports.buildHeader = buildHeader;
83
+ function buildBody(cveArray) {
84
+ const cveMessages = [];
85
+ (0, reportUtils_1.findCVESeveritiesAndOrderByHighestPriority)(cveArray).forEach(reportSeverityModel => {
86
+ const { outputColour, severity, cveName } = reportSeverityModel;
87
+ const severityShorthand = chalk_1.default
88
+ .hex(outputColour)
89
+ .bold(`[${severity.charAt(0).toUpperCase()}]`);
90
+ const builtMessage = `${severityShorthand} ${cveName}`;
91
+ cveMessages.push(builtMessage);
92
+ });
93
+ const numAndSeverityType = getNumOfAndSeverityType(cveArray);
94
+ const issueMessage = ` ${chalk_1.default.bold('Issue')} : ${numAndSeverityType} ${cveMessages.join(', ')}.`;
95
+ const adviceMessage = ` ${chalk_1.default.bold('Advice')} : ${chalk_1.default.bold('Update to latest version')}.`;
96
+ return new reportOutputModel_1.ReportOutputBodyModel(issueMessage, adviceMessage);
207
97
  }
208
- function searchLowCVEs(vuln) {
209
- let sevCode = vuln.severityCode || vuln.severity_code;
210
- if (sevCode === 'HIGH' || sevCode === 'MEDIUM' || sevCode === 'LOW') {
211
- return vuln;
98
+ exports.buildBody = buildBody;
99
+ function buildFormattedHeaderNum(contrastHeaderNum) {
100
+ let formattedHeaderNum;
101
+ if (contrastHeaderNum < 10) {
102
+ formattedHeaderNum = `00${contrastHeaderNum}`;
212
103
  }
213
- }
214
- const filterVulnerabilitiesBySeverity = (severity, vulnerabilities) => {
215
- let filteredVulns = [];
216
- if (severity) {
217
- for (let x in vulnerabilities) {
218
- if (severity.severity === 'HIGH') {
219
- let highVulnerability = vulnerabilities[x].filter(searchHighCVEs);
220
- if (highVulnerability.length > 0) {
221
- filteredVulns[x] = highVulnerability;
222
- }
223
- }
224
- else if (severity.severity === 'MEDIUM') {
225
- let mediumVulnerability = vulnerabilities[x].filter(searchMediumCVEs);
226
- if (mediumVulnerability.length > 0) {
227
- filteredVulns[x] = mediumVulnerability;
228
- }
229
- }
230
- else if (severity.severity === 'LOW') {
231
- let lowVulnerability = vulnerabilities[x].filter(searchLowCVEs);
232
- if (lowVulnerability.length > 0) {
233
- filteredVulns[x] = lowVulnerability;
234
- }
235
- }
236
- }
104
+ else if (contrastHeaderNum >= 10 && contrastHeaderNum < 100) {
105
+ formattedHeaderNum = `0${contrastHeaderNum}`;
237
106
  }
238
- return filteredVulns;
239
- };
240
- module.exports = {
241
- displaySuccessMessageReport: displaySuccessMessageReport,
242
- getAllDependenciesArray: getAllDependenciesArray,
243
- dependencyRiskReport: dependencyRiskReport,
244
- createLibraryHeader: createLibraryHeader,
245
- breakPipeline: breakPipeline,
246
- parameterOptions: parameterOptions,
247
- analyseReportOptions: analyseReportOptions,
248
- getReport: getReport,
249
- checkIfDepIsScoped: checkIfDepIsScoped,
250
- checkIfDepIsRegisteredOnNPM: checkIfDepIsRegisteredOnNPM,
251
- filterVulnerabilitiesBySeverity: filterVulnerabilitiesBySeverity,
252
- searchLowCVEs: searchLowCVEs,
253
- searchMediumCVEs: searchMediumCVEs,
254
- searchHighCVEs: searchHighCVEs,
255
- returnCveData: returnCveData,
256
- printVulnerabilityResponse: printVulnerabilityResponse
257
- };
107
+ else if (contrastHeaderNum >= 100) {
108
+ formattedHeaderNum = contrastHeaderNum;
109
+ }
110
+ return `CONTRAST-${formattedHeaderNum}`;
111
+ }
112
+ exports.buildFormattedHeaderNum = buildFormattedHeaderNum;
113
+ function getNumOfAndSeverityType(cveArray) {
114
+ const { critical, high, medium, low, note } = (0, reportUtils_1.severityCountAllCVEs)(cveArray, new severityCountModel_1.SeverityCountModel());
115
+ const criticalMessage = critical > 0 ? `${critical} Critical` : '';
116
+ const highMessage = high > 0 ? `${high} High` : '';
117
+ const mediumMessage = medium > 0 ? `${medium} Medium` : '';
118
+ const lowMessage = low > 0 ? `${low} Low` : '';
119
+ const noteMessage = note > 0 ? `${note} Note` : '';
120
+ return `${criticalMessage} ${highMessage} ${mediumMessage} ${lowMessage} ${noteMessage}`
121
+ .replace(/\s+/g, ' ')
122
+ .trim();
123
+ }
124
+ exports.getNumOfAndSeverityType = getNumOfAndSeverityType;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReportCVEModel = exports.ReportLibraryModel = void 0;
4
+ class ReportLibraryModel {
5
+ constructor(name, cveArray) {
6
+ this.name = name;
7
+ this.cveArray = cveArray;
8
+ }
9
+ }
10
+ exports.ReportLibraryModel = ReportLibraryModel;
11
+ class ReportCVEModel {
12
+ constructor(name, description, severityCode, cvss3SeverityCode) {
13
+ this.name = name;
14
+ this.description = description;
15
+ this.severityCode = severityCode;
16
+ this.cvss3SeverityCode = cvss3SeverityCode;
17
+ }
18
+ }
19
+ exports.ReportCVEModel = ReportCVEModel;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReportCompositeKey = exports.ReportModelStructure = exports.ReportList = void 0;
4
+ class ReportList {
5
+ constructor() {
6
+ this.reportOutputList = [];
7
+ }
8
+ }
9
+ exports.ReportList = ReportList;
10
+ class ReportModelStructure {
11
+ constructor(compositeKey, cveArray) {
12
+ this.compositeKey = compositeKey;
13
+ this.cveArray = cveArray;
14
+ }
15
+ }
16
+ exports.ReportModelStructure = ReportModelStructure;
17
+ class ReportCompositeKey {
18
+ constructor(libraryName, libraryVersion, highestSeverity) {
19
+ this.libraryName = libraryName;
20
+ this.libraryVersion = libraryVersion;
21
+ this.highestSeverity = highestSeverity;
22
+ }
23
+ }
24
+ exports.ReportCompositeKey = ReportCompositeKey;