@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.
- package/.prettierignore +3 -0
- package/README.md +115 -78
- package/dist/audit/AnalysisEngine.js +37 -0
- package/dist/audit/catalogueApplication/catalogueApplication.js +36 -0
- package/dist/audit/dotnetAnalysisEngine/index.js +25 -0
- package/dist/audit/dotnetAnalysisEngine/parseLockFileContents.js +35 -0
- package/dist/audit/dotnetAnalysisEngine/parseProjectFileContents.js +15 -0
- package/dist/audit/dotnetAnalysisEngine/readLockFileContents.js +18 -0
- package/dist/audit/dotnetAnalysisEngine/readProjectFileContents.js +14 -0
- package/dist/audit/dotnetAnalysisEngine/sanitizer.js +9 -0
- package/dist/audit/goAnalysisEngine/index.js +17 -0
- package/dist/audit/goAnalysisEngine/parseProjectFileContents.js +164 -0
- package/dist/audit/goAnalysisEngine/readProjectFileContents.js +21 -0
- package/dist/audit/goAnalysisEngine/sanitizer.js +5 -0
- package/dist/audit/javaAnalysisEngine/index.js +34 -0
- package/dist/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +153 -0
- package/dist/audit/javaAnalysisEngine/parseProjectFileContents.js +353 -0
- package/dist/audit/javaAnalysisEngine/readProjectFileContents.js +98 -0
- package/dist/audit/javaAnalysisEngine/sanitizer.js +5 -0
- package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +24 -0
- package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +24 -0
- package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasLockFile.js +35 -0
- package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +23 -0
- package/dist/audit/languageAnalysisEngine/commonApi.js +18 -0
- package/dist/audit/languageAnalysisEngine/constants.js +20 -0
- package/dist/audit/languageAnalysisEngine/filterProjectPath.js +20 -0
- package/dist/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +25 -0
- package/dist/audit/languageAnalysisEngine/getProjectRootFilenames.js +39 -0
- package/dist/audit/languageAnalysisEngine/index.js +39 -0
- package/dist/audit/languageAnalysisEngine/langugageAnalysisFactory.js +95 -0
- package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +121 -0
- package/dist/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +17 -0
- package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +257 -0
- package/dist/audit/languageAnalysisEngine/report/newReportingFeature.js +81 -0
- package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +133 -0
- package/dist/audit/languageAnalysisEngine/sendSnapshot.js +41 -0
- package/dist/audit/languageAnalysisEngine/util/capabilities.js +11 -0
- package/dist/audit/languageAnalysisEngine/util/generalAPI.js +39 -0
- package/dist/audit/languageAnalysisEngine/util/requestUtils.js +14 -0
- package/dist/audit/nodeAnalysisEngine/handleNPMLockFileV2.js +40 -0
- package/dist/audit/nodeAnalysisEngine/index.js +31 -0
- package/dist/audit/nodeAnalysisEngine/parseNPMLockFileContents.js +18 -0
- package/dist/audit/nodeAnalysisEngine/parseYarn2LockFileContents.js +51 -0
- package/dist/audit/nodeAnalysisEngine/parseYarnLockFileContents.js +18 -0
- package/dist/audit/nodeAnalysisEngine/readNPMLockFileContents.js +17 -0
- package/dist/audit/nodeAnalysisEngine/readProjectFileContents.js +14 -0
- package/dist/audit/nodeAnalysisEngine/readYarnLockFileContents.js +24 -0
- package/dist/audit/nodeAnalysisEngine/sanitizer.js +9 -0
- package/dist/audit/phpAnalysisEngine/index.js +23 -0
- package/dist/audit/phpAnalysisEngine/parseLockFileContents.js +52 -0
- package/dist/audit/phpAnalysisEngine/readLockFileContents.js +13 -0
- package/dist/audit/phpAnalysisEngine/readProjectFileContents.js +16 -0
- package/dist/audit/phpAnalysisEngine/sanitizer.js +5 -0
- package/dist/audit/pythonAnalysisEngine/index.js +25 -0
- package/dist/audit/pythonAnalysisEngine/parsePipfileLockContents.js +17 -0
- package/dist/audit/pythonAnalysisEngine/parseProjectFileContents.js +21 -0
- package/dist/audit/pythonAnalysisEngine/readPipfileLockFileContents.js +13 -0
- package/dist/audit/pythonAnalysisEngine/readPythonProjectFileContents.js +14 -0
- package/dist/audit/pythonAnalysisEngine/sanitizer.js +7 -0
- package/dist/audit/rubyAnalysisEngine/index.js +25 -0
- package/dist/audit/rubyAnalysisEngine/parseGemfileLockContents.js +176 -0
- package/dist/audit/rubyAnalysisEngine/parsedGemfile.js +22 -0
- package/dist/audit/rubyAnalysisEngine/readGemfileContents.js +14 -0
- package/dist/audit/rubyAnalysisEngine/readGemfileLockContents.js +14 -0
- package/dist/audit/rubyAnalysisEngine/sanitizer.js +6 -0
- package/dist/commands/audit/auditConfig.js +25 -0
- package/dist/commands/audit/auditController.js +31 -0
- package/dist/commands/audit/help.js +52 -0
- package/dist/commands/audit/processAudit.js +18 -0
- package/dist/commands/audit/saveFile.js +11 -0
- package/dist/commands/auth/auth.js +20 -2
- package/dist/commands/config/config.js +19 -8
- package/dist/commands/scan/processScan.js +9 -13
- package/dist/common/HTTPClient.js +112 -13
- package/dist/common/errorHandling.js +65 -1
- package/dist/common/versionChecker.js +30 -0
- package/dist/constants/constants.js +4 -2
- package/dist/constants/lambda.js +32 -4
- package/dist/constants/locales.js +60 -21
- package/dist/constants.js +181 -21
- package/dist/index.js +50 -23
- package/dist/lambda/aws.js +14 -11
- package/dist/lambda/help.js +4 -0
- package/dist/lambda/lambda.js +50 -27
- package/dist/lambda/lambdaUtils.js +72 -0
- package/dist/lambda/logUtils.js +11 -1
- package/dist/lambda/scanDetailCompletion.js +4 -4
- package/dist/lambda/scanRequest.js +11 -5
- package/dist/lambda/utils.js +110 -53
- package/dist/sbom/generateSbom.js +20 -0
- package/dist/scan/autoDetection.js +0 -32
- package/dist/scan/fileUtils.js +1 -1
- package/dist/scan/help.js +14 -40
- package/dist/scan/populateProjectIdAndProjectName.js +5 -0
- package/dist/scan/saveResults.js +14 -0
- package/dist/scan/scan.js +105 -40
- package/dist/scan/scanConfig.js +39 -0
- package/dist/scan/scanController.js +19 -16
- package/dist/scan/scanResults.js +24 -16
- package/dist/utils/commonApi.js +3 -3
- package/dist/utils/paramsUtil/commandlineParams.js +1 -20
- package/dist/utils/paramsUtil/paramHandler.js +3 -6
- package/dist/utils/parsedCLIOptions.js +14 -8
- package/dist/utils/requestUtils.js +1 -1
- package/dist/utils/saveFile.js +19 -0
- package/package.json +26 -21
- package/src/audit/AnalysisEngine.js +103 -0
- package/src/audit/catalogueApplication/catalogueApplication.js +42 -0
- package/src/audit/dotnetAnalysisEngine/index.js +26 -0
- package/src/audit/dotnetAnalysisEngine/parseLockFileContents.js +47 -0
- package/src/audit/dotnetAnalysisEngine/parseProjectFileContents.js +29 -0
- package/src/audit/dotnetAnalysisEngine/readLockFileContents.js +30 -0
- package/src/audit/dotnetAnalysisEngine/readProjectFileContents.js +26 -0
- package/src/audit/dotnetAnalysisEngine/sanitizer.js +11 -0
- package/src/audit/goAnalysisEngine/index.js +18 -0
- package/src/audit/goAnalysisEngine/parseProjectFileContents.js +209 -0
- package/src/audit/goAnalysisEngine/readProjectFileContents.js +31 -0
- package/src/audit/goAnalysisEngine/sanitizer.js +7 -0
- package/src/audit/javaAnalysisEngine/index.js +41 -0
- package/src/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +222 -0
- package/src/audit/javaAnalysisEngine/parseProjectFileContents.js +420 -0
- package/src/audit/javaAnalysisEngine/readProjectFileContents.js +141 -0
- package/src/audit/javaAnalysisEngine/sanitizer.js +6 -0
- package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +35 -0
- package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +41 -0
- package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasLockFile.js +54 -0
- package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +32 -0
- package/src/audit/languageAnalysisEngine/commonApi.js +20 -0
- package/src/audit/languageAnalysisEngine/constants.js +23 -0
- package/src/audit/languageAnalysisEngine/filterProjectPath.js +21 -0
- package/src/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +41 -0
- package/src/audit/languageAnalysisEngine/getProjectRootFilenames.js +72 -0
- package/src/audit/languageAnalysisEngine/index.js +45 -0
- package/src/audit/languageAnalysisEngine/langugageAnalysisFactory.js +126 -0
- package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +177 -0
- package/src/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +27 -0
- package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.js +303 -0
- package/src/audit/languageAnalysisEngine/report/newReportingFeature.js +124 -0
- package/src/audit/languageAnalysisEngine/report/reportingFeature.js +190 -0
- package/src/audit/languageAnalysisEngine/sendSnapshot.js +51 -0
- package/src/audit/languageAnalysisEngine/util/capabilities.js +12 -0
- package/src/audit/languageAnalysisEngine/util/generalAPI.js +43 -0
- package/src/audit/languageAnalysisEngine/util/requestUtils.js +17 -0
- package/src/audit/nodeAnalysisEngine/handleNPMLockFileV2.js +49 -0
- package/src/audit/nodeAnalysisEngine/index.js +35 -0
- package/src/audit/nodeAnalysisEngine/parseNPMLockFileContents.js +20 -0
- package/src/audit/nodeAnalysisEngine/parseYarn2LockFileContents.js +63 -0
- package/src/audit/nodeAnalysisEngine/parseYarnLockFileContents.js +26 -0
- package/src/audit/nodeAnalysisEngine/readNPMLockFileContents.js +23 -0
- package/src/audit/nodeAnalysisEngine/readProjectFileContents.js +27 -0
- package/src/audit/nodeAnalysisEngine/readYarnLockFileContents.js +36 -0
- package/src/audit/nodeAnalysisEngine/sanitizer.js +11 -0
- package/src/audit/phpAnalysisEngine/index.js +27 -0
- package/src/audit/phpAnalysisEngine/parseLockFileContents.js +60 -0
- package/src/audit/phpAnalysisEngine/readLockFileContents.js +14 -0
- package/src/audit/phpAnalysisEngine/readProjectFileContents.js +25 -0
- package/src/audit/phpAnalysisEngine/sanitizer.js +4 -0
- package/src/audit/pythonAnalysisEngine/index.js +55 -0
- package/src/audit/pythonAnalysisEngine/parsePipfileLockContents.js +23 -0
- package/src/audit/pythonAnalysisEngine/parseProjectFileContents.js +33 -0
- package/src/audit/pythonAnalysisEngine/readPipfileLockFileContents.js +16 -0
- package/src/audit/pythonAnalysisEngine/readPythonProjectFileContents.js +22 -0
- package/src/audit/pythonAnalysisEngine/sanitizer.js +9 -0
- package/src/audit/rubyAnalysisEngine/index.js +30 -0
- package/src/audit/rubyAnalysisEngine/parseGemfileLockContents.js +215 -0
- package/src/audit/rubyAnalysisEngine/parsedGemfile.js +39 -0
- package/src/audit/rubyAnalysisEngine/readGemfileContents.js +18 -0
- package/src/audit/rubyAnalysisEngine/readGemfileLockContents.js +17 -0
- package/src/audit/rubyAnalysisEngine/sanitizer.js +8 -0
- package/src/commands/audit/auditConfig.ts +30 -0
- package/src/commands/audit/auditController.ts +31 -0
- package/src/commands/audit/help.ts +48 -0
- package/src/commands/audit/processAudit.ts +18 -0
- package/src/commands/audit/saveFile.ts +6 -0
- package/src/commands/auth/auth.js +26 -2
- package/src/commands/config/config.js +22 -8
- package/src/commands/scan/processScan.js +9 -13
- package/src/common/HTTPClient.js +149 -14
- package/src/common/errorHandling.ts +85 -2
- package/src/common/versionChecker.ts +39 -0
- package/src/constants/constants.js +5 -4
- package/src/constants/lambda.js +45 -4
- package/src/constants/locales.js +76 -26
- package/src/constants.js +204 -23
- package/src/index.ts +67 -27
- package/src/lambda/aws.ts +13 -12
- package/src/lambda/help.ts +4 -0
- package/src/lambda/lambda.ts +53 -34
- package/src/lambda/lambdaUtils.ts +111 -0
- package/src/lambda/logUtils.ts +19 -1
- package/src/lambda/scanDetailCompletion.ts +4 -4
- package/src/lambda/scanRequest.ts +13 -11
- package/src/lambda/utils.ts +149 -81
- package/src/sbom/generateSbom.ts +17 -0
- package/src/scan/autoDetection.js +0 -29
- package/src/scan/fileUtils.js +1 -1
- package/src/scan/help.js +14 -45
- package/src/scan/populateProjectIdAndProjectName.js +5 -0
- package/src/scan/saveResults.js +14 -0
- package/src/scan/scan.js +127 -58
- package/src/scan/scanConfig.js +54 -0
- package/src/scan/scanController.js +22 -15
- package/src/scan/scanResults.js +32 -19
- package/src/utils/commonApi.js +2 -3
- package/src/utils/getConfig.ts +2 -0
- package/src/utils/paramsUtil/commandlineParams.js +1 -26
- package/src/utils/paramsUtil/paramHandler.js +3 -7
- package/src/utils/parsedCLIOptions.js +11 -9
- package/src/utils/requestUtils.js +1 -1
- package/src/utils/saveFile.js +19 -0
- package/dist/lambda/scanDetail.js +0 -30
- package/dist/scan/fileFinder.js +0 -15
- package/dist/utils/paramsUtil/yamlParams.js +0 -6
package/.prettierignore
ADDED
package/README.md
CHANGED
|
@@ -1,13 +1,45 @@
|
|
|
1
|
-
#
|
|
1
|
+
# CodeSec by Contrast Security
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
This version supports **Java** and **Python** functions on AWS.
|
|
3
|
+
CodeSec delivers:
|
|
5
4
|
|
|
6
|
-
|
|
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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
57
|
+
### Start scanning
|
|
52
58
|
|
|
53
|
-
|
|
54
|
-
-
|
|
59
|
+
Use contrast lambda to scan your AWS Lambda functions.
|
|
60
|
+
`contrast lambda --function-name MyFunctionName --region my-aws-region`
|
|
55
61
|
|
|
56
|
-
|
|
62
|
+
## Contrast commands
|
|
57
63
|
|
|
58
|
-
|
|
59
|
-
- `yarn global add @contrast/contrast`
|
|
64
|
+
### auth
|
|
60
65
|
|
|
61
|
-
|
|
66
|
+
Authenticate Contrast using your GitHub or Google account. A new browser window will open for login.
|
|
62
67
|
|
|
63
|
-
|
|
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
|
-
|
|
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
|
-
|
|
72
|
+
Displays stored credentials.
|
|
74
73
|
|
|
75
|
-
|
|
76
|
-
- `contrast lambda --function-name <function> [options]`
|
|
74
|
+
**Usage:** `contrast config`
|
|
77
75
|
|
|
78
|
-
|
|
76
|
+
**Options:**
|
|
79
77
|
|
|
80
|
-
|
|
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
|
-
|
|
80
|
+
### scan
|
|
86
81
|
|
|
87
|
-
|
|
82
|
+
Performs a security SAST scan.
|
|
88
83
|
|
|
89
|
-
|
|
84
|
+
**Usage:** `contrast scan [option]`
|
|
90
85
|
|
|
91
|
-
|
|
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
|
-
|
|
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
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
143
|
+
### version
|
|
108
144
|
|
|
109
|
-
|
|
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
|
+
};
|