@contrast/contrast 1.0.1 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/.prettierignore +2 -0
  2. package/README.md +103 -133
  3. package/dist/audit/languageAnalysisEngine/{langugageAnalysisFactory.js → languageAnalysisFactory.js} +26 -11
  4. package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +62 -234
  5. package/dist/audit/languageAnalysisEngine/report/models/reportLibraryModel.js +19 -0
  6. package/dist/audit/languageAnalysisEngine/report/models/reportListModel.js +24 -0
  7. package/dist/audit/languageAnalysisEngine/report/models/reportSeverityModel.js +10 -0
  8. package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +24 -129
  9. package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +85 -0
  10. package/dist/audit/languageAnalysisEngine/sendSnapshot.js +3 -1
  11. package/dist/commands/audit/auditController.js +6 -3
  12. package/dist/commands/audit/saveFile.js +11 -0
  13. package/dist/commands/auth/auth.js +19 -1
  14. package/dist/commands/config/config.js +19 -8
  15. package/dist/commands/scan/processScan.js +8 -25
  16. package/dist/common/HTTPClient.js +30 -26
  17. package/dist/common/errorHandling.js +17 -1
  18. package/dist/common/versionChecker.js +32 -0
  19. package/dist/constants/constants.js +4 -2
  20. package/dist/constants/lambda.js +3 -1
  21. package/dist/constants/locales.js +41 -18
  22. package/dist/constants.js +39 -3
  23. package/dist/index.js +49 -28
  24. package/dist/lambda/help.js +22 -14
  25. package/dist/lambda/lambda.js +6 -0
  26. package/dist/sbom/generateSbom.js +20 -0
  27. package/dist/scan/help.js +4 -2
  28. package/dist/scan/models/groupedResultsModel.js +10 -0
  29. package/dist/scan/models/resultContentModel.js +2 -0
  30. package/dist/scan/models/scanResultsModel.js +11 -0
  31. package/dist/scan/populateProjectIdAndProjectName.js +1 -0
  32. package/dist/scan/saveResults.js +9 -10
  33. package/dist/scan/scan.js +99 -74
  34. package/dist/scan/scanConfig.js +20 -1
  35. package/dist/scan/scanController.js +7 -2
  36. package/dist/scan/scanResults.js +6 -0
  37. package/dist/utils/getConfig.js +3 -0
  38. package/dist/utils/paramsUtil/commandlineParams.js +1 -1
  39. package/dist/utils/requestUtils.js +1 -1
  40. package/dist/utils/saveFile.js +19 -0
  41. package/package.json +2 -2
  42. package/src/audit/languageAnalysisEngine/{langugageAnalysisFactory.js → languageAnalysisFactory.js} +33 -15
  43. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +127 -0
  44. package/src/audit/languageAnalysisEngine/report/models/reportLibraryModel.ts +30 -0
  45. package/src/audit/languageAnalysisEngine/report/models/reportListModel.ts +32 -0
  46. package/src/audit/languageAnalysisEngine/report/models/reportSeverityModel.ts +9 -0
  47. package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +56 -0
  48. package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +110 -0
  49. package/src/audit/languageAnalysisEngine/sendSnapshot.js +3 -1
  50. package/src/commands/audit/auditController.ts +12 -3
  51. package/src/commands/audit/processAudit.ts +0 -1
  52. package/src/commands/audit/saveFile.ts +6 -0
  53. package/src/commands/auth/auth.js +25 -1
  54. package/src/commands/config/config.js +22 -8
  55. package/src/commands/scan/processScan.js +8 -29
  56. package/src/common/HTTPClient.js +42 -36
  57. package/src/common/errorHandling.ts +29 -2
  58. package/src/common/versionChecker.ts +41 -0
  59. package/src/constants/constants.js +5 -4
  60. package/src/constants/lambda.js +3 -1
  61. package/src/constants/locales.js +51 -19
  62. package/src/constants.js +44 -3
  63. package/src/index.ts +63 -31
  64. package/src/lambda/help.ts +22 -14
  65. package/src/lambda/lambda.ts +8 -0
  66. package/src/sbom/generateSbom.ts +17 -0
  67. package/src/scan/help.js +4 -2
  68. package/src/scan/models/groupedResultsModel.ts +18 -0
  69. package/src/scan/models/resultContentModel.ts +86 -0
  70. package/src/scan/models/scanResultsModel.ts +52 -0
  71. package/src/scan/populateProjectIdAndProjectName.js +1 -0
  72. package/src/scan/saveResults.js +8 -9
  73. package/src/scan/scan.ts +192 -0
  74. package/src/scan/scanConfig.js +26 -1
  75. package/src/scan/scanController.js +11 -2
  76. package/src/scan/scanResults.js +11 -0
  77. package/src/utils/getConfig.ts +12 -0
  78. package/src/utils/paramsUtil/commandlineParams.js +1 -1
  79. package/src/utils/requestUtils.js +1 -1
  80. package/src/utils/saveFile.js +19 -0
  81. package/dist/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +0 -17
  82. package/dist/audit/languageAnalysisEngine/report/newReportingFeature.js +0 -81
  83. package/dist/common/findLatestCLIVersion.js +0 -23
  84. package/dist/lambda/scanDetail.js +0 -30
  85. package/dist/scan/fileFinder.js +0 -15
  86. package/dist/utils/fileUtils.js +0 -31
  87. package/dist/utils/paramsUtil/genericCommandLineParams.js +0 -12
  88. package/dist/utils/paramsUtil/yamlParams.js +0 -6
  89. package/src/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +0 -27
  90. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.js +0 -303
  91. package/src/audit/languageAnalysisEngine/report/newReportingFeature.js +0 -124
  92. package/src/audit/languageAnalysisEngine/report/reportingFeature.js +0 -190
  93. package/src/common/findLatestCLIVersion.ts +0 -27
  94. package/src/scan/scan.js +0 -162
package/.prettierignore CHANGED
@@ -1,2 +1,4 @@
1
1
  test/commands/**
2
2
  dist/**
3
+ test/errorHandling.spec.ts
4
+ **/models
package/README.md CHANGED
@@ -1,33 +1,46 @@
1
- # Contrast Command Line Interface
1
+ # CodeSec by Contrast Security
2
2
 
3
- - [About Contrast CLI](#about-contrast-cli)
4
- - [Requirements](#requirements)
5
- - [Step 1 – Install](#step-1--install)
6
- - [Installation via Homebrew](#installation-via-homebrew)
7
- - [Install NPM / YARN](#install-npm--yarn)
8
- - [Install with binaries](#install-with-binaries)
9
- - [Step 2 – Authenticate](#step-2--authenticate)
10
- - [Step 3 – Scan](#step-3--scan)
11
- - [Usage](#usage)
12
- - [Commands](#commands)
13
- - [Examples of usage](#examples-of-usage)
14
- - [Example of Results](#example-of-results)
15
- - [Dependencies Vulnerabilities](#dependencies-vulnerabilities)
16
- - [Least Privilege](#least-privilege)
3
+ CodeSec delivers:
17
4
 
18
- ## About Contrast CLI
5
+ - The fastest and most accurate SAST scanner.
6
+ - Immediate and actionable results — scan code and serverless environments.
7
+ - A frictionless and seamless sign-in process with GitHub or Google Account. From start to finish in minutes.
8
+ - By running a scan on your lambda functions, you can find: Least privilege identity and access management (IAM) vulnerabilities (over permissive policies) and remediation.
19
9
 
20
- Contrast CLI helps you find & fix security issues on AWS lambda functions (supports **Java** and **Python**)
21
- By running a scan on your lambda functions, you can find:
10
+ ## Install
22
11
 
23
- - Least privilege identity and access management (IAM) vulnerabilities (over permissive policies) and remediation
24
- - The Common Vulnerabilities and Exposures (CVE) from your libraries (Vulnerable Dependencies) and remediation
12
+ ```shell
13
+ npm install -g @contrast/contrast
14
+ ```
15
+
16
+ ## Authenticate
17
+
18
+ Authenticate by entering contrast auth in the terminal.
19
+
20
+ In the resulting browser window, log in and authenticate with your GitHub or Google credentials.
21
+
22
+ ## Run a scan
23
+
24
+ ### SAST scan
25
+
26
+ #### Scan Requirements
27
+
28
+ Make sure you have the correct file types to scan.
25
29
 
26
- ## Requirements
30
+ - Upload a .jar or .war file to scan a Java project for analysis
31
+ - Upload a .js or .zip file to scan a JavaScript project for analysis
32
+ - Upload a .exe. or .zip file to scan a .NET c# web forms project
27
33
 
28
- - AWS credentials should be **available** on your local configure (usually `~/.aws/credentials`)
29
- - You have an option run lambda scan with your aws-profile to pass `--profile`
30
- - You also can export different credentials
34
+ Start scanning
35
+
36
+ Use the Contrast scan command `contrast scan`
37
+
38
+ ### Lambda function scan
39
+
40
+ #### Lambda Requirements
41
+
42
+ - Currently supports Java and Python functions on AWS.
43
+ Configure AWS credentials on your local environment by running the commands with your credentials:
31
44
 
32
45
  ```shell
33
46
  export AWS_DEFAULT_REGION=<YOUR_AWS_REGION>
@@ -35,148 +48,105 @@ export AWS_ACCESS_KEY_ID=<YOUR_ACCESS_KEY_ID>
35
48
  export AWS_SECRET_ACCESS_KEY=<YOUR_SECRET_ACCESS_KEY>
36
49
  ```
37
50
 
38
- These permissions are required to gather all required information on an AWS Lambda to use the `contrast lambda` command:
39
-
40
- - Lambda: [GetFunction](https://docs.aws.amazon.com/lambda/latest/dg/API_GetFunction.html) | [GetLayerVersion](https://docs.aws.amazon.com/lambda/latest/dg/API_GetLayerVersion.html)
41
- - IAM: [GetRolePolicy](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetRolePolicy.html) | [GetPolicy](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicy.html) | [GetPolicyVersion](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicyVersion.html) | [ListRolePolicies](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListRolePolicies.html) | [ListAttachedRolePolicies](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAttachedRolePolicies.html)
42
-
43
- Policy example:
44
-
45
- ```json
46
- {
47
- "Version": "2012-10-17",
48
- "Statement": [
49
- {
50
- "Sid": "VisualEditor0",
51
- "Effect": "Allow",
52
- "Action": [
53
- "iam:GetPolicyVersion",
54
- "iam:GetPolicy",
55
- "lambda:GetLayerVersion",
56
- "lambda:GetFunction",
57
- "iam:ListAttachedRolePolicies",
58
- "iam:ListRolePolicies",
59
- "iam:GetRolePolicy"
60
- ],
61
- "Resource": [
62
- "arn:aws:lambda:*:YOUR_ACCOUNT:layer:*:*",
63
- "arn:aws:lambda:*:YOUR_ACCOUNT:function:*",
64
- "arn:aws:iam::YOUR_ACCOUNT:role/*",
65
- "arn:aws:iam::YOUR_ACCOUNT:policy/*"
66
- ]
67
- }
68
- ]
69
- }
70
- ```
51
+ - AWS credentials should be available on your local configure (usually **~/.aws/credentials**). You have an option to run a lambda scan with your aws-profile to pass --profile. You also can export different credentials.
71
52
 
72
- ## Step 1 Install
53
+ - These permissions are required to gather all required information on an AWS Lambda to use the `contrast lambda` command:
73
54
 
74
- ### Installation via Homebrew
55
+ - Lambda: [GetFunction](https://docs.aws.amazon.com/lambda/latest/dg/API_GetFunction.html) | [GetLayerVersion](https://docs.aws.amazon.com/lambda/latest/dg/API_GetLayerVersion.html)
56
+ - IAM: [GetRolePolicy](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetRolePolicy.html) | [GetPolicy](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicy.html) | [GetPolicyVersion](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicyVersion.html) | [ListRolePolicies](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListRolePolicies.html) | [ListAttachedRolePolicies](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAttachedRolePolicies.html)
75
57
 
76
- - `brew tap Contrast-Security-OSS/homebrew-contrast`
77
- - `brew install contrast`
58
+ ### Start scanning
78
59
 
79
- ### Install NPM / YARN
60
+ Use contrast lambda to scan your AWS Lambda functions.
61
+ `contrast lambda --function-name MyFunctionName --region my-aws-region`
80
62
 
81
- - `npm install -g @contrast/contrast`
82
- - `yarn global add @contrast/contrast`
63
+ ## Contrast commands
83
64
 
84
- ### Install with binaries
65
+ ### auth
85
66
 
86
- - Go to [https://pkg.contrastsecurity.com/ui/repos/tree/General/cli](https://pkg.contrastsecurity.com/ui/repos/tree/General/cli)
87
- - Select your operating system and download the package
88
- - You must allow **execute permissions** on the file depending on your OS
67
+ Authenticate Contrast using your GitHub or Google account. A new browser window will open for login.
89
68
 
90
- | Architecture | Link |
91
- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
92
- | macOS | [https://pkg.contrastsecurity.com/ui/repos/tree/General/cli/1.0.0/mac/contrast](https://pkg.contrastsecurity.com/ui/repos/tree/General/cli/1.0.0/mac/contrast) |
93
- | Linux | [https://pkg.contrastsecurity.com/ui/repos/tree/General/cli/1.0.0/linux/contrast](https://pkg.contrastsecurity.com/ui/repos/tree/General/cli/1.0.0/linux/contrast) |
94
- | Windows | [https://pkg.contrastsecurity.com/ui/repos/tree/General/cli/1.0.0/windows/contrast.exe](https://pkg.contrastsecurity.com/ui/repos/tree/General/cli/1.0.0/windows/contrast.exe) |
69
+ **Usage:** `contrast auth`
95
70
 
96
- ## Step 2 – Authenticate
71
+ ### config
97
72
 
98
- Authenticate using your existing [GitHub](https://github.com/) or [Google](https://www.google.com/) account.
73
+ Displays stored credentials.
99
74
 
100
- ```shell
101
- contrast auth
102
- ```
75
+ **Usage:** `contrast config`
103
76
 
104
- ## Step 3 – Scan
77
+ **Options:**
105
78
 
106
- Use contrast lambda to scan your AWS Lambda functions:
79
+ - **-c, --clear** - Removes stored credentials.
107
80
 
108
- ```shell
109
- contrast lambda --function-name MyFunctionName --region my-aws-region
110
- ```
81
+ ### scan
111
82
 
112
- ### Usage
83
+ Performs a security SAST scan.
113
84
 
114
- - `contrast [command] [option]`
115
- - `contrast lambda --list-functions`
116
- - `contrast lambda --function-name <function> [options]`
117
- - `contrast lambda --help`
85
+ **Usage:** `contrast scan [option]`
118
86
 
119
- ### Commands
87
+ **Options:**
120
88
 
121
- - `auth` - Authenticate Contrast using your `Github` or `Google` account
122
- - `lambda` - Perform scan on AWS Lambda function
123
- - `--function-name` - Name of AWS lambda function to scan
124
- - `--list-functions` - List all available lambda functions to scan
125
- - `--endpoint-url` (optional) - AWS Endpoint override, works like in AWS CLI
126
- - `--region` (optional) - Region override, default to AWS_DEAFAULT_REGION env var, works like in AWS CLI
127
- - `--profile` (optional) - AWS configuration profile override, works like in AWS CLI
128
- - `--json-output` (optional) - Return response in JSON (versus default human readable format)
129
- - `--verbose` (optional) - Returns extended information to the terminal
130
- - `--help` Displays usage guide
131
- - `version` - Displays version of Contrast CLI
132
- - `config` - Displays stored credentials
133
- - `config --clear` - Removes stored credentials
134
- - `help` - Displays usage guide
89
+ - **contrast scan --file**
135
90
 
136
- ### Examples of usage
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**
137
93
 
138
- show help for lambda
94
+ - **contrast scan --name**
139
95
 
140
- ```shell
141
- contrast lambda --help
142
- ```
96
+ - Contrast project name. If not specified, Contrast uses contrast.settings to identify the project or creates a project.
97
+ - Alias: **–n**
143
98
 
144
- get list of all available functions for scan
99
+ - **contrast scan --save**
145
100
 
146
- ```shell
147
- contrast lambda --list-functions
148
- ```
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**
149
103
 
150
- scan lambda function in specific region
104
+ - **contrast scan --timeout**
105
+ - Time in seconds to wait for the scan to complete. Default value is 300 seconds.
106
+ - Alias: **-t**
151
107
 
152
- ```shell
153
- contrast lambda -f myFunctionName --region eu-cental-1
154
- ```
108
+ ### lambda
155
109
 
156
- scan lambda function with different profile
110
+ Name of AWS lambda function to scan.
157
111
 
158
- ```shell
159
- contrast lambda -f myFunctionName --profile myDevProfile
160
- ```
112
+ **Usage:** `contrast lambda --function-name`
161
113
 
162
- scan lambda function with full details in json format
114
+ **Options:**
163
115
 
164
- ```shell
165
- contrast lambda -f myFunctionName --json-output
166
- ```
116
+ - **contrast lambda --list-functions**
117
+ Lists all available lambda functions to scan.
167
118
 
168
- scan lambda function with all possible flags
119
+ - **contrast lambda --function-name --endpoint-url**
120
+ AWS Endpoint override. Similar to AWS CLI.
121
+ Alias: **-e**
169
122
 
170
- ```shell
171
- contrast lambda -f myFunctionName --region eu-cental-1 --profile myDevProfile --endpoint-url https://adbb-94-188-169-138.eu.ngrok.io/ --verbose --json-output
172
- ```
123
+ - **contrast lambda --function-name --region**
124
+ Region override. Defaults to AWS_DEFAULT_REGION. Similar to AWS CLI.
125
+ Alias: **-r**
126
+
127
+ - **contrast lambda --function-name --profile**
128
+ AWS configuration profile override. Similar to AWS CLI.
129
+ Alias: **-p**
130
+
131
+ - **contrast lambda --function-name --json**
132
+ Return response in JSON (versus default human-readable format).
133
+ Alias: **-j**
134
+
135
+ - **contrast lambda -–function-name -–verbose**
136
+ Returns extended information to the terminal.
137
+ Alias: **-v**
173
138
 
174
- ## Example of Results
139
+ - **contrast lambda --function-name -–help**
140
+ Displays usage guide.
141
+ Alias: **-h**
175
142
 
176
- ### Dependency vulnerabilities
143
+ ### help
177
144
 
178
- ![image](https://user-images.githubusercontent.com/289035/166472066-fa4a179c-cbef-436f-bc8e-9cbb8a4b465e.png)
145
+ Displays usage guide. To list detailed help for any CLI command, add the -h or --help flag to the command.
146
+ **Usage:** `contrast scan --help`
147
+ Alias: **-h**
179
148
 
180
- ### Least Privilege
149
+ ### version
181
150
 
182
- ![image](https://user-images.githubusercontent.com/289035/166480331-54ec133f-3379-4023-9fe4-c0db352c5b16.png)
151
+ Displays version of Contrast CLI.
152
+ **Usage:** `contrast version` Alias: **-v**, **--version**
@@ -9,9 +9,11 @@ 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');
13
+ const fs = require('fs');
14
+ const chalk = require('chalk');
15
+ const saveFile = require('../../commands/audit/saveFile').default;
16
+ const generateSbom = require('../../sbom/generateSbom').default;
15
17
  module.exports = exports = (err, analysis) => {
16
18
  const { identifiedLanguageInfo } = analysis.languageAnalysis;
17
19
  const catalogueAppId = analysis.languageAnalysis.appId;
@@ -35,15 +37,8 @@ module.exports = exports = (err, analysis) => {
35
37
  }
36
38
  console.log('\n **************CONTRAST OSS ANALYSIS BEGINS**************');
37
39
  const snapshotResponse = await newSendSnapShot(analysis, catalogueAppId);
38
- if (config.report) {
39
- const ignoreDevUrl = await checkDevDeps(config);
40
- if (ignoreDevUrl) {
41
- await vulnReportWithoutDevDep(analysis, catalogueAppId, snapshotResponse.id, config);
42
- }
43
- else {
44
- await vulnerabilityReport(analysis, catalogueAppId, config);
45
- }
46
- }
40
+ await vulnerabilityReport(analysis, catalogueAppId, snapshotResponse.id);
41
+ await auditSave(config);
47
42
  console.log('\n ***************CONTRAST OSS ANALYSIS COMPLETE************** \n');
48
43
  };
49
44
  if (identifiedLanguageInfo.language === DOTNET) {
@@ -68,3 +63,23 @@ module.exports = exports = (err, analysis) => {
68
63
  goAE(identifiedLanguageInfo, analysis.config, langCallback);
69
64
  }
70
65
  };
66
+ async function auditSave(config) {
67
+ if (config.save) {
68
+ if (config.save.toLowerCase() === 'sbom') {
69
+ saveFile(config, await generateSbom(config));
70
+ const filename = `${config.applicationId}-sbom-cyclonedx.json`;
71
+ if (fs.existsSync(filename)) {
72
+ console.log(i18n.__('auditSBOMSaveSuccess') + ` - ${filename}`);
73
+ }
74
+ else {
75
+ console.log(chalk.yellow.bold(`\n Unable to save ${filename} Software Bill of Materials (SBOM)`));
76
+ }
77
+ }
78
+ else {
79
+ console.log(i18n.__('auditBadFiletypeSpecifiedForSave'));
80
+ }
81
+ }
82
+ else if (config.save === null) {
83
+ console.log(i18n.__('auditNoFiletypeSpecifiedForSave'));
84
+ }
85
+ }
@@ -1,257 +1,85 @@
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;
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
75
4
  };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.printFormattedOutput = exports.printVulnerabilityResponse = exports.getReport = exports.createLibraryHeader = void 0;
7
+ const i18n_1 = __importDefault(require("i18n"));
8
+ const commonApi_1 = require("../../../utils/commonApi");
9
+ const reportListModel_1 = require("./models/reportListModel");
10
+ const lodash_1 = require("lodash");
11
+ const chalk_1 = __importDefault(require("chalk"));
12
+ const reportUtils_1 = require("./utils/reportUtils");
13
+ const oraWrapper_1 = require("../../../utils/oraWrapper");
76
14
  const createLibraryHeader = (id, numberOfVulnerableLibraries, numberOfCves, name) => {
77
15
  name
78
- ? console.log(` Application Name: ${name} | Application ID: ${id}`)
16
+ ? console.log(`\n Application Name: ${name} | Application ID: ${id}`)
79
17
  : 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;
102
- };
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
- }
18
+ 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
+ '************************** ');
143
25
  };
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);
26
+ exports.createLibraryHeader = createLibraryHeader;
27
+ const getReport = async (config, reportId) => {
28
+ 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);
149
32
  return client
150
- .getReport(userParams)
151
- .then(res => {
33
+ .getReportById(config, reportId)
34
+ .then((res) => {
152
35
  if (res.statusCode === 200) {
153
- displaySuccessMessageReport();
36
+ (0, oraWrapper_1.succeedSpinner)(reportSpinner, i18n_1.default.__('auditReportSuccessMessage'));
154
37
  return res.body;
155
38
  }
156
39
  else {
157
- handleResponseErrors(res, 'report');
40
+ (0, oraWrapper_1.failSpinner)(reportSpinner, i18n_1.default.__('auditReportFail'));
41
+ console.log('config-------------------');
42
+ console.log(config);
43
+ console.log('reportId----------------');
44
+ console.log(reportId);
45
+ console.log(JSON.stringify(res));
46
+ (0, commonApi_1.handleResponseErrors)(res, 'report');
158
47
  }
159
48
  })
160
- .catch(err => {
49
+ .catch((err) => {
161
50
  console.log(err);
162
51
  });
163
52
  };
164
- const printVulnerabilityResponse = (severity, filteredVulns, vulnerabilities) => {
53
+ exports.getReport = getReport;
54
+ const printVulnerabilityResponse = (vulnerabilities, config) => {
165
55
  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;
56
+ (0, exports.printFormattedOutput)(vulnerabilities, config);
57
+ if (Object.keys(vulnerabilities).length > 0) {
58
+ hasSomeVulnerabilitiesReported = true;
175
59
  }
176
60
  return hasSomeVulnerabilitiesReported;
177
61
  };
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
- });
194
- }
195
- };
196
- function searchHighCVEs(vuln) {
197
- let sevCode = vuln.severityCode || vuln.severity_code;
198
- if (sevCode === 'HIGH') {
199
- return vuln;
200
- }
201
- }
202
- function searchMediumCVEs(vuln) {
203
- let sevCode = vuln.severityCode || vuln.severity_code;
204
- if (sevCode === 'HIGH' || sevCode === 'MEDIUM') {
205
- return vuln;
62
+ exports.printVulnerabilityResponse = printVulnerabilityResponse;
63
+ const printFormattedOutput = (libraries, config) => {
64
+ const report = new reportListModel_1.ReportList();
65
+ for (const library of libraries) {
66
+ const { name, version } = (0, reportUtils_1.findNameAndVersion)(library, config);
67
+ const newOutputModel = new reportListModel_1.ReportModelStructure(new reportListModel_1.ReportCompositeKey(name, version, (0, reportUtils_1.findHighestSeverityCVE)(library.cveArray)), library.cveArray);
68
+ report.reportOutputList.push(newOutputModel);
206
69
  }
207
- }
208
- function searchLowCVEs(vuln) {
209
- let sevCode = vuln.severityCode || vuln.severity_code;
210
- if (sevCode === 'HIGH' || sevCode === 'MEDIUM' || sevCode === 'LOW') {
211
- return vuln;
70
+ const orderedOutputList = (0, lodash_1.orderBy)(report.reportOutputList, reportListItem => reportListItem.compositeKey.highestSeverity.priority);
71
+ for (const reportModel of orderedOutputList) {
72
+ const name = reportModel.compositeKey.libraryName;
73
+ const version = reportModel.compositeKey.libraryVersion;
74
+ const highestSeverity = reportModel.compositeKey.highestSeverity.severity;
75
+ const numOfCVEs = reportModel.cveArray.length;
76
+ const cveNames = [];
77
+ reportModel.cveArray.forEach(cve => cveNames.push(cve.name));
78
+ const boldHeader = chalk_1.default.bold(`${highestSeverity} | Vulnerable Library`);
79
+ const cvePluralised = numOfCVEs > 1 ? 'CVEs' : 'CVE';
80
+ console.log(`\n ${boldHeader} ${name} (${version}) has ${numOfCVEs} known ${cvePluralised}`);
81
+ console.log(` ${cveNames.join(', ')}`);
82
+ console.log(chalk_1.default.bold(' How to fix: Update to latest version'));
212
83
  }
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
- }
237
- }
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
84
  };
85
+ exports.printFormattedOutput = printFormattedOutput;