@contrast/contrast 1.0.0 → 1.0.3

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 (213) hide show
  1. package/.prettierignore +3 -0
  2. package/README.md +115 -78
  3. package/dist/audit/AnalysisEngine.js +37 -0
  4. package/dist/audit/catalogueApplication/catalogueApplication.js +36 -0
  5. package/dist/audit/dotnetAnalysisEngine/index.js +25 -0
  6. package/dist/audit/dotnetAnalysisEngine/parseLockFileContents.js +35 -0
  7. package/dist/audit/dotnetAnalysisEngine/parseProjectFileContents.js +15 -0
  8. package/dist/audit/dotnetAnalysisEngine/readLockFileContents.js +18 -0
  9. package/dist/audit/dotnetAnalysisEngine/readProjectFileContents.js +14 -0
  10. package/dist/audit/dotnetAnalysisEngine/sanitizer.js +9 -0
  11. package/dist/audit/goAnalysisEngine/index.js +17 -0
  12. package/dist/audit/goAnalysisEngine/parseProjectFileContents.js +164 -0
  13. package/dist/audit/goAnalysisEngine/readProjectFileContents.js +21 -0
  14. package/dist/audit/goAnalysisEngine/sanitizer.js +5 -0
  15. package/dist/audit/javaAnalysisEngine/index.js +34 -0
  16. package/dist/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +153 -0
  17. package/dist/audit/javaAnalysisEngine/parseProjectFileContents.js +353 -0
  18. package/dist/audit/javaAnalysisEngine/readProjectFileContents.js +98 -0
  19. package/dist/audit/javaAnalysisEngine/sanitizer.js +5 -0
  20. package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +24 -0
  21. package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +24 -0
  22. package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasLockFile.js +35 -0
  23. package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +23 -0
  24. package/dist/audit/languageAnalysisEngine/commonApi.js +18 -0
  25. package/dist/audit/languageAnalysisEngine/constants.js +20 -0
  26. package/dist/audit/languageAnalysisEngine/filterProjectPath.js +20 -0
  27. package/dist/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +25 -0
  28. package/dist/audit/languageAnalysisEngine/getProjectRootFilenames.js +39 -0
  29. package/dist/audit/languageAnalysisEngine/index.js +39 -0
  30. package/dist/audit/languageAnalysisEngine/langugageAnalysisFactory.js +95 -0
  31. package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +121 -0
  32. package/dist/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +17 -0
  33. package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +257 -0
  34. package/dist/audit/languageAnalysisEngine/report/newReportingFeature.js +81 -0
  35. package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +133 -0
  36. package/dist/audit/languageAnalysisEngine/sendSnapshot.js +41 -0
  37. package/dist/audit/languageAnalysisEngine/util/capabilities.js +11 -0
  38. package/dist/audit/languageAnalysisEngine/util/generalAPI.js +39 -0
  39. package/dist/audit/languageAnalysisEngine/util/requestUtils.js +14 -0
  40. package/dist/audit/nodeAnalysisEngine/handleNPMLockFileV2.js +40 -0
  41. package/dist/audit/nodeAnalysisEngine/index.js +31 -0
  42. package/dist/audit/nodeAnalysisEngine/parseNPMLockFileContents.js +18 -0
  43. package/dist/audit/nodeAnalysisEngine/parseYarn2LockFileContents.js +51 -0
  44. package/dist/audit/nodeAnalysisEngine/parseYarnLockFileContents.js +18 -0
  45. package/dist/audit/nodeAnalysisEngine/readNPMLockFileContents.js +17 -0
  46. package/dist/audit/nodeAnalysisEngine/readProjectFileContents.js +14 -0
  47. package/dist/audit/nodeAnalysisEngine/readYarnLockFileContents.js +24 -0
  48. package/dist/audit/nodeAnalysisEngine/sanitizer.js +9 -0
  49. package/dist/audit/phpAnalysisEngine/index.js +23 -0
  50. package/dist/audit/phpAnalysisEngine/parseLockFileContents.js +52 -0
  51. package/dist/audit/phpAnalysisEngine/readLockFileContents.js +13 -0
  52. package/dist/audit/phpAnalysisEngine/readProjectFileContents.js +16 -0
  53. package/dist/audit/phpAnalysisEngine/sanitizer.js +5 -0
  54. package/dist/audit/pythonAnalysisEngine/index.js +25 -0
  55. package/dist/audit/pythonAnalysisEngine/parsePipfileLockContents.js +17 -0
  56. package/dist/audit/pythonAnalysisEngine/parseProjectFileContents.js +21 -0
  57. package/dist/audit/pythonAnalysisEngine/readPipfileLockFileContents.js +13 -0
  58. package/dist/audit/pythonAnalysisEngine/readPythonProjectFileContents.js +14 -0
  59. package/dist/audit/pythonAnalysisEngine/sanitizer.js +7 -0
  60. package/dist/audit/rubyAnalysisEngine/index.js +25 -0
  61. package/dist/audit/rubyAnalysisEngine/parseGemfileLockContents.js +176 -0
  62. package/dist/audit/rubyAnalysisEngine/parsedGemfile.js +22 -0
  63. package/dist/audit/rubyAnalysisEngine/readGemfileContents.js +14 -0
  64. package/dist/audit/rubyAnalysisEngine/readGemfileLockContents.js +14 -0
  65. package/dist/audit/rubyAnalysisEngine/sanitizer.js +6 -0
  66. package/dist/commands/audit/auditConfig.js +25 -0
  67. package/dist/commands/audit/auditController.js +31 -0
  68. package/dist/commands/audit/help.js +52 -0
  69. package/dist/commands/audit/processAudit.js +18 -0
  70. package/dist/commands/audit/saveFile.js +11 -0
  71. package/dist/commands/auth/auth.js +20 -2
  72. package/dist/commands/config/config.js +19 -8
  73. package/dist/commands/scan/processScan.js +9 -13
  74. package/dist/common/HTTPClient.js +112 -13
  75. package/dist/common/errorHandling.js +65 -1
  76. package/dist/common/versionChecker.js +30 -0
  77. package/dist/constants/constants.js +4 -2
  78. package/dist/constants/lambda.js +32 -4
  79. package/dist/constants/locales.js +60 -21
  80. package/dist/constants.js +181 -21
  81. package/dist/index.js +50 -23
  82. package/dist/lambda/aws.js +14 -11
  83. package/dist/lambda/help.js +4 -0
  84. package/dist/lambda/lambda.js +50 -27
  85. package/dist/lambda/lambdaUtils.js +72 -0
  86. package/dist/lambda/logUtils.js +11 -1
  87. package/dist/lambda/scanDetailCompletion.js +4 -4
  88. package/dist/lambda/scanRequest.js +11 -5
  89. package/dist/lambda/utils.js +110 -53
  90. package/dist/sbom/generateSbom.js +20 -0
  91. package/dist/scan/autoDetection.js +0 -32
  92. package/dist/scan/fileUtils.js +1 -1
  93. package/dist/scan/help.js +14 -40
  94. package/dist/scan/populateProjectIdAndProjectName.js +5 -0
  95. package/dist/scan/saveResults.js +14 -0
  96. package/dist/scan/scan.js +105 -40
  97. package/dist/scan/scanConfig.js +39 -0
  98. package/dist/scan/scanController.js +19 -16
  99. package/dist/scan/scanResults.js +24 -16
  100. package/dist/utils/commonApi.js +3 -3
  101. package/dist/utils/paramsUtil/commandlineParams.js +1 -20
  102. package/dist/utils/paramsUtil/paramHandler.js +3 -6
  103. package/dist/utils/parsedCLIOptions.js +14 -8
  104. package/dist/utils/requestUtils.js +1 -1
  105. package/dist/utils/saveFile.js +19 -0
  106. package/package.json +26 -21
  107. package/src/audit/AnalysisEngine.js +103 -0
  108. package/src/audit/catalogueApplication/catalogueApplication.js +42 -0
  109. package/src/audit/dotnetAnalysisEngine/index.js +26 -0
  110. package/src/audit/dotnetAnalysisEngine/parseLockFileContents.js +47 -0
  111. package/src/audit/dotnetAnalysisEngine/parseProjectFileContents.js +29 -0
  112. package/src/audit/dotnetAnalysisEngine/readLockFileContents.js +30 -0
  113. package/src/audit/dotnetAnalysisEngine/readProjectFileContents.js +26 -0
  114. package/src/audit/dotnetAnalysisEngine/sanitizer.js +11 -0
  115. package/src/audit/goAnalysisEngine/index.js +18 -0
  116. package/src/audit/goAnalysisEngine/parseProjectFileContents.js +209 -0
  117. package/src/audit/goAnalysisEngine/readProjectFileContents.js +31 -0
  118. package/src/audit/goAnalysisEngine/sanitizer.js +7 -0
  119. package/src/audit/javaAnalysisEngine/index.js +41 -0
  120. package/src/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +222 -0
  121. package/src/audit/javaAnalysisEngine/parseProjectFileContents.js +420 -0
  122. package/src/audit/javaAnalysisEngine/readProjectFileContents.js +141 -0
  123. package/src/audit/javaAnalysisEngine/sanitizer.js +6 -0
  124. package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +35 -0
  125. package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +41 -0
  126. package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasLockFile.js +54 -0
  127. package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +32 -0
  128. package/src/audit/languageAnalysisEngine/commonApi.js +20 -0
  129. package/src/audit/languageAnalysisEngine/constants.js +23 -0
  130. package/src/audit/languageAnalysisEngine/filterProjectPath.js +21 -0
  131. package/src/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +41 -0
  132. package/src/audit/languageAnalysisEngine/getProjectRootFilenames.js +72 -0
  133. package/src/audit/languageAnalysisEngine/index.js +45 -0
  134. package/src/audit/languageAnalysisEngine/langugageAnalysisFactory.js +126 -0
  135. package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +177 -0
  136. package/src/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +27 -0
  137. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.js +303 -0
  138. package/src/audit/languageAnalysisEngine/report/newReportingFeature.js +124 -0
  139. package/src/audit/languageAnalysisEngine/report/reportingFeature.js +190 -0
  140. package/src/audit/languageAnalysisEngine/sendSnapshot.js +51 -0
  141. package/src/audit/languageAnalysisEngine/util/capabilities.js +12 -0
  142. package/src/audit/languageAnalysisEngine/util/generalAPI.js +43 -0
  143. package/src/audit/languageAnalysisEngine/util/requestUtils.js +17 -0
  144. package/src/audit/nodeAnalysisEngine/handleNPMLockFileV2.js +49 -0
  145. package/src/audit/nodeAnalysisEngine/index.js +35 -0
  146. package/src/audit/nodeAnalysisEngine/parseNPMLockFileContents.js +20 -0
  147. package/src/audit/nodeAnalysisEngine/parseYarn2LockFileContents.js +63 -0
  148. package/src/audit/nodeAnalysisEngine/parseYarnLockFileContents.js +26 -0
  149. package/src/audit/nodeAnalysisEngine/readNPMLockFileContents.js +23 -0
  150. package/src/audit/nodeAnalysisEngine/readProjectFileContents.js +27 -0
  151. package/src/audit/nodeAnalysisEngine/readYarnLockFileContents.js +36 -0
  152. package/src/audit/nodeAnalysisEngine/sanitizer.js +11 -0
  153. package/src/audit/phpAnalysisEngine/index.js +27 -0
  154. package/src/audit/phpAnalysisEngine/parseLockFileContents.js +60 -0
  155. package/src/audit/phpAnalysisEngine/readLockFileContents.js +14 -0
  156. package/src/audit/phpAnalysisEngine/readProjectFileContents.js +25 -0
  157. package/src/audit/phpAnalysisEngine/sanitizer.js +4 -0
  158. package/src/audit/pythonAnalysisEngine/index.js +55 -0
  159. package/src/audit/pythonAnalysisEngine/parsePipfileLockContents.js +23 -0
  160. package/src/audit/pythonAnalysisEngine/parseProjectFileContents.js +33 -0
  161. package/src/audit/pythonAnalysisEngine/readPipfileLockFileContents.js +16 -0
  162. package/src/audit/pythonAnalysisEngine/readPythonProjectFileContents.js +22 -0
  163. package/src/audit/pythonAnalysisEngine/sanitizer.js +9 -0
  164. package/src/audit/rubyAnalysisEngine/index.js +30 -0
  165. package/src/audit/rubyAnalysisEngine/parseGemfileLockContents.js +215 -0
  166. package/src/audit/rubyAnalysisEngine/parsedGemfile.js +39 -0
  167. package/src/audit/rubyAnalysisEngine/readGemfileContents.js +18 -0
  168. package/src/audit/rubyAnalysisEngine/readGemfileLockContents.js +17 -0
  169. package/src/audit/rubyAnalysisEngine/sanitizer.js +8 -0
  170. package/src/commands/audit/auditConfig.ts +30 -0
  171. package/src/commands/audit/auditController.ts +31 -0
  172. package/src/commands/audit/help.ts +48 -0
  173. package/src/commands/audit/processAudit.ts +18 -0
  174. package/src/commands/audit/saveFile.ts +6 -0
  175. package/src/commands/auth/auth.js +26 -2
  176. package/src/commands/config/config.js +22 -8
  177. package/src/commands/scan/processScan.js +9 -13
  178. package/src/common/HTTPClient.js +149 -14
  179. package/src/common/errorHandling.ts +85 -2
  180. package/src/common/versionChecker.ts +39 -0
  181. package/src/constants/constants.js +5 -4
  182. package/src/constants/lambda.js +45 -4
  183. package/src/constants/locales.js +76 -26
  184. package/src/constants.js +204 -23
  185. package/src/index.ts +67 -27
  186. package/src/lambda/aws.ts +13 -12
  187. package/src/lambda/help.ts +4 -0
  188. package/src/lambda/lambda.ts +53 -34
  189. package/src/lambda/lambdaUtils.ts +111 -0
  190. package/src/lambda/logUtils.ts +19 -1
  191. package/src/lambda/scanDetailCompletion.ts +4 -4
  192. package/src/lambda/scanRequest.ts +13 -11
  193. package/src/lambda/utils.ts +149 -81
  194. package/src/sbom/generateSbom.ts +17 -0
  195. package/src/scan/autoDetection.js +0 -29
  196. package/src/scan/fileUtils.js +1 -1
  197. package/src/scan/help.js +14 -45
  198. package/src/scan/populateProjectIdAndProjectName.js +5 -0
  199. package/src/scan/saveResults.js +14 -0
  200. package/src/scan/scan.js +127 -58
  201. package/src/scan/scanConfig.js +54 -0
  202. package/src/scan/scanController.js +22 -15
  203. package/src/scan/scanResults.js +32 -19
  204. package/src/utils/commonApi.js +2 -3
  205. package/src/utils/getConfig.ts +2 -0
  206. package/src/utils/paramsUtil/commandlineParams.js +1 -26
  207. package/src/utils/paramsUtil/paramHandler.js +3 -7
  208. package/src/utils/parsedCLIOptions.js +11 -9
  209. package/src/utils/requestUtils.js +1 -1
  210. package/src/utils/saveFile.js +19 -0
  211. package/dist/lambda/scanDetail.js +0 -30
  212. package/dist/scan/fileFinder.js +0 -15
  213. package/dist/utils/paramsUtil/yamlParams.js +0 -6
@@ -0,0 +1,3 @@
1
+ test/commands/**
2
+ dist/**
3
+ test/errorHandling.spec.ts
package/README.md CHANGED
@@ -1,13 +1,45 @@
1
- # Contrast Command Line Interface
1
+ # CodeSec by Contrast Security
2
2
 
3
- Install Contrast, authenticate, and then start running a Lambda scan.
4
- This version supports **Java** and **Python** functions on AWS.
3
+ CodeSec delivers:
5
4
 
6
- ## Requirements
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.
7
9
 
8
- - AWS credentials should be **available** on your local configure (usually `~/.aws/credentials`)
9
- - You have an option run lambda scan with your aws-profile to pass `--profile`
10
- - You also can export differnt credentials
10
+ ## Install
11
+
12
+ ```
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
+ ####Requirements
27
+ Make sure you have the correct file types to scan.
28
+
29
+ - Upload a .jar or .war file to scan a Java project for analysis
30
+ - Upload a .js or .zip file to scan a JavaScript project for analysis
31
+ - Upload a .exe. or .zip file to scan a .NET c# web forms project
32
+
33
+ Start scanning
34
+
35
+ Use the Contrast scan command `contrast scan`
36
+
37
+ ### Lambda function scan
38
+
39
+ ####Requirements
40
+
41
+ - Currently supports Java and Python functions on AWS.
42
+ Configure AWS credentials on your local environment by running the commands with your credentials:
11
43
 
12
44
  ```shell
13
45
  export AWS_DEFAULT_REGION=<YOUR_AWS_REGION>
@@ -15,95 +47,100 @@ export AWS_ACCESS_KEY_ID=<YOUR_ACCESS_KEY_ID>
15
47
  export AWS_SECRET_ACCESS_KEY=<YOUR_SECRET_ACCESS_KEY>
16
48
  ```
17
49
 
18
- These permissions are required to gather all required information on an AWS Lambda to use the `contrast lambda` command:
50
+ - 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.
19
51
 
20
- - 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)
21
- - 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)
52
+ - These permissions are required to gather all required information on an AWS Lambda to use the `contrast lambda` command:
22
53
 
23
- Policy example:
24
- ```
25
- {
26
- "Version": "2012-10-17",
27
- "Statement": [
28
- {
29
- "Sid": "VisualEditor0",
30
- "Effect": "Allow",
31
- "Action": [
32
- "iam:GetPolicyVersion",
33
- "iam:GetPolicy",
34
- "lambda:GetLayerVersion",
35
- "lambda:GetFunction",
36
- "iam:ListAttachedRolePolicies",
37
- "iam:ListRolePolicies",
38
- "iam:GetRolePolicy"
39
- ],
40
- "Resource": [
41
- "arn:aws:lambda:*:YOUR_ACCOUNT:layer:*:*",
42
- "arn:aws:lambda:*:YOUR_ACCOUNT:function:*",
43
- "arn:aws:iam::YOUR_ACCOUNT:role/*",
44
- "arn:aws:iam::YOUR_ACCOUNT:policy/*"
45
- ]
46
- }
47
- ]
48
- }
49
- ```
54
+ - 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)
55
+ - 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)
50
56
 
51
- ## Installation via Homebrew
57
+ ### Start scanning
52
58
 
53
- - `brew tap Contrast-Security-OSS/homebrew-contrast`
54
- - `brew install contrast`
59
+ Use contrast lambda to scan your AWS Lambda functions.
60
+ `contrast lambda --function-name MyFunctionName --region my-aws-region`
55
61
 
56
- ### Install NPM / YARN
62
+ ## Contrast commands
57
63
 
58
- - `npm i -g @contrast/contrast`
59
- - `yarn global add @contrast/contrast`
64
+ ### auth
60
65
 
61
- ### Install with binaries
66
+ Authenticate Contrast using your GitHub or Google account. A new browser window will open for login.
62
67
 
63
- - Go to [https://pkg.contrastsecurity.com/ui/repos/tree/General/cli](https://pkg.contrastsecurity.com/ui/repos/tree/General/cli)
64
- - Select your operating system and download the package
65
- - You must allow **execute permissions** on the file depending on your OS
68
+ **Usage:** `contrast auth`
66
69
 
67
- | Architecture | Link |
68
- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
69
- | 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) |
70
- | 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) |
71
- | 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) |
70
+ ### config
72
71
 
73
- ## Usage
72
+ Displays stored credentials.
74
73
 
75
- - `contrast [command] [option]`
76
- - `contrast lambda --function-name <function> [options]`
74
+ **Usage:** `contrast config`
77
75
 
78
- ## Running a scan on a Lambda function
76
+ **Options:**
79
77
 
80
- 1. `contrast auth`
81
- Authenticate by entering contrast auth in the terminal.
82
- In the resulting browser window, log in and authenticate with your GitHub or Google credentials.
83
- 2. `contrast lambda --function-name <YOUR_FUNCTION_NAME> --region <AWS_REGION>`
78
+ - **-c, --clear** - Removes stored credentials.
84
79
 
85
- More infromation
80
+ ### scan
86
81
 
87
- - `contrast lambda --help`
82
+ Performs a security SAST scan.
88
83
 
89
- ## Commands
84
+ **Usage:** `contrast scan [option]`
90
85
 
91
- - `auth` - Authenticate Contrast using your `Github` or `Google` account
92
- - `lambda` - Perform scan on AWS Lambda function
93
- - `version` - Displays version of Contrast CLI
94
- - `config` - Displays stored credentials (`–c, --clear` - Removes stored credentials)
95
- - `help` - Displays usage guide
86
+ **Options:**
96
87
 
97
- ## Example of Running
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**
98
90
 
99
- ```shell
100
- contrast lambda --function-name myFunctionName
101
- contrast lambda -f myFunctionName --region eu-cental-1
102
- contrast lambda -f myFunctionName --region eu-cental-1 --profile myDevProfile
103
- contrast lambda -f myFunctionName -v -j -r eu-cental-1 -p myDevProfile
104
- contrast lambda --function-name myFunctionName --verbose --json-output --region eu-cental-1 --profile myDevProfile
105
- ```
91
+ - **contrast scan --name**
92
+ Contrast project name. If not specified, Contrast creates a project from the name of the file
93
+ Alias: **–n**
94
+ - **contrast scan --save**
95
+ Download the results to a Static Analysis Results Interchange Format (SARIF) file.
96
+ Alias: **-s**
97
+
98
+ - **contrast scan --timeout**
99
+ Time in seconds to wait for the scan to complete. Default value is 300 seconds.
100
+ Alias: **-t**
101
+
102
+ ### lambda
103
+
104
+ Name of AWS lambda function to scan.
105
+
106
+ **Usage:** `contrast lambda --function-name`
107
+
108
+ **Options:**
109
+
110
+ - **contrast lambda --function-name --endpoint-url**
111
+ AWS Endpoint override. Similar to AWS CLI.
112
+ Alias: **-e**
113
+
114
+ - **contrast lambda --function-name --region**
115
+ Region override. Defaults to AWS_DEFAULT_REGION. Similar to AWS CLI.
116
+ Alias: **-r**
117
+
118
+ - **contrast lambda --function-name --profile**
119
+ AWS configuration profile override. Similar to AWS CLI.
120
+ Alias: **-p**
121
+
122
+ - **contrast lambda --function-name --json**
123
+ Return response in JSON (versus default human-readable format).
124
+ Alias: **-j**
125
+
126
+ - **contrast lambda -–function-name -–verbose**
127
+ Returns extended information to the terminal.
128
+ Alias: **-v**
129
+
130
+ - **contrast lambda -–function-name --list-functions**
131
+ Lists all available lambda functions to scan.
132
+
133
+ - **contrast lambda --function-name -–help**
134
+ Displays usage guide.
135
+ Alias: **-h**
136
+
137
+ ### help
138
+
139
+ Displays usage guide. To list detailed help for any CLI command, add the -h or --help flag to the command.
140
+ **Usage:** `contrast scan --help`
141
+ Alias: **-h**
106
142
 
107
- ## Example of Results
143
+ ### version
108
144
 
109
- ![image](https://user-images.githubusercontent.com/289035/165555050-e9a709c9-f2a9-4edc-a064-8208445238bc.png)
145
+ Displays version of Contrast CLI.
146
+ **Usage:** `contrast version` Alias: **-v**, **--version**
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ class AnalysisEngine {
3
+ constructor(initAnalysis = {}) {
4
+ this.analyzers = [];
5
+ this.analysis = { ...initAnalysis };
6
+ }
7
+ use(analyzer) {
8
+ if (Array.isArray(analyzer)) {
9
+ this.analyzers = [...this.analyzers, ...analyzer];
10
+ return;
11
+ }
12
+ this.analyzers.push(analyzer);
13
+ }
14
+ analyze(callback, config) {
15
+ let i = 0;
16
+ const next = err => {
17
+ if (err) {
18
+ return setImmediate(() => callback(err, this.analysis));
19
+ }
20
+ if (i >= this.analyzers.length) {
21
+ return setImmediate(() => callback(null, this.analysis));
22
+ }
23
+ const analyzer = this.analyzers[i];
24
+ i++;
25
+ setImmediate(() => {
26
+ try {
27
+ analyzer(this.analysis, next, config);
28
+ }
29
+ catch (uncaughtErr) {
30
+ next(uncaughtErr);
31
+ }
32
+ });
33
+ };
34
+ next();
35
+ }
36
+ }
37
+ module.exports = exports = AnalysisEngine;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ const i18n = require('i18n');
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');
14
+ };
15
+ const catalogueApplication = async (config) => {
16
+ const client = getHttpClient(config);
17
+ let appId;
18
+ await client
19
+ .catalogueCommand(config)
20
+ .then(res => {
21
+ if (res.statusCode === 201) {
22
+ displaySuccessMessage(config, res.body.application.app_id);
23
+ appId = res.body.application.app_id;
24
+ }
25
+ else {
26
+ handleResponseErrors(res, 'catalogue');
27
+ }
28
+ })
29
+ .catch(err => {
30
+ console.log(err);
31
+ });
32
+ return appId;
33
+ };
34
+ module.exports = {
35
+ catalogueApplication: catalogueApplication
36
+ };
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ const AnalysisEngine = require('../AnalysisEngine');
3
+ const readProjectFileContents = require('./readProjectFileContents');
4
+ const parseProjectFileContents = require('./parseProjectFileContents');
5
+ const readLockFileContents = require('./readLockFileContents');
6
+ const parseLockFileContents = require('./parseLockFileContents');
7
+ const sanitizer = require('./sanitizer');
8
+ const i18n = require('i18n');
9
+ module.exports = exports = (language, config, callback) => {
10
+ const ae = new AnalysisEngine({ language, config, dotnet: {} });
11
+ ae.use([
12
+ readProjectFileContents,
13
+ parseProjectFileContents,
14
+ readLockFileContents,
15
+ parseLockFileContents,
16
+ sanitizer
17
+ ]);
18
+ ae.analyze((err, analysis) => {
19
+ if (err) {
20
+ callback(new Error(i18n.__('dotnetAnalysisFailure') + err.message));
21
+ return;
22
+ }
23
+ callback(null, analysis);
24
+ });
25
+ };
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ const i18n = require('i18n');
3
+ module.exports = exports = ({ language: { lockFilePath }, dotnet }, next) => {
4
+ const { rawLockFileContents } = dotnet;
5
+ if (!rawLockFileContents) {
6
+ next();
7
+ return;
8
+ }
9
+ try {
10
+ let count = 0;
11
+ dotnet.lockFile = JSON.parse(rawLockFileContents);
12
+ for (const dependenciesNode in dotnet.lockFile.dependencies) {
13
+ for (const innerNode in dotnet.lockFile.dependencies[dependenciesNode]) {
14
+ const nodeValidation = JSON.stringify(dotnet.lockFile.dependencies[dependenciesNode][innerNode]);
15
+ if (nodeValidation.includes('"type":"Project"')) {
16
+ count += 1;
17
+ delete dotnet.lockFile.dependencies[dependenciesNode][innerNode];
18
+ dotnet.additionalInfo = 'dependenciesNote';
19
+ }
20
+ }
21
+ }
22
+ if (count > 0) {
23
+ const multiLevelProjectWarning = () => {
24
+ console.log('');
25
+ console.log(i18n.__('dependenciesNote'));
26
+ };
27
+ setTimeout(multiLevelProjectWarning, 7000);
28
+ }
29
+ }
30
+ catch (err) {
31
+ next(new Error(i18n.__('dotnetParseLockfile', lockFilePath) + `${err.message}`));
32
+ return;
33
+ }
34
+ next();
35
+ };
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ const xml2js = require('xml2js');
3
+ const i18n = require('i18n');
4
+ module.exports = exports = ({ language: { projectFilePath }, dotnet }, next) => {
5
+ const { rawProjectFileContents } = dotnet;
6
+ const parser = new xml2js.Parser({ explicitArray: false, mergeAttrs: true });
7
+ parser.parseString(rawProjectFileContents, (err, projectFileXML) => {
8
+ if (err) {
9
+ next(new Error(i18n.__('dotnetParseProjectFile', projectFilePath) + `${err}`));
10
+ return;
11
+ }
12
+ dotnet.projectFile = projectFileXML;
13
+ next();
14
+ });
15
+ };
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ const fs = require('fs');
3
+ const i18n = require('i18n');
4
+ module.exports = exports = (analysis, next) => {
5
+ const { language: { lockFilePath }, dotnet } = analysis;
6
+ if (!lockFilePath) {
7
+ next();
8
+ return;
9
+ }
10
+ try {
11
+ dotnet.rawLockFileContents = fs.readFileSync(lockFilePath);
12
+ }
13
+ catch (err) {
14
+ next(new Error(i18n.__('dotnetReadLockfile', lockFilePath) + `${err.message}`));
15
+ return;
16
+ }
17
+ next();
18
+ };
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ const fs = require('fs');
3
+ const i18n = require('i18n');
4
+ module.exports = exports = (analysis, next) => {
5
+ const { language: { projectFilePath }, dotnet } = analysis;
6
+ try {
7
+ dotnet.rawProjectFileContents = fs.readFileSync(projectFilePath);
8
+ }
9
+ catch (err) {
10
+ next(new Error(i18n.__('dotnetReadProjectFile', projectFilePath) + `${err.message}`));
11
+ return;
12
+ }
13
+ next();
14
+ };
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ module.exports = exports = ({ dotnet }, next) => {
3
+ delete dotnet.rawProjectFileContents;
4
+ delete dotnet.parsedProjectFileContents;
5
+ delete dotnet.projectFileXML;
6
+ delete dotnet.packageReferences;
7
+ delete dotnet.rawLockFileContents;
8
+ next();
9
+ };
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ const AnalysisEngine = require('../AnalysisEngine');
3
+ const readProjectFileContents = require('./readProjectFileContents');
4
+ const parseProjectFileContents = require('./parseProjectFileContents');
5
+ const sanitizer = require('./sanitizer');
6
+ const i18n = require('i18n');
7
+ module.exports = exports = (language, config, callback) => {
8
+ const ae = new AnalysisEngine({ language, config, go: {} });
9
+ ae.use([readProjectFileContents, parseProjectFileContents, sanitizer]);
10
+ ae.analyze((err, analysis) => {
11
+ if (err) {
12
+ callback(new Error(i18n.__('goAnalysisError') + `${err.message}`));
13
+ return;
14
+ }
15
+ callback(null, analysis);
16
+ });
17
+ };
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+ const i18n = require('i18n');
3
+ const crypto = require('crypto');
4
+ module.exports = exports = ({ go }, next) => {
5
+ const { modGraphOutput } = go;
6
+ try {
7
+ go.goDependencyTrees = parseGo(modGraphOutput);
8
+ }
9
+ catch (err) {
10
+ next(new Error(i18n.__('goParseProjectFile') + `${err.message}`));
11
+ return;
12
+ }
13
+ next();
14
+ };
15
+ const splitAllLinesIntoArray = modGraphOutput => {
16
+ return modGraphOutput.split(/\r\n|\r|\n/);
17
+ };
18
+ const parseGo = modGraphOutput => {
19
+ let splitLines = splitAllLinesIntoArray(modGraphOutput);
20
+ const directDepNames = getDirectDepNames(splitLines);
21
+ const uniqueTransitiveDepNames = getAllUniqueTransitiveDepNames(splitLines, directDepNames);
22
+ let rootNodes = createRootNodes(splitLines);
23
+ createTransitiveDeps(uniqueTransitiveDepNames, splitLines, rootNodes);
24
+ return rootNodes;
25
+ };
26
+ const getAllDepsOfADepAsEdge = (dep, deps) => {
27
+ let edges = {};
28
+ const depRows = deps.filter(line => {
29
+ return line.startsWith(dep);
30
+ });
31
+ depRows.forEach(dep => {
32
+ const edgeName = dep.split(' ')[1];
33
+ edges[edgeName] = edgeName;
34
+ });
35
+ return edges;
36
+ };
37
+ const getAllDepsOfADepAsName = (dep, deps) => {
38
+ let edges = [];
39
+ const depRows = deps.filter(line => {
40
+ return line.startsWith(dep);
41
+ });
42
+ depRows.forEach(dep => {
43
+ const edgeName = dep.split(' ')[1];
44
+ edges.push(edgeName);
45
+ });
46
+ return edges;
47
+ };
48
+ const createRootNodes = deps => {
49
+ let rootDep = {};
50
+ const rootDeps = getRootDeps(deps);
51
+ const edges = rootDeps.map(dep => {
52
+ return dep.split(' ')[1];
53
+ });
54
+ rootDep[rootDeps[0].split(' ')[0]] = {};
55
+ edges.forEach(edge => {
56
+ const splitEdge = edge.split('@');
57
+ const splitGroupName = splitEdge[0].split('/');
58
+ const name = splitGroupName.pop();
59
+ const lastSlash = splitEdge[0].lastIndexOf('/');
60
+ let group = splitEdge[0].substring(0, lastSlash);
61
+ const hash = getHash(splitEdge[0]);
62
+ group = checkGroupExists(group, name);
63
+ const edgesOfDep = getAllDepsOfADepAsEdge(edge, deps);
64
+ rootDep[rootDeps[0].split(' ')[0]][edge] = {
65
+ artifactID: name,
66
+ group: group,
67
+ version: splitEdge[1],
68
+ scope: '"compile',
69
+ type: 'direct',
70
+ hash: hash,
71
+ edges: edgesOfDep
72
+ };
73
+ });
74
+ return rootDep;
75
+ };
76
+ const getRootDeps = deps => {
77
+ const rootDeps = deps.filter(dep => {
78
+ const parentDep = dep.split(' ')[0];
79
+ if (parentDep.split('@v').length === 1) {
80
+ return dep;
81
+ }
82
+ });
83
+ return rootDeps;
84
+ };
85
+ const getHash = library => {
86
+ let shaSum = crypto.createHash('sha1');
87
+ shaSum.update(library);
88
+ return shaSum.digest('hex');
89
+ };
90
+ const getDirectDepNames = deps => {
91
+ const directDepNames = [];
92
+ deps.forEach(dep => {
93
+ const parentDep = dep.split(' ')[0];
94
+ if (parentDep.split('@v').length === 1) {
95
+ dep.split(' ')[1] !== undefined
96
+ ? directDepNames.push(dep.split(' ')[1])
97
+ : null;
98
+ }
99
+ });
100
+ return directDepNames;
101
+ };
102
+ const getAllUniqueTransitiveDepNames = (deps, directDepNames) => {
103
+ let uniqueDeps = [];
104
+ deps.forEach(dep => {
105
+ const parentDep = dep.split(' ')[0];
106
+ if (parentDep.split('@v').length !== 1) {
107
+ if (!directDepNames.includes(parentDep)) {
108
+ if (!uniqueDeps.includes(parentDep)) {
109
+ parentDep.length > 1 ? uniqueDeps.push(parentDep) : null;
110
+ }
111
+ }
112
+ }
113
+ });
114
+ return uniqueDeps;
115
+ };
116
+ const checkGroupExists = (group, name) => {
117
+ if (group === null || group === '') {
118
+ return name;
119
+ }
120
+ return group;
121
+ };
122
+ const createTransitiveDeps = (transitiveDeps, splitLines, rootNodes) => {
123
+ transitiveDeps.forEach(dep => {
124
+ const splitEdge = dep.split('@');
125
+ const splitGroupName = splitEdge[0].split('/');
126
+ const name = splitGroupName.pop();
127
+ const lastSlash = splitEdge[0].lastIndexOf('/');
128
+ let group = splitEdge[0].substring(0, lastSlash);
129
+ const hash = getHash(splitEdge[0]);
130
+ group = checkGroupExists(group, name);
131
+ const transitiveDep = {
132
+ artifactID: name,
133
+ group: group,
134
+ version: splitEdge[1],
135
+ scope: 'compile',
136
+ type: 'transitive',
137
+ hash: hash,
138
+ edges: {}
139
+ };
140
+ const edges = getAllDepsOfADepAsEdge(dep, splitLines);
141
+ transitiveDep.edges = edges;
142
+ const edgesAsName = getAllDepsOfADepAsName(dep, splitLines);
143
+ edgesAsName.forEach(dep => {
144
+ const splitEdge = dep.split('@');
145
+ const splitGroupName = splitEdge[0].split('/');
146
+ const name = splitGroupName.pop();
147
+ const lastSlash = splitEdge[0].lastIndexOf('/');
148
+ let group = splitEdge[0].substring(0, lastSlash);
149
+ const hash = getHash(splitEdge[0]);
150
+ group = checkGroupExists(group, name);
151
+ const transitiveDep = {
152
+ artifactID: name,
153
+ group: group,
154
+ version: splitEdge[1],
155
+ scope: 'compile',
156
+ type: 'transitive',
157
+ hash: hash,
158
+ edges: {}
159
+ };
160
+ rootNodes[Object.keys(rootNodes)[0]][dep] = transitiveDep;
161
+ });
162
+ rootNodes[Object.keys(rootNodes)[0]][dep] = transitiveDep;
163
+ });
164
+ };
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ const child_process = require('child_process');
3
+ const i18n = require('i18n');
4
+ module.exports = exports = async ({ language: { projectFilePath }, go }, next) => {
5
+ let cmdStdout;
6
+ let cwd;
7
+ try {
8
+ cwd = projectFilePath.replace('go.mod', '');
9
+ cmdStdout = child_process.execSync('go mod graph', { cwd });
10
+ go.modGraphOutput = cmdStdout.toString();
11
+ next();
12
+ }
13
+ catch (err) {
14
+ if (err.message === 'spawnSync /bin/sh ENOENT') {
15
+ err.message =
16
+ '\n\n*************** No transitive dependencies ***************\n\nWe are unable to build a dependency tree view from your repository as there were no transitive dependencies found.';
17
+ }
18
+ next(new Error(i18n.__('goReadProjectFile', cwd, `${err.message ? err.message : ''}`)));
19
+ return;
20
+ }
21
+ };
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ module.exports = exports = ({ go }, next) => {
3
+ delete go.modGraphOutput;
4
+ next();
5
+ };