@contrast/contrast 1.0.9 → 1.0.12
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/README.md +2 -2
- package/dist/audit/languageAnalysisEngine/getProjectRootFilenames.js +17 -17
- package/dist/audit/{languageAnalysisEngine/report → report}/commonReportingFunctions.js +56 -35
- package/dist/audit/report/models/reportGuidanceModel.js +6 -0
- package/dist/audit/{languageAnalysisEngine/report → report}/models/reportLibraryModel.js +0 -0
- package/dist/audit/{languageAnalysisEngine/report → report}/models/reportListModel.js +0 -0
- package/dist/audit/{languageAnalysisEngine/report → report}/models/reportOutputModel.js +1 -2
- package/dist/audit/{languageAnalysisEngine/report → report}/models/reportSeverityModel.js +0 -0
- package/dist/audit/{languageAnalysisEngine/report → report}/models/severityCountModel.js +1 -0
- package/dist/audit/{languageAnalysisEngine/report → report}/reportingFeature.js +12 -8
- package/dist/audit/{languageAnalysisEngine/report → report}/utils/reportUtils.js +3 -4
- package/dist/commands/audit/auditConfig.js +3 -3
- package/dist/commands/audit/help.js +3 -1
- package/dist/commands/audit/processAudit.js +4 -2
- package/dist/commands/auth/auth.js +1 -1
- package/dist/commands/config/config.js +2 -2
- package/dist/commands/scan/processScan.js +11 -4
- package/dist/commands/scan/sca/scaAnalysis.js +20 -9
- package/dist/common/HTTPClient.js +9 -0
- package/dist/common/commonHelp.js +19 -0
- package/dist/common/errorHandling.js +2 -2
- package/dist/common/fail.js +66 -0
- package/dist/common/versionChecker.js +4 -2
- package/dist/constants/constants.js +2 -2
- package/dist/constants/locales.js +26 -11
- package/dist/constants.js +52 -5
- package/dist/index.js +5 -2
- package/dist/lambda/help.js +2 -3
- package/dist/scaAnalysis/common/scaParserForGoAndJava.js +32 -0
- package/dist/scaAnalysis/common/treeUpload.js +20 -5
- package/dist/scaAnalysis/dotnet/analysis.js +15 -3
- package/dist/scaAnalysis/go/goAnalysis.js +8 -2
- package/dist/scaAnalysis/java/analysis.js +10 -6
- package/dist/scaAnalysis/java/index.js +7 -1
- package/dist/scaAnalysis/java/javaBuildDepsParser.js +19 -3
- package/dist/scaAnalysis/javascript/index.js +3 -0
- package/dist/scaAnalysis/php/analysis.js +1 -1
- package/dist/scaAnalysis/php/index.js +12 -6
- package/dist/scaAnalysis/php/phpNewServicesMapper.js +62 -0
- package/dist/scaAnalysis/python/analysis.js +43 -5
- package/dist/scaAnalysis/python/index.js +7 -2
- package/dist/scaAnalysis/ruby/analysis.js +14 -4
- package/dist/scan/autoDetection.js +5 -13
- package/dist/scan/formatScanOutput.js +6 -5
- package/dist/scan/help.js +2 -3
- package/dist/scan/populateProjectIdAndProjectName.js +5 -0
- package/dist/scan/scan.js +4 -0
- package/dist/scan/scanConfig.js +4 -4
- package/dist/scan/scanResults.js +46 -3
- package/dist/telemetry/telemetry.js +137 -0
- package/dist/utils/commonApi.js +1 -1
- package/dist/utils/getConfig.js +2 -4
- package/dist/utils/parsedCLIOptions.js +3 -1
- package/dist/utils/requestUtils.js +7 -1
- package/package.json +4 -2
- package/src/audit/languageAnalysisEngine/getProjectRootFilenames.js +22 -29
- package/src/audit/{languageAnalysisEngine/report → report}/commonReportingFunctions.ts +80 -44
- package/src/audit/report/models/reportGuidanceModel.ts +5 -0
- package/src/audit/{languageAnalysisEngine/report → report}/models/reportLibraryModel.ts +0 -0
- package/src/audit/{languageAnalysisEngine/report → report}/models/reportListModel.ts +0 -0
- package/src/audit/{languageAnalysisEngine/report → report}/models/reportOutputModel.ts +1 -7
- package/src/audit/{languageAnalysisEngine/report → report}/models/reportSeverityModel.ts +0 -0
- package/src/audit/{languageAnalysisEngine/report → report}/models/severityCountModel.ts +2 -0
- package/src/audit/{languageAnalysisEngine/report → report}/reportingFeature.ts +16 -9
- package/src/audit/{languageAnalysisEngine/report → report}/utils/reportUtils.ts +4 -4
- package/src/commands/audit/auditConfig.ts +10 -3
- package/src/commands/audit/help.ts +3 -1
- package/src/commands/audit/processAudit.ts +16 -2
- package/src/commands/auth/auth.js +3 -1
- package/src/commands/config/config.js +4 -2
- package/src/commands/scan/processScan.js +18 -4
- package/src/commands/scan/sca/scaAnalysis.js +27 -10
- package/src/common/HTTPClient.js +15 -0
- package/src/common/commonHelp.ts +13 -0
- package/src/common/errorHandling.ts +2 -3
- package/src/common/fail.js +75 -0
- package/src/common/versionChecker.ts +4 -4
- package/src/constants/constants.js +2 -2
- package/src/constants/locales.js +35 -13
- package/src/constants.js +56 -6
- package/src/index.ts +17 -2
- package/src/lambda/help.ts +2 -3
- package/src/scaAnalysis/common/scaParserForGoAndJava.js +41 -0
- package/src/scaAnalysis/common/treeUpload.js +21 -5
- package/src/scaAnalysis/dotnet/analysis.js +21 -3
- package/src/scaAnalysis/go/goAnalysis.js +9 -2
- package/src/scaAnalysis/java/analysis.js +11 -6
- package/src/scaAnalysis/java/index.js +9 -1
- package/src/scaAnalysis/java/javaBuildDepsParser.js +25 -6
- package/src/scaAnalysis/javascript/index.js +3 -0
- package/src/scaAnalysis/php/analysis.js +1 -1
- package/src/scaAnalysis/php/index.js +12 -6
- package/src/scaAnalysis/php/phpNewServicesMapper.js +77 -0
- package/src/scaAnalysis/python/analysis.js +49 -5
- package/src/scaAnalysis/python/index.js +7 -2
- package/src/scaAnalysis/ruby/analysis.js +16 -4
- package/src/scan/autoDetection.js +6 -13
- package/src/scan/formatScanOutput.ts +7 -5
- package/src/scan/help.js +2 -3
- package/src/scan/populateProjectIdAndProjectName.js +5 -1
- package/src/scan/scan.ts +4 -0
- package/src/scan/scanConfig.js +6 -4
- package/src/scan/scanResults.js +52 -3
- package/src/telemetry/telemetry.ts +154 -0
- package/src/utils/commonApi.js +1 -1
- package/src/utils/getConfig.ts +2 -11
- package/src/utils/parsedCLIOptions.js +14 -1
- package/src/utils/requestUtils.js +8 -1
|
@@ -12,7 +12,7 @@ const MEDIUM = 'MEDIUM';
|
|
|
12
12
|
const HIGH = 'HIGH';
|
|
13
13
|
const CRITICAL = 'CRITICAL';
|
|
14
14
|
const APP_NAME = 'contrast';
|
|
15
|
-
const APP_VERSION = '1.0.
|
|
15
|
+
const APP_VERSION = '1.0.12';
|
|
16
16
|
const TIMEOUT = 120000;
|
|
17
17
|
const HIGH_COLOUR = '#ff9900';
|
|
18
18
|
const CRITICAL_COLOUR = '#e35858';
|
|
@@ -29,7 +29,7 @@ const AUTH_CALLBACK_URL = 'https://cli-auth-api.contrastsecurity.com';
|
|
|
29
29
|
const SARIF_FILE = 'SARIF';
|
|
30
30
|
const SBOM_CYCLONE_DX_FILE = 'cyclonedx';
|
|
31
31
|
const SBOM_SPDX_FILE = 'spdx';
|
|
32
|
-
const CE_URL = 'https://ce.contrastsecurity.com
|
|
32
|
+
const CE_URL = 'https://ce.contrastsecurity.com';
|
|
33
33
|
module.exports = {
|
|
34
34
|
supportedLanguages: { NODE, DOTNET, JAVA, RUBY, PYTHON, GO, PHP, JAVASCRIPT },
|
|
35
35
|
supportedLanguagesScan: { JAVASCRIPT, DOTNET, JAVA },
|
|
@@ -16,7 +16,7 @@ const en_locales = () => {
|
|
|
16
16
|
languageAnalysisFactoryFailureHeader: 'FAIL',
|
|
17
17
|
libraryAnalysisError: 'Please ensure the language parameter is set in accordance to the language specified on the project path.\nContrast CLI must be run in the same directory as the project manifest file OR the project_path parameter must be used to identify the directory containing the project manifest file.\n\nFor further information please read our usage guide, which can be accessed with the following command:\n\ncontrast-cli --help',
|
|
18
18
|
yamlMissingParametersHeader: 'Missing Parameters',
|
|
19
|
-
|
|
19
|
+
genericErrorMessage: 'An error has occur please check your command again. For more information use the --help commands.',
|
|
20
20
|
unauthenticatedErrorHeader: '401 error - Unauthenticated',
|
|
21
21
|
unauthenticatedErrorMessage: 'Please check the following keys are correct:\n--organization-id, --api-key or --authorization',
|
|
22
22
|
badRequestErrorHeader: '400 error - Bad Request',
|
|
@@ -45,7 +45,7 @@ const en_locales = () => {
|
|
|
45
45
|
languageAnalysisProjectRootFileNameMissingError: "%s isn't a file or directory",
|
|
46
46
|
languageAnalysisProjectRootFileNameFailure: 'Failed to get information about the file or directory @ %s because: ',
|
|
47
47
|
languageAnalysisFailure: ' analysis failed because: ',
|
|
48
|
-
languageAnalysisNoLanguage: 'We cannot detect a project, use
|
|
48
|
+
languageAnalysisNoLanguage: 'We cannot detect a project, use -f <path> to specify a file or folder to analyze.',
|
|
49
49
|
languageAnalysisNoLanguageHelpLine: `${chalk.bold('contrast audit --help')} for more information.`,
|
|
50
50
|
NodeAnalysisFailure: 'NODE analysis failed because: ',
|
|
51
51
|
phpAnalysisFailure: 'PHP analysis failed because: ',
|
|
@@ -79,8 +79,9 @@ const en_locales = () => {
|
|
|
79
79
|
constantsHostId: 'Provide the name of the host and optionally the port expressed as "<host>:<port>".',
|
|
80
80
|
constantsApplicationName: 'The name of the application cataloged by Contrast UI',
|
|
81
81
|
constantsCatalogueApplication: 'Provide this if you want to catalogue an application',
|
|
82
|
+
failOptionErrorMessage: ' FAIL - CVEs have been detected that match at least the cve_severity option specified.',
|
|
82
83
|
constantsLanguage: 'Valid values are JAVA, DOTNET, NODE, PYTHON and RUBY. If there are multiple project configuration files in the project_path, language is also required. Also, provide this when cataloguing an application',
|
|
83
|
-
constantsFilePath: `
|
|
84
|
+
constantsFilePath: `Specify a directory or the file where dependencies are declared. (By default, CodeSec will search for project files in the current directory.)`,
|
|
84
85
|
constantsSilent: 'Silences JSON output.',
|
|
85
86
|
constantsAppGroups: 'Assign your application to one or more pre-existing groups when using the catalogue command. Group lists should be comma separated.',
|
|
86
87
|
constantsVersion: 'Displays CLI Version you are currently on.',
|
|
@@ -93,12 +94,17 @@ const en_locales = () => {
|
|
|
93
94
|
constantsProjectId: 'The ID associated with a scan project. Replace <ProjectID> with the ID for the scan project. To find the ID, select a scan project in Contrast and locate the last number in the URL.',
|
|
94
95
|
constantsReport: 'Display vulnerability information for this application',
|
|
95
96
|
constantsFail: 'Set the process to fail if this option is set in combination with --cve_severity.',
|
|
96
|
-
|
|
97
|
+
failThresholdOptionErrorMessage: 'More than 0 vulnerabilities found',
|
|
98
|
+
failSeverityOptionErrorMessage: ' FAIL - Results detected vulnerabilities over accepted severity level',
|
|
97
99
|
constantsSeverity: 'Allows the user to report libraries with vulnerabilities above a chosen severity level. For example, cve_severity medium only reports libraries with vulnerabilities at medium or higher severity. Values for level are high, medium or low.',
|
|
98
100
|
constantsCount: 'The number of CVEs that must be exceeded to fail a build',
|
|
99
101
|
constantsHeader: 'CodeSec by Contrast Security',
|
|
102
|
+
configHeader2: 'Config options',
|
|
103
|
+
clearHeader: '-c, --clear',
|
|
104
|
+
clearContent: 'Removes stored credentials',
|
|
100
105
|
constantsPrerequisitesContentScanLanguages: 'Java, Javascript and .NET supported',
|
|
101
|
-
constantsContrastContent:
|
|
106
|
+
constantsContrastContent: 'Use the ‘contrast’ command for fast and accurate security analysis of your applications, APIs, serverless functions, and libraries.',
|
|
107
|
+
constantsContrastCategories: '\n Code: Java, .NET, .NET Core, JavaScript\n Serverless: AWS Lambda - Java, Python\n Libraries: Java, .NET, Node, Ruby, Python, Go, PHP\n',
|
|
102
108
|
constantsUsageGuideContentRecommendation: 'Our recommendation is that this is invoked as part of a CI pipeline so that running the cli is automated as part of your build process.',
|
|
103
109
|
constantsPrerequisitesHeader: 'Pre-requisites',
|
|
104
110
|
constantsAuthUsageHeader: 'Usage',
|
|
@@ -187,12 +193,14 @@ const en_locales = () => {
|
|
|
187
193
|
permissionsError: 'You do not have the correct permissions here. \n Contact support@contrastsecurity.com to get this fixed.',
|
|
188
194
|
scanErrorFileMessage: 'We only accept the following file types: \nJava - .jar, .war \nJavaScript - .js or .zip files',
|
|
189
195
|
helpAuthSummary: 'Authenticate Contrast using your Github or Google account',
|
|
190
|
-
|
|
191
|
-
|
|
196
|
+
helpAuditSummary: 'Searches for a suitable file in the working directory to perform a security audit of dependencies and returns the results. [Contrast audit --help (for options).]',
|
|
197
|
+
helpScanSummary: 'Searches for a .jar, .war, .js, or .zip file in the working directory, uploads files for analysis, and returns the results. [For further help/options, enter scan --help]',
|
|
198
|
+
helpLambdaSummary: 'Performs a static security scan on an AWS lambda function. lambda --help (for options)',
|
|
192
199
|
helpVersionSummary: 'Displays version of Contrast CLI',
|
|
193
200
|
helpConfigSummary: 'Displays stored credentials',
|
|
194
201
|
helpSummary: 'Displays usage guide',
|
|
195
202
|
authName: 'auth',
|
|
203
|
+
auditName: 'audit',
|
|
196
204
|
scanName: 'scan',
|
|
197
205
|
lambdaName: 'lambda',
|
|
198
206
|
versionName: 'version',
|
|
@@ -205,8 +213,7 @@ const en_locales = () => {
|
|
|
205
213
|
scanOptionsFileNameSummary: 'Path of the file you want to scan. If no file is specified, Contrast searches for a .jar, .war, .exe or .zip file in the working directory.',
|
|
206
214
|
scanOptionsVerboseSummary: ' Returns extended information to the terminal.',
|
|
207
215
|
authSuccessMessage: 'Authentication successful',
|
|
208
|
-
runAuthSuccessMessage: "Now you can use Contrast
|
|
209
|
-
"or 'contrast help' to learn more about the capabilities.",
|
|
216
|
+
runAuthSuccessMessage: "Now you can use CodeSec by Contrast \nRun: \n'contrast scan' on your file \n'contrast audit' on a file or directory,\n'contrast lambda' on an AWS function.\nor 'contrast help' to learn more about the capabilities.",
|
|
210
217
|
authWaitingMessage: 'Waiting for auth...',
|
|
211
218
|
authTimedOutMessage: 'Auth Timed out, try again',
|
|
212
219
|
zipErrorScan: 'We only support zip files for JAVASCRIPT language, please set the flag --language JAVASCRIPT',
|
|
@@ -228,7 +235,7 @@ const en_locales = () => {
|
|
|
228
235
|
lambdaPrerequisitesContent: '',
|
|
229
236
|
lambdaPrerequisitesContentLambdaLanguages: 'Supported runtimes: Java & Python',
|
|
230
237
|
lambdaPrerequisitesContentLambdaDescriptionTitle: 'AWS Requirements\n',
|
|
231
|
-
lambdaPrerequisitesContentLambdaDescription: 'Make sure you have the AWS credentials configured on your local environment. \nYou need the following AWS permissions configured on your IAM user:\n - Lambda: GetFunction, GetLayerVersion
|
|
238
|
+
lambdaPrerequisitesContentLambdaDescription: 'Make sure you have the AWS credentials configured on your local environment. \nYou need the following AWS permissions configured on your IAM user:\n - Lambda: GetFunction, GetLayerVersion, ListFunctions\n - IAM: GetRolePolicy, GetPolicy, GetPolicyVersion, ListRolePolicies, ListAttachedRolePolicies',
|
|
232
239
|
scanFileNameOption: '-f, --file',
|
|
233
240
|
lambdaFunctionNameOption: '-f, --function-name',
|
|
234
241
|
lambdaListFunctionsOption: '-l, --list-functions',
|
|
@@ -271,7 +278,8 @@ const en_locales = () => {
|
|
|
271
278
|
constantsAuditPrerequisitesContentPHPMessage: `${chalk.bold('PHP:')} composer.json and composer.lock\n`,
|
|
272
279
|
constantsAuditOptions: 'Audit Options',
|
|
273
280
|
auditOptionsSaveDescription: 'Generate and save an SBOM (Software Bill of Materials)\n',
|
|
274
|
-
auditOptionsSaveOptionsDescription: 'Valid options are: spdx
|
|
281
|
+
auditOptionsSaveOptionsDescription: 'Valid options are: --save spdx and --save cyclonedx (CycloneDX is the default format.)',
|
|
282
|
+
exceededFreeTier: `It looks like you are really loving CodeSec! \nYou have reached the monthly scan limit on the FREE tier. \nPlease contact sales@contrastsecurity.com to upgrade.`,
|
|
275
283
|
scanNotCompleted: 'Scan not completed. Check for framework and language support here: %s',
|
|
276
284
|
auditNotCompleted: 'audit not completed. Please try again',
|
|
277
285
|
scanNoVulnerabilitiesFound: '🎉 No vulnerabilities found.',
|
|
@@ -287,6 +295,13 @@ const en_locales = () => {
|
|
|
287
295
|
auditReportFailureMessage: 'Unable to generate library report',
|
|
288
296
|
auditSCAAnalysisBegins: 'Contrast SCA audit started',
|
|
289
297
|
auditSCAAnalysisComplete: 'Contrast audit complete',
|
|
298
|
+
commonHelpHeader: 'Need More Help?',
|
|
299
|
+
commonHelpCheckOutHeader: chalk.hex('#9DC184')('Check out:'),
|
|
300
|
+
commonHelpCheckOutText: ' https://support.contrastsecurity.com',
|
|
301
|
+
commonHelpLearnMoreHeader: chalk.hex('#9DC184')('Learn more at:'),
|
|
302
|
+
commonHelpLearnMoreText: ' https://developer.contrastsecurity.com',
|
|
303
|
+
commonHelpJoinDiscussionHeader: chalk.hex('#9DC184')('Join the discussion:'),
|
|
304
|
+
commonHelpJoinDiscussionText: ' https://dev.to/codesec',
|
|
290
305
|
...lambda
|
|
291
306
|
};
|
|
292
307
|
};
|
package/dist/constants.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
const commandLineUsage = require('command-line-usage');
|
|
3
3
|
const i18n = require('i18n');
|
|
4
4
|
const { en_locales } = require('./constants/locales.js');
|
|
5
|
+
const { parseSeverity } = require('./common/fail');
|
|
6
|
+
const { commonHelpLinks } = require('./common/commonHelp');
|
|
5
7
|
i18n.configure({
|
|
6
8
|
staticCatalog: {
|
|
7
9
|
en: en_locales()
|
|
@@ -93,6 +95,22 @@ const scanOptionDefinitions = [
|
|
|
93
95
|
'}: ' +
|
|
94
96
|
i18n.__('constantsProxyServer')
|
|
95
97
|
},
|
|
98
|
+
{
|
|
99
|
+
name: 'fail',
|
|
100
|
+
type: Boolean,
|
|
101
|
+
description: '{bold ' +
|
|
102
|
+
i18n.__('constantsOptional') +
|
|
103
|
+
'}: ' +
|
|
104
|
+
i18n.__('failOptionErrorMessage')
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: 'severity',
|
|
108
|
+
type: severity => parseSeverity(severity),
|
|
109
|
+
description: '{bold ' +
|
|
110
|
+
i18n.__('constantsOptional') +
|
|
111
|
+
'}: ' +
|
|
112
|
+
i18n.__('constantsSeverity')
|
|
113
|
+
},
|
|
96
114
|
{
|
|
97
115
|
name: 'ff',
|
|
98
116
|
type: Boolean,
|
|
@@ -189,12 +207,28 @@ const auditOptionDefinitions = [
|
|
|
189
207
|
{
|
|
190
208
|
name: 'file',
|
|
191
209
|
alias: 'f',
|
|
192
|
-
defaultValue: process.cwd(),
|
|
210
|
+
defaultValue: process.cwd().concat('/'),
|
|
193
211
|
description: '{bold ' +
|
|
194
212
|
i18n.__('constantsOptional') +
|
|
195
213
|
'}: ' +
|
|
196
214
|
i18n.__('constantsFilePath')
|
|
197
215
|
},
|
|
216
|
+
{
|
|
217
|
+
name: 'fail',
|
|
218
|
+
type: Boolean,
|
|
219
|
+
description: '{bold ' +
|
|
220
|
+
i18n.__('constantsOptional') +
|
|
221
|
+
'}: ' +
|
|
222
|
+
i18n.__('failOptionErrorMessage')
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
name: 'severity',
|
|
226
|
+
type: severity => parseSeverity(severity),
|
|
227
|
+
description: '{bold ' +
|
|
228
|
+
i18n.__('constantsOptional') +
|
|
229
|
+
'}: ' +
|
|
230
|
+
i18n.__('constantsSeverity')
|
|
231
|
+
},
|
|
198
232
|
{
|
|
199
233
|
name: 'app-groups',
|
|
200
234
|
description: '{bold ' +
|
|
@@ -227,6 +261,7 @@ const auditOptionDefinitions = [
|
|
|
227
261
|
{
|
|
228
262
|
name: 'ignore-dev',
|
|
229
263
|
type: Boolean,
|
|
264
|
+
alias: 'i',
|
|
230
265
|
description: '{bold ' +
|
|
231
266
|
i18n.__('constantsOptional') +
|
|
232
267
|
'}: ' +
|
|
@@ -259,7 +294,6 @@ const auditOptionDefinitions = [
|
|
|
259
294
|
},
|
|
260
295
|
{
|
|
261
296
|
name: 'host',
|
|
262
|
-
alias: 'h',
|
|
263
297
|
description: '{bold ' +
|
|
264
298
|
i18n.__('constantsRequired') +
|
|
265
299
|
'}: ' +
|
|
@@ -302,12 +336,20 @@ const auditOptionDefinitions = [
|
|
|
302
336
|
i18n.__('constantsOptional') +
|
|
303
337
|
'}: ' +
|
|
304
338
|
i18n.__('scanOptionsTimeoutSummary')
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
name: 'help',
|
|
342
|
+
alias: 'h',
|
|
343
|
+
type: Boolean
|
|
305
344
|
}
|
|
306
345
|
];
|
|
307
346
|
const mainUsageGuide = commandLineUsage([
|
|
308
347
|
{
|
|
309
348
|
header: i18n.__('constantsHeader'),
|
|
310
|
-
content: [
|
|
349
|
+
content: [
|
|
350
|
+
i18n.__('constantsContrastContent'),
|
|
351
|
+
i18n.__('constantsContrastCategories')
|
|
352
|
+
]
|
|
311
353
|
},
|
|
312
354
|
{
|
|
313
355
|
header: i18n.__('constantsUsage'),
|
|
@@ -319,14 +361,19 @@ const mainUsageGuide = commandLineUsage([
|
|
|
319
361
|
{ name: i18n.__('authName'), summary: i18n.__('helpAuthSummary') },
|
|
320
362
|
{ name: i18n.__('scanName'), summary: i18n.__('helpScanSummary') },
|
|
321
363
|
{ name: i18n.__('lambdaName'), summary: i18n.__('helpLambdaSummary') },
|
|
364
|
+
{ name: i18n.__('auditName'), summary: i18n.__('helpAuditSummary') },
|
|
322
365
|
{ name: i18n.__('versionName'), summary: i18n.__('helpVersionSummary') },
|
|
323
366
|
{ name: i18n.__('configName'), summary: i18n.__('helpConfigSummary') },
|
|
324
367
|
{ name: i18n.__('helpName'), summary: i18n.__('helpSummary') }
|
|
325
368
|
]
|
|
326
369
|
},
|
|
327
370
|
{
|
|
328
|
-
|
|
329
|
-
|
|
371
|
+
header: i18n.__('configHeader2'),
|
|
372
|
+
content: [
|
|
373
|
+
{ name: i18n.__('clearHeader'), summary: i18n.__('clearContent') }
|
|
374
|
+
]
|
|
375
|
+
},
|
|
376
|
+
commonHelpLinks()
|
|
330
377
|
]);
|
|
331
378
|
const mainDefinition = [{ name: 'command', defaultOption: true }];
|
|
332
379
|
module.exports = {
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,7 @@ const lambda_1 = require("./lambda/lambda");
|
|
|
15
15
|
const getConfig_1 = require("./utils/getConfig");
|
|
16
16
|
const versionChecker_1 = require("./common/versionChecker");
|
|
17
17
|
const errorHandling_1 = require("./common/errorHandling");
|
|
18
|
+
const telemetry_1 = require("./telemetry/telemetry");
|
|
18
19
|
const { commandLineDefinitions: { mainUsageGuide, mainDefinition } } = constants_1.default;
|
|
19
20
|
const config = (0, getConfig_1.localConfig)(constants_2.APP_NAME, constants_2.APP_VERSION);
|
|
20
21
|
const getMainOption = () => {
|
|
@@ -58,10 +59,10 @@ const start = async () => {
|
|
|
58
59
|
return await (0, lambda_1.processLambda)(argvMain);
|
|
59
60
|
}
|
|
60
61
|
if (command === 'scan') {
|
|
61
|
-
return await (0, processScan_1.processScan)(argvMain);
|
|
62
|
+
return await (0, processScan_1.processScan)(config, argvMain);
|
|
62
63
|
}
|
|
63
64
|
if (command === 'audit') {
|
|
64
|
-
return await (0, processAudit_1.processAudit)(argvMain);
|
|
65
|
+
return await (0, processAudit_1.processAudit)(config, argvMain);
|
|
65
66
|
}
|
|
66
67
|
if (command === 'help' ||
|
|
67
68
|
argvMain.includes('--help') ||
|
|
@@ -73,9 +74,11 @@ const start = async () => {
|
|
|
73
74
|
foundCommand
|
|
74
75
|
? console.log(`Unknown Command: Did you mean "${foundCommand}"? \nUse "${foundCommand} --help" for the full list of options`)
|
|
75
76
|
: console.log(`Unknown Command: ${command} \nUse --help for the full list`);
|
|
77
|
+
await (0, telemetry_1.sendTelemetryConfigAsConfObj)(config, command, argvMain, 'FAILURE', 'undefined');
|
|
76
78
|
}
|
|
77
79
|
else {
|
|
78
80
|
console.log(`Unknown Command: ${command} \nUse --help for the full list`);
|
|
81
|
+
await (0, telemetry_1.sendTelemetryConfigAsConfObj)(config, command, argvMain, 'FAILURE', 'undefined');
|
|
79
82
|
}
|
|
80
83
|
process.exit(9);
|
|
81
84
|
}
|
package/dist/lambda/help.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.lambdaUsageGuide = void 0;
|
|
7
7
|
const command_line_usage_1 = __importDefault(require("command-line-usage"));
|
|
8
8
|
const i18n_1 = __importDefault(require("i18n"));
|
|
9
|
+
const commonHelp_1 = require("../common/commonHelp");
|
|
9
10
|
const lambdaUsageGuide = (0, command_line_usage_1.default)([
|
|
10
11
|
{
|
|
11
12
|
header: i18n_1.default.__('lambdaHeader'),
|
|
@@ -80,8 +81,6 @@ const lambdaUsageGuide = (0, command_line_usage_1.default)([
|
|
|
80
81
|
{ name: i18n_1.default.__('lambdaHelpOption'), summary: i18n_1.default.__('helpSummary') }
|
|
81
82
|
]
|
|
82
83
|
},
|
|
83
|
-
|
|
84
|
-
content: '{underline https://www.contrastsecurity.com/developer/codesec}'
|
|
85
|
-
}
|
|
84
|
+
(0, commonHelp_1.commonHelpLinks)()
|
|
86
85
|
]);
|
|
87
86
|
exports.lambdaUsageGuide = lambdaUsageGuide;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const parseDependenciesForSCAServices = dependencyTreeObject => {
|
|
3
|
+
let parsedDependencyTree = {};
|
|
4
|
+
let subDeps;
|
|
5
|
+
for (let tree in dependencyTreeObject) {
|
|
6
|
+
let unParsedDependencyTree = dependencyTreeObject[tree];
|
|
7
|
+
for (let dependency in unParsedDependencyTree) {
|
|
8
|
+
subDeps = parseSubDependencies(unParsedDependencyTree[dependency].edges);
|
|
9
|
+
let parsedDependency = {
|
|
10
|
+
name: unParsedDependencyTree[dependency].artifactID,
|
|
11
|
+
group: unParsedDependencyTree[dependency].group,
|
|
12
|
+
version: unParsedDependencyTree[dependency].version,
|
|
13
|
+
directDependency: unParsedDependencyTree[dependency].type === 'direct',
|
|
14
|
+
isProduction: true,
|
|
15
|
+
dependencies: subDeps
|
|
16
|
+
};
|
|
17
|
+
parsedDependencyTree[dependency] = parsedDependency;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return parsedDependencyTree;
|
|
21
|
+
};
|
|
22
|
+
const parseSubDependencies = dependencies => {
|
|
23
|
+
let subDeps = [];
|
|
24
|
+
for (let x in dependencies) {
|
|
25
|
+
subDeps.push(dependencies[x]);
|
|
26
|
+
}
|
|
27
|
+
return subDeps;
|
|
28
|
+
};
|
|
29
|
+
module.exports = {
|
|
30
|
+
parseDependenciesForSCAServices,
|
|
31
|
+
parseSubDependencies
|
|
32
|
+
};
|
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
const commonApi = require('../../utils/commonApi');
|
|
3
3
|
const { APP_VERSION } = require('../../constants/constants');
|
|
4
4
|
const commonSendSnapShot = async (analysis, config) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
let requestBody = {};
|
|
6
|
+
config.experimental === true
|
|
7
|
+
? (requestBody = sendToSCAServices(config, analysis))
|
|
8
|
+
: (requestBody = {
|
|
9
|
+
appID: config.applicationId,
|
|
10
|
+
cliVersion: APP_VERSION,
|
|
11
|
+
snapshot: analysis
|
|
12
|
+
});
|
|
10
13
|
const client = commonApi.getHttpClient(config);
|
|
11
14
|
return client
|
|
12
15
|
.sendSnapshot(requestBody, config)
|
|
@@ -22,6 +25,18 @@ const commonSendSnapShot = async (analysis, config) => {
|
|
|
22
25
|
throw err;
|
|
23
26
|
});
|
|
24
27
|
};
|
|
28
|
+
const sendToSCAServices = (config, analysis) => {
|
|
29
|
+
return {
|
|
30
|
+
applicationId: config.applicationId,
|
|
31
|
+
dependencyTree: analysis,
|
|
32
|
+
organizationId: config.organizationId,
|
|
33
|
+
language: config.language,
|
|
34
|
+
tool: {
|
|
35
|
+
name: 'Contrast Codesec',
|
|
36
|
+
version: APP_VERSION
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
};
|
|
25
40
|
module.exports = {
|
|
26
41
|
commonSendSnapShot
|
|
27
42
|
};
|
|
@@ -31,13 +31,25 @@ const readAndParseLockFile = lockFilePath => {
|
|
|
31
31
|
}
|
|
32
32
|
return lockFile;
|
|
33
33
|
};
|
|
34
|
+
const checkForCorrectFiles = languageFiles => {
|
|
35
|
+
if (!languageFiles.includes('packages.lock.json')) {
|
|
36
|
+
throw new Error(i18n.__('languageAnalysisHasNoLockFile', '.NET'));
|
|
37
|
+
}
|
|
38
|
+
if (!languageFiles.some(i => i.includes('.csproj'))) {
|
|
39
|
+
throw new Error(i18n.__('languageAnalysisProjectFileError', '.NET'));
|
|
40
|
+
}
|
|
41
|
+
};
|
|
34
42
|
const getDotNetDeps = (filePath, languageFiles) => {
|
|
35
|
-
|
|
36
|
-
const
|
|
43
|
+
checkForCorrectFiles(languageFiles);
|
|
44
|
+
const projectFileName = languageFiles.find(fileName => fileName.includes('.csproj'));
|
|
45
|
+
const lockFileName = languageFiles.find(fileName => fileName.includes('.json'));
|
|
46
|
+
const projectFile = readAndParseProjectFile(filePath + `/${projectFileName}`);
|
|
47
|
+
const lockFile = readAndParseLockFile(filePath + `/${lockFileName}`);
|
|
37
48
|
return { projectFile, lockFile };
|
|
38
49
|
};
|
|
39
50
|
module.exports = {
|
|
40
51
|
getDotNetDeps,
|
|
41
52
|
readAndParseProjectFile,
|
|
42
|
-
readAndParseLockFile
|
|
53
|
+
readAndParseLockFile,
|
|
54
|
+
checkForCorrectFiles
|
|
43
55
|
};
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const { createGoTSMessage } = require('../common/formatMessage');
|
|
3
|
+
const { parseDependenciesForSCAServices } = require('../common/scaParserForGoAndJava');
|
|
3
4
|
const goReadDepFile = require('./goReadDepFile');
|
|
4
5
|
const goParseDeps = require('./goParseDeps');
|
|
5
|
-
const goAnalysis =
|
|
6
|
+
const goAnalysis = config => {
|
|
6
7
|
try {
|
|
7
8
|
const rawGoDependencies = goReadDepFile.getGoDependencies(config);
|
|
8
9
|
const parsedGoDependencies = goParseDeps.parseGoDependencies(rawGoDependencies);
|
|
9
|
-
|
|
10
|
+
if (config.experimental) {
|
|
11
|
+
return parseDependenciesForSCAServices(parsedGoDependencies);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
return createGoTSMessage(parsedGoDependencies);
|
|
15
|
+
}
|
|
10
16
|
}
|
|
11
17
|
catch (e) {
|
|
12
18
|
console.log(e.message.toString());
|
|
@@ -5,17 +5,20 @@ const i18n = require('i18n');
|
|
|
5
5
|
const fs = require('fs');
|
|
6
6
|
const MAVEN = 'maven';
|
|
7
7
|
const GRADLE = 'gradle';
|
|
8
|
-
const determineProjectTypeAndCwd = (files,
|
|
8
|
+
const determineProjectTypeAndCwd = (files, config) => {
|
|
9
9
|
const projectData = {};
|
|
10
|
+
if (files.length > 1) {
|
|
11
|
+
files = files.filter(i => config.fileName.includes(i));
|
|
12
|
+
}
|
|
10
13
|
if (files[0].includes('pom.xml')) {
|
|
11
14
|
projectData.projectType = MAVEN;
|
|
12
15
|
}
|
|
13
16
|
else if (files[0].includes('build.gradle')) {
|
|
14
17
|
projectData.projectType = GRADLE;
|
|
15
18
|
}
|
|
16
|
-
projectData.cwd = file
|
|
17
|
-
? file.replace('pom.xml', '').replace('build.gradle', '')
|
|
18
|
-
: file;
|
|
19
|
+
projectData.cwd = config.file
|
|
20
|
+
? config.file.replace('pom.xml', '').replace('build.gradle', '')
|
|
21
|
+
: config.file;
|
|
19
22
|
return projectData;
|
|
20
23
|
};
|
|
21
24
|
const buildMaven = (config, projectData, timeout) => {
|
|
@@ -86,7 +89,7 @@ const getJavaBuildDeps = (config, files) => {
|
|
|
86
89
|
projectType: undefined
|
|
87
90
|
};
|
|
88
91
|
try {
|
|
89
|
-
const projectData = determineProjectTypeAndCwd(files, config
|
|
92
|
+
const projectData = determineProjectTypeAndCwd(files, config);
|
|
90
93
|
if (projectData.projectType === MAVEN) {
|
|
91
94
|
output.mvnDependancyTreeOutput = buildMaven(config, projectData, timeout);
|
|
92
95
|
}
|
|
@@ -101,5 +104,6 @@ const getJavaBuildDeps = (config, files) => {
|
|
|
101
104
|
}
|
|
102
105
|
};
|
|
103
106
|
module.exports = {
|
|
104
|
-
getJavaBuildDeps
|
|
107
|
+
getJavaBuildDeps,
|
|
108
|
+
determineProjectTypeAndCwd
|
|
105
109
|
};
|
|
@@ -2,12 +2,18 @@
|
|
|
2
2
|
const analysis = require('./analysis');
|
|
3
3
|
const { parseBuildDeps } = require('./javaBuildDepsParser');
|
|
4
4
|
const { createJavaTSMessage } = require('../common/formatMessage');
|
|
5
|
+
const { parseDependenciesForSCAServices } = require('../common/scaParserForGoAndJava');
|
|
5
6
|
const javaAnalysis = (config, languageFiles) => {
|
|
6
7
|
languageFiles.JAVA.forEach(file => {
|
|
7
8
|
file.replace('build.gradle.kts', 'build.gradle');
|
|
8
9
|
});
|
|
9
10
|
const javaDeps = buildJavaTree(config, languageFiles.JAVA);
|
|
10
|
-
|
|
11
|
+
if (config.experimental) {
|
|
12
|
+
return parseDependenciesForSCAServices(javaDeps);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
return createJavaTSMessage(javaDeps);
|
|
16
|
+
}
|
|
11
17
|
};
|
|
12
18
|
const buildJavaTree = (config, files) => {
|
|
13
19
|
const javaBuildDeps = analysis.getJavaBuildDeps(config, files);
|
|
@@ -14,13 +14,12 @@ const parseBuildDeps = (config, input) => {
|
|
|
14
14
|
const preParser = shavedOutput => {
|
|
15
15
|
let obj = [];
|
|
16
16
|
for (let dep in shavedOutput) {
|
|
17
|
+
shavedOutput[dep] = shaveDependencyType(shavedOutput[dep]);
|
|
17
18
|
obj.push(shavedOutput[dep]
|
|
18
19
|
.replace('+-', '+---')
|
|
19
20
|
.replace('[INFO]', '')
|
|
20
21
|
.replace('\\-', '\\---')
|
|
21
22
|
.replace(':jar:', ':')
|
|
22
|
-
.replace(':test', '')
|
|
23
|
-
.replace(':compile', '')
|
|
24
23
|
.replace(' +', '+')
|
|
25
24
|
.replace(' |', '|')
|
|
26
25
|
.replace(' \\', '\\')
|
|
@@ -50,6 +49,21 @@ const preParser = shavedOutput => {
|
|
|
50
49
|
}
|
|
51
50
|
return depTree;
|
|
52
51
|
};
|
|
52
|
+
const shaveDependencyType = dep => {
|
|
53
|
+
if (dep.endsWith('\r')) {
|
|
54
|
+
dep = dep.slice(0, -1);
|
|
55
|
+
}
|
|
56
|
+
if (dep.endsWith(':test')) {
|
|
57
|
+
dep = dep.slice(0, -5);
|
|
58
|
+
}
|
|
59
|
+
if (dep.endsWith(':compile')) {
|
|
60
|
+
dep = dep.slice(0, -8);
|
|
61
|
+
}
|
|
62
|
+
if (dep.endsWith(':provided')) {
|
|
63
|
+
dep = dep.slice(0, -9);
|
|
64
|
+
}
|
|
65
|
+
return dep;
|
|
66
|
+
};
|
|
53
67
|
const shaveOutput = (gradleDependencyTreeOutput, projectType) => {
|
|
54
68
|
let shavedOutput = gradleDependencyTreeOutput.split('\n');
|
|
55
69
|
if (projectType === 'maven') {
|
|
@@ -335,5 +349,7 @@ module.exports = {
|
|
|
335
349
|
computeRelationToLastElement,
|
|
336
350
|
addIndentation,
|
|
337
351
|
computeLevel,
|
|
338
|
-
computeIndentation
|
|
352
|
+
computeIndentation,
|
|
353
|
+
shaveDependencyType,
|
|
354
|
+
preParser
|
|
339
355
|
};
|
|
@@ -4,6 +4,9 @@ const i18n = require('i18n');
|
|
|
4
4
|
const formatMessage = require('../common/formatMessage');
|
|
5
5
|
const jsAnalysis = async (config, languageFiles) => {
|
|
6
6
|
checkForCorrectFiles(languageFiles);
|
|
7
|
+
if (!config.file.endsWith('/')) {
|
|
8
|
+
config.file = config.file.concat('/');
|
|
9
|
+
}
|
|
7
10
|
return buildNodeTree(config, languageFiles.JAVASCRIPT);
|
|
8
11
|
};
|
|
9
12
|
const buildNodeTree = async (config, files) => {
|
|
@@ -5,7 +5,7 @@ const _ = require('lodash');
|
|
|
5
5
|
const readFile = (config, nameOfFile) => {
|
|
6
6
|
if (config.file) {
|
|
7
7
|
try {
|
|
8
|
-
return fs.readFileSync(config.file + '/' + nameOfFile);
|
|
8
|
+
return fs.readFileSync(config.file + '/' + nameOfFile, 'utf8');
|
|
9
9
|
}
|
|
10
10
|
catch (error) {
|
|
11
11
|
console.log('Unable to find file');
|
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const { readFile, parseProjectFiles } = require('./analysis');
|
|
3
3
|
const { createPhpTSMessage } = require('../common/formatMessage');
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
const { parsePHPLockFileForScaServices } = require('./phpNewServicesMapper');
|
|
5
|
+
const phpAnalysis = config => {
|
|
6
|
+
let analysis = readFiles(config);
|
|
7
|
+
if (config.experimental) {
|
|
8
|
+
return parsePHPLockFileForScaServices(analysis.rawLockFileContents);
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
const phpDep = parseProjectFiles(analysis);
|
|
12
|
+
return createPhpTSMessage(phpDep);
|
|
13
|
+
}
|
|
8
14
|
};
|
|
9
|
-
const readFiles =
|
|
15
|
+
const readFiles = config => {
|
|
10
16
|
let php = {};
|
|
11
17
|
php.composerJSON = JSON.parse(readFile(config, 'composer.json'));
|
|
12
18
|
php.rawLockFileContents = JSON.parse(readFile(config, 'composer.lock'));
|
|
13
19
|
return php;
|
|
14
20
|
};
|
|
15
21
|
module.exports = {
|
|
16
|
-
phpAnalysis
|
|
22
|
+
phpAnalysis: phpAnalysis
|
|
17
23
|
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const { keyBy, merge } = require('lodash');
|
|
3
|
+
const parsePHPLockFileForScaServices = phpLockFile => {
|
|
4
|
+
const packages = keyBy(phpLockFile.packages, 'name');
|
|
5
|
+
const packagesDev = keyBy(phpLockFile['packages-dev'], 'name');
|
|
6
|
+
return merge(buildDepTree(packages, true), buildDepTree(packagesDev, false));
|
|
7
|
+
};
|
|
8
|
+
const buildDepTree = (packages, isProduction) => {
|
|
9
|
+
const dependencyTree = {};
|
|
10
|
+
for (const packagesKey in packages) {
|
|
11
|
+
const currentObj = packages[packagesKey];
|
|
12
|
+
const { group, name } = findGroupAndName(currentObj.name);
|
|
13
|
+
const key = `${group}/${name}@${currentObj.version}`;
|
|
14
|
+
dependencyTree[key] = {
|
|
15
|
+
group: group,
|
|
16
|
+
name: name,
|
|
17
|
+
version: currentObj.version,
|
|
18
|
+
directDependency: true,
|
|
19
|
+
isProduction: isProduction,
|
|
20
|
+
dependencies: []
|
|
21
|
+
};
|
|
22
|
+
const mergedChildDeps = merge(buildSubDepsIntoFlatStructure(currentObj.require), buildSubDepsIntoFlatStructure(currentObj['require-dev']));
|
|
23
|
+
for (const childKey in mergedChildDeps) {
|
|
24
|
+
const { group, name } = findGroupAndName(childKey);
|
|
25
|
+
const builtKey = `${group}/${name}`;
|
|
26
|
+
dependencyTree[builtKey] = mergedChildDeps[childKey];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return dependencyTree;
|
|
30
|
+
};
|
|
31
|
+
const buildSubDepsIntoFlatStructure = childDeps => {
|
|
32
|
+
const dependencyTree = {};
|
|
33
|
+
for (const dep in childDeps) {
|
|
34
|
+
const version = childDeps[dep];
|
|
35
|
+
const { group, name } = findGroupAndName(dep);
|
|
36
|
+
const key = `${group}/${name}`;
|
|
37
|
+
dependencyTree[key] = {
|
|
38
|
+
group: group,
|
|
39
|
+
name: name,
|
|
40
|
+
version: version,
|
|
41
|
+
directDependency: false,
|
|
42
|
+
isProduction: false,
|
|
43
|
+
dependencies: []
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return dependencyTree;
|
|
47
|
+
};
|
|
48
|
+
const findGroupAndName = groupAndName => {
|
|
49
|
+
if (groupAndName.includes('/')) {
|
|
50
|
+
const groupName = groupAndName.split('/');
|
|
51
|
+
return { group: groupName[0], name: groupName[1] };
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
return { group: groupAndName, name: groupAndName };
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
module.exports = {
|
|
58
|
+
parsePHPLockFileForScaServices,
|
|
59
|
+
buildDepTree,
|
|
60
|
+
buildSubDepsIntoFlatStructure,
|
|
61
|
+
findGroupAndName
|
|
62
|
+
};
|