@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
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const i18n = require('i18n')
|
|
2
|
+
|
|
3
|
+
const processFail = (config, reportResults) => {
|
|
4
|
+
if (config.severity !== undefined) {
|
|
5
|
+
if (
|
|
6
|
+
reportResults[config.severity] !== undefined &&
|
|
7
|
+
isSeverityViolation(config.severity, reportResults)
|
|
8
|
+
) {
|
|
9
|
+
failPipeline('failSeverityOptionErrorMessage')
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (config.severity === undefined && reportResults.total > 0) {
|
|
14
|
+
failPipeline('failThresholdOptionErrorMessage')
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const isSeverityViolation = (severity, reportResults) => {
|
|
19
|
+
let count = 0
|
|
20
|
+
switch (severity) {
|
|
21
|
+
case 'critical':
|
|
22
|
+
count += reportResults.critical
|
|
23
|
+
break
|
|
24
|
+
case 'high':
|
|
25
|
+
count += reportResults.high + reportResults.critical
|
|
26
|
+
break
|
|
27
|
+
case 'medium':
|
|
28
|
+
count += reportResults.medium + reportResults.low + reportResults.critical
|
|
29
|
+
break
|
|
30
|
+
case 'low':
|
|
31
|
+
count +=
|
|
32
|
+
reportResults.high + reportResults.critical + reportResults.medium
|
|
33
|
+
break
|
|
34
|
+
case 'note':
|
|
35
|
+
if (reportResults.note == reportResults.total) {
|
|
36
|
+
count = 0
|
|
37
|
+
} else {
|
|
38
|
+
count = reportResults.total
|
|
39
|
+
}
|
|
40
|
+
break
|
|
41
|
+
default:
|
|
42
|
+
count = 0
|
|
43
|
+
}
|
|
44
|
+
return count > 0
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const failPipeline = (message = '') => {
|
|
48
|
+
console.log(
|
|
49
|
+
'\n ******************************** ' +
|
|
50
|
+
i18n.__('snapshotFailureHeader') +
|
|
51
|
+
' *********************************\n' +
|
|
52
|
+
i18n.__(message)
|
|
53
|
+
)
|
|
54
|
+
process.exit(1)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const parseSeverity = severity => {
|
|
58
|
+
const severities = ['NOTE', 'LOW', 'MEDIUM', 'HIGH', 'CRITICAL']
|
|
59
|
+
if (severities.includes(severity.toUpperCase())) {
|
|
60
|
+
return severity.toLowerCase()
|
|
61
|
+
} else {
|
|
62
|
+
console.log(
|
|
63
|
+
severity +
|
|
64
|
+
' Not recognised as a severity type please use LOW, MEDIUM, HIGH, CRITICAL, NOTE'
|
|
65
|
+
)
|
|
66
|
+
return undefined
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = {
|
|
71
|
+
failPipeline,
|
|
72
|
+
processFail,
|
|
73
|
+
isSeverityViolation,
|
|
74
|
+
parseSeverity
|
|
75
|
+
}
|
|
@@ -18,11 +18,11 @@ const getLatestVersion = async (config: any) => {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
// @ts-ignore
|
|
22
21
|
export async function findLatestCLIVersion(config: ContrastConf) {
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
const isCI = process.env.CONTRAST_CODESEC_CI
|
|
23
|
+
? JSON.parse(process.env.CONTRAST_CODESEC_CI)
|
|
24
|
+
: false
|
|
25
|
+
if (!isCI) {
|
|
26
26
|
let latestCLIVersion: string = await getLatestVersion(config)
|
|
27
27
|
//strip key
|
|
28
28
|
latestCLIVersion = latestCLIVersion.substring(8)
|
|
@@ -14,7 +14,7 @@ const HIGH = 'HIGH'
|
|
|
14
14
|
const CRITICAL = 'CRITICAL'
|
|
15
15
|
// App
|
|
16
16
|
const APP_NAME = 'contrast'
|
|
17
|
-
const APP_VERSION = '1.0.
|
|
17
|
+
const APP_VERSION = '1.0.12'
|
|
18
18
|
const TIMEOUT = 120000
|
|
19
19
|
const HIGH_COLOUR = '#ff9900'
|
|
20
20
|
const CRITICAL_COLOUR = '#e35858'
|
|
@@ -32,7 +32,7 @@ const AUTH_CALLBACK_URL = 'https://cli-auth-api.contrastsecurity.com'
|
|
|
32
32
|
const SARIF_FILE = 'SARIF'
|
|
33
33
|
const SBOM_CYCLONE_DX_FILE = 'cyclonedx'
|
|
34
34
|
const SBOM_SPDX_FILE = 'spdx'
|
|
35
|
-
const CE_URL = 'https://ce.contrastsecurity.com
|
|
35
|
+
const CE_URL = 'https://ce.contrastsecurity.com'
|
|
36
36
|
|
|
37
37
|
module.exports = {
|
|
38
38
|
supportedLanguages: { NODE, DOTNET, JAVA, RUBY, PYTHON, GO, PHP, JAVASCRIPT },
|
package/src/constants/locales.js
CHANGED
|
@@ -20,8 +20,8 @@ const en_locales = () => {
|
|
|
20
20
|
libraryAnalysisError:
|
|
21
21
|
'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',
|
|
22
22
|
yamlMissingParametersHeader: 'Missing Parameters',
|
|
23
|
-
|
|
24
|
-
'
|
|
23
|
+
genericErrorMessage:
|
|
24
|
+
'An error has occur please check your command again. For more information use the --help commands.',
|
|
25
25
|
unauthenticatedErrorHeader: '401 error - Unauthenticated',
|
|
26
26
|
unauthenticatedErrorMessage:
|
|
27
27
|
'Please check the following keys are correct:\n--organization-id, --api-key or --authorization',
|
|
@@ -67,7 +67,7 @@ const en_locales = () => {
|
|
|
67
67
|
'Failed to get information about the file or directory @ %s because: ',
|
|
68
68
|
languageAnalysisFailure: ' analysis failed because: ',
|
|
69
69
|
languageAnalysisNoLanguage:
|
|
70
|
-
'We cannot detect a project, use
|
|
70
|
+
'We cannot detect a project, use -f <path> to specify a file or folder to analyze.',
|
|
71
71
|
languageAnalysisNoLanguageHelpLine: `${chalk.bold(
|
|
72
72
|
'contrast audit --help'
|
|
73
73
|
)} for more information.`,
|
|
@@ -121,9 +121,11 @@ const en_locales = () => {
|
|
|
121
121
|
'The name of the application cataloged by Contrast UI',
|
|
122
122
|
constantsCatalogueApplication:
|
|
123
123
|
'Provide this if you want to catalogue an application',
|
|
124
|
+
failOptionErrorMessage:
|
|
125
|
+
' FAIL - CVEs have been detected that match at least the cve_severity option specified.',
|
|
124
126
|
constantsLanguage:
|
|
125
127
|
'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',
|
|
126
|
-
constantsFilePath: `
|
|
128
|
+
constantsFilePath: `Specify a directory or the file where dependencies are declared. (By default, CodeSec will search for project files in the current directory.)`,
|
|
127
129
|
constantsSilent: 'Silences JSON output.',
|
|
128
130
|
constantsAppGroups:
|
|
129
131
|
'Assign your application to one or more pre-existing groups when using the catalogue command. Group lists should be comma separated.',
|
|
@@ -142,16 +144,22 @@ const en_locales = () => {
|
|
|
142
144
|
constantsReport: 'Display vulnerability information for this application',
|
|
143
145
|
constantsFail:
|
|
144
146
|
'Set the process to fail if this option is set in combination with --cve_severity.',
|
|
145
|
-
|
|
146
|
-
|
|
147
|
+
failThresholdOptionErrorMessage: 'More than 0 vulnerabilities found',
|
|
148
|
+
failSeverityOptionErrorMessage:
|
|
149
|
+
' FAIL - Results detected vulnerabilities over accepted severity level',
|
|
147
150
|
constantsSeverity:
|
|
148
151
|
'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.',
|
|
149
152
|
constantsCount: 'The number of CVEs that must be exceeded to fail a build',
|
|
150
153
|
constantsHeader: 'CodeSec by Contrast Security',
|
|
154
|
+
configHeader2: 'Config options',
|
|
155
|
+
clearHeader: '-c, --clear',
|
|
156
|
+
clearContent: 'Removes stored credentials',
|
|
151
157
|
constantsPrerequisitesContentScanLanguages:
|
|
152
158
|
'Java, Javascript and .NET supported',
|
|
153
159
|
constantsContrastContent:
|
|
154
|
-
|
|
160
|
+
'Use the ‘contrast’ command for fast and accurate security analysis of your applications, APIs, serverless functions, and libraries.',
|
|
161
|
+
constantsContrastCategories:
|
|
162
|
+
'\n Code: Java, .NET, .NET Core, JavaScript\n Serverless: AWS Lambda - Java, Python\n Libraries: Java, .NET, Node, Ruby, Python, Go, PHP\n',
|
|
155
163
|
constantsUsageGuideContentRecommendation:
|
|
156
164
|
'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.',
|
|
157
165
|
constantsPrerequisitesHeader: 'Pre-requisites',
|
|
@@ -282,12 +290,17 @@ const en_locales = () => {
|
|
|
282
290
|
'We only accept the following file types: \nJava - .jar, .war \nJavaScript - .js or .zip files',
|
|
283
291
|
helpAuthSummary:
|
|
284
292
|
'Authenticate Contrast using your Github or Google account',
|
|
285
|
-
|
|
286
|
-
|
|
293
|
+
helpAuditSummary:
|
|
294
|
+
'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).]',
|
|
295
|
+
helpScanSummary:
|
|
296
|
+
'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]',
|
|
297
|
+
helpLambdaSummary:
|
|
298
|
+
'Performs a static security scan on an AWS lambda function. lambda --help (for options)',
|
|
287
299
|
helpVersionSummary: 'Displays version of Contrast CLI',
|
|
288
300
|
helpConfigSummary: 'Displays stored credentials',
|
|
289
301
|
helpSummary: 'Displays usage guide',
|
|
290
302
|
authName: 'auth',
|
|
303
|
+
auditName: 'audit',
|
|
291
304
|
scanName: 'scan',
|
|
292
305
|
lambdaName: 'lambda',
|
|
293
306
|
versionName: 'version',
|
|
@@ -305,8 +318,7 @@ const en_locales = () => {
|
|
|
305
318
|
scanOptionsVerboseSummary: ' Returns extended information to the terminal.',
|
|
306
319
|
authSuccessMessage: 'Authentication successful',
|
|
307
320
|
runAuthSuccessMessage:
|
|
308
|
-
"Now you can use Contrast
|
|
309
|
-
"or 'contrast help' to learn more about the capabilities.",
|
|
321
|
+
"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.",
|
|
310
322
|
authWaitingMessage: 'Waiting for auth...',
|
|
311
323
|
authTimedOutMessage: 'Auth Timed out, try again',
|
|
312
324
|
zipErrorScan:
|
|
@@ -334,7 +346,7 @@ const en_locales = () => {
|
|
|
334
346
|
'Supported runtimes: Java & Python',
|
|
335
347
|
lambdaPrerequisitesContentLambdaDescriptionTitle: 'AWS Requirements\n',
|
|
336
348
|
lambdaPrerequisitesContentLambdaDescription:
|
|
337
|
-
'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
|
|
349
|
+
'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',
|
|
338
350
|
scanFileNameOption: '-f, --file',
|
|
339
351
|
lambdaFunctionNameOption: '-f, --function-name',
|
|
340
352
|
lambdaListFunctionsOption: '-l, --list-functions',
|
|
@@ -405,7 +417,8 @@ const en_locales = () => {
|
|
|
405
417
|
auditOptionsSaveDescription:
|
|
406
418
|
'Generate and save an SBOM (Software Bill of Materials)\n',
|
|
407
419
|
auditOptionsSaveOptionsDescription:
|
|
408
|
-
'Valid options are: spdx
|
|
420
|
+
'Valid options are: --save spdx and --save cyclonedx (CycloneDX is the default format.)',
|
|
421
|
+
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.`,
|
|
409
422
|
scanNotCompleted:
|
|
410
423
|
'Scan not completed. Check for framework and language support here: %s',
|
|
411
424
|
auditNotCompleted: 'audit not completed. Please try again',
|
|
@@ -428,6 +441,15 @@ const en_locales = () => {
|
|
|
428
441
|
auditReportFailureMessage: 'Unable to generate library report',
|
|
429
442
|
auditSCAAnalysisBegins: 'Contrast SCA audit started',
|
|
430
443
|
auditSCAAnalysisComplete: 'Contrast audit complete',
|
|
444
|
+
commonHelpHeader: 'Need More Help?',
|
|
445
|
+
commonHelpCheckOutHeader: chalk.hex('#9DC184')('Check out:'),
|
|
446
|
+
commonHelpCheckOutText: ' https://support.contrastsecurity.com',
|
|
447
|
+
commonHelpLearnMoreHeader: chalk.hex('#9DC184')('Learn more at:'),
|
|
448
|
+
commonHelpLearnMoreText: ' https://developer.contrastsecurity.com',
|
|
449
|
+
commonHelpJoinDiscussionHeader: chalk.hex('#9DC184')(
|
|
450
|
+
'Join the discussion:'
|
|
451
|
+
),
|
|
452
|
+
commonHelpJoinDiscussionText: ' https://dev.to/codesec',
|
|
431
453
|
...lambda
|
|
432
454
|
}
|
|
433
455
|
}
|
package/src/constants.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const commandLineUsage = require('command-line-usage')
|
|
2
2
|
const i18n = require('i18n')
|
|
3
3
|
const { en_locales } = require('./constants/locales.js')
|
|
4
|
+
const { parseSeverity } = require('./common/fail')
|
|
5
|
+
const { commonHelpLinks } = require('./common/commonHelp')
|
|
4
6
|
|
|
5
7
|
i18n.configure({
|
|
6
8
|
staticCatalog: {
|
|
@@ -106,6 +108,24 @@ const scanOptionDefinitions = [
|
|
|
106
108
|
'}: ' +
|
|
107
109
|
i18n.__('constantsProxyServer')
|
|
108
110
|
},
|
|
111
|
+
{
|
|
112
|
+
name: 'fail',
|
|
113
|
+
type: Boolean,
|
|
114
|
+
description:
|
|
115
|
+
'{bold ' +
|
|
116
|
+
i18n.__('constantsOptional') +
|
|
117
|
+
'}: ' +
|
|
118
|
+
i18n.__('failOptionErrorMessage')
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: 'severity',
|
|
122
|
+
type: severity => parseSeverity(severity),
|
|
123
|
+
description:
|
|
124
|
+
'{bold ' +
|
|
125
|
+
i18n.__('constantsOptional') +
|
|
126
|
+
'}: ' +
|
|
127
|
+
i18n.__('constantsSeverity')
|
|
128
|
+
},
|
|
109
129
|
{
|
|
110
130
|
name: 'ff',
|
|
111
131
|
type: Boolean,
|
|
@@ -213,13 +233,31 @@ const auditOptionDefinitions = [
|
|
|
213
233
|
{
|
|
214
234
|
name: 'file',
|
|
215
235
|
alias: 'f',
|
|
216
|
-
defaultValue: process.cwd(),
|
|
236
|
+
defaultValue: process.cwd().concat('/'),
|
|
217
237
|
description:
|
|
218
238
|
'{bold ' +
|
|
219
239
|
i18n.__('constantsOptional') +
|
|
220
240
|
'}: ' +
|
|
221
241
|
i18n.__('constantsFilePath')
|
|
222
242
|
},
|
|
243
|
+
{
|
|
244
|
+
name: 'fail',
|
|
245
|
+
type: Boolean,
|
|
246
|
+
description:
|
|
247
|
+
'{bold ' +
|
|
248
|
+
i18n.__('constantsOptional') +
|
|
249
|
+
'}: ' +
|
|
250
|
+
i18n.__('failOptionErrorMessage')
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
name: 'severity',
|
|
254
|
+
type: severity => parseSeverity(severity),
|
|
255
|
+
description:
|
|
256
|
+
'{bold ' +
|
|
257
|
+
i18n.__('constantsOptional') +
|
|
258
|
+
'}: ' +
|
|
259
|
+
i18n.__('constantsSeverity')
|
|
260
|
+
},
|
|
223
261
|
{
|
|
224
262
|
name: 'app-groups',
|
|
225
263
|
description:
|
|
@@ -257,6 +295,7 @@ const auditOptionDefinitions = [
|
|
|
257
295
|
{
|
|
258
296
|
name: 'ignore-dev',
|
|
259
297
|
type: Boolean,
|
|
298
|
+
alias: 'i',
|
|
260
299
|
description:
|
|
261
300
|
'{bold ' +
|
|
262
301
|
i18n.__('constantsOptional') +
|
|
@@ -293,7 +332,6 @@ const auditOptionDefinitions = [
|
|
|
293
332
|
},
|
|
294
333
|
{
|
|
295
334
|
name: 'host',
|
|
296
|
-
alias: 'h',
|
|
297
335
|
description:
|
|
298
336
|
'{bold ' +
|
|
299
337
|
i18n.__('constantsRequired') +
|
|
@@ -341,13 +379,21 @@ const auditOptionDefinitions = [
|
|
|
341
379
|
i18n.__('constantsOptional') +
|
|
342
380
|
'}: ' +
|
|
343
381
|
i18n.__('scanOptionsTimeoutSummary')
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
name: 'help',
|
|
385
|
+
alias: 'h',
|
|
386
|
+
type: Boolean
|
|
344
387
|
}
|
|
345
388
|
]
|
|
346
389
|
|
|
347
390
|
const mainUsageGuide = commandLineUsage([
|
|
348
391
|
{
|
|
349
392
|
header: i18n.__('constantsHeader'),
|
|
350
|
-
content: [
|
|
393
|
+
content: [
|
|
394
|
+
i18n.__('constantsContrastContent'),
|
|
395
|
+
i18n.__('constantsContrastCategories')
|
|
396
|
+
]
|
|
351
397
|
},
|
|
352
398
|
{
|
|
353
399
|
header: i18n.__('constantsUsage'),
|
|
@@ -359,15 +405,19 @@ const mainUsageGuide = commandLineUsage([
|
|
|
359
405
|
{ name: i18n.__('authName'), summary: i18n.__('helpAuthSummary') },
|
|
360
406
|
{ name: i18n.__('scanName'), summary: i18n.__('helpScanSummary') },
|
|
361
407
|
{ name: i18n.__('lambdaName'), summary: i18n.__('helpLambdaSummary') },
|
|
408
|
+
{ name: i18n.__('auditName'), summary: i18n.__('helpAuditSummary') },
|
|
362
409
|
{ name: i18n.__('versionName'), summary: i18n.__('helpVersionSummary') },
|
|
363
410
|
{ name: i18n.__('configName'), summary: i18n.__('helpConfigSummary') },
|
|
364
411
|
{ name: i18n.__('helpName'), summary: i18n.__('helpSummary') }
|
|
365
412
|
]
|
|
366
413
|
},
|
|
367
414
|
{
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
415
|
+
header: i18n.__('configHeader2'),
|
|
416
|
+
content: [
|
|
417
|
+
{ name: i18n.__('clearHeader'), summary: i18n.__('clearContent') }
|
|
418
|
+
]
|
|
419
|
+
},
|
|
420
|
+
commonHelpLinks()
|
|
371
421
|
])
|
|
372
422
|
|
|
373
423
|
const mainDefinition = [{ name: 'command', defaultOption: true }]
|
package/src/index.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
isCorrectNodeVersion
|
|
15
15
|
} from './common/versionChecker'
|
|
16
16
|
import { findCommandOnError } from './common/errorHandling'
|
|
17
|
+
import { sendTelemetryConfigAsConfObj } from './telemetry/telemetry'
|
|
17
18
|
|
|
18
19
|
const {
|
|
19
20
|
commandLineDefinitions: { mainUsageGuide, mainDefinition }
|
|
@@ -75,11 +76,11 @@ const start = async () => {
|
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
if (command === 'scan') {
|
|
78
|
-
return await processScan(argvMain)
|
|
79
|
+
return await processScan(config, argvMain)
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
if (command === 'audit') {
|
|
82
|
-
return await processAudit(argvMain)
|
|
83
|
+
return await processAudit(config, argvMain)
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
if (
|
|
@@ -98,10 +99,24 @@ const start = async () => {
|
|
|
98
99
|
: console.log(
|
|
99
100
|
`Unknown Command: ${command} \nUse --help for the full list`
|
|
100
101
|
)
|
|
102
|
+
await sendTelemetryConfigAsConfObj(
|
|
103
|
+
config,
|
|
104
|
+
command,
|
|
105
|
+
argvMain,
|
|
106
|
+
'FAILURE',
|
|
107
|
+
'undefined'
|
|
108
|
+
)
|
|
101
109
|
} else {
|
|
102
110
|
console.log(
|
|
103
111
|
`Unknown Command: ${command} \nUse --help for the full list`
|
|
104
112
|
)
|
|
113
|
+
await sendTelemetryConfigAsConfObj(
|
|
114
|
+
config,
|
|
115
|
+
command,
|
|
116
|
+
argvMain,
|
|
117
|
+
'FAILURE',
|
|
118
|
+
'undefined'
|
|
119
|
+
)
|
|
105
120
|
}
|
|
106
121
|
process.exit(9)
|
|
107
122
|
} else {
|
package/src/lambda/help.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import commandLineUsage from 'command-line-usage'
|
|
2
2
|
import i18n from 'i18n'
|
|
3
|
+
import { commonHelpLinks } from '../common/commonHelp'
|
|
3
4
|
|
|
4
5
|
const lambdaUsageGuide = commandLineUsage([
|
|
5
6
|
{
|
|
@@ -80,9 +81,7 @@ const lambdaUsageGuide = commandLineUsage([
|
|
|
80
81
|
{ name: i18n.__('lambdaHelpOption'), summary: i18n.__('helpSummary') }
|
|
81
82
|
]
|
|
82
83
|
},
|
|
83
|
-
|
|
84
|
-
content: '{underline https://www.contrastsecurity.com/developer/codesec}'
|
|
85
|
-
}
|
|
84
|
+
commonHelpLinks()
|
|
86
85
|
])
|
|
87
86
|
|
|
88
87
|
export { lambdaUsageGuide }
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const parseDependenciesForSCAServices = dependencyTreeObject => {
|
|
2
|
+
let parsedDependencyTree = {}
|
|
3
|
+
let subDeps
|
|
4
|
+
|
|
5
|
+
for (let tree in dependencyTreeObject) {
|
|
6
|
+
let unParsedDependencyTree = dependencyTreeObject[tree]
|
|
7
|
+
for (let dependency in unParsedDependencyTree) {
|
|
8
|
+
subDeps = parseSubDependencies(unParsedDependencyTree[dependency].edges)
|
|
9
|
+
|
|
10
|
+
let parsedDependency = {
|
|
11
|
+
name: unParsedDependencyTree[dependency].artifactID,
|
|
12
|
+
group: unParsedDependencyTree[dependency].group,
|
|
13
|
+
version: unParsedDependencyTree[dependency].version,
|
|
14
|
+
directDependency: unParsedDependencyTree[dependency].type === 'direct',
|
|
15
|
+
isProduction: true,
|
|
16
|
+
dependencies: subDeps
|
|
17
|
+
}
|
|
18
|
+
parsedDependencyTree[dependency] = parsedDependency
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return parsedDependencyTree
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const parseSubDependencies = dependencies => {
|
|
25
|
+
// converting:
|
|
26
|
+
// dependencies: {
|
|
27
|
+
// 'gopkg.in/check.v1@v0.0.0-2': 'gopkg.in/check.v1@v0.0.0-2'
|
|
28
|
+
// }
|
|
29
|
+
// to:
|
|
30
|
+
// dependencies: [ 'gopkg.in/check.v1@v0.0.0-2' ]
|
|
31
|
+
let subDeps = []
|
|
32
|
+
for (let x in dependencies) {
|
|
33
|
+
subDeps.push(dependencies[x])
|
|
34
|
+
}
|
|
35
|
+
return subDeps
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = {
|
|
39
|
+
parseDependenciesForSCAServices,
|
|
40
|
+
parseSubDependencies
|
|
41
|
+
}
|
|
@@ -2,11 +2,14 @@ const commonApi = require('../../utils/commonApi')
|
|
|
2
2
|
const { APP_VERSION } = require('../../constants/constants')
|
|
3
3
|
|
|
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
|
|
|
11
14
|
const client = commonApi.getHttpClient(config)
|
|
12
15
|
return client
|
|
@@ -23,6 +26,19 @@ const commonSendSnapShot = async (analysis, config) => {
|
|
|
23
26
|
})
|
|
24
27
|
}
|
|
25
28
|
|
|
29
|
+
const sendToSCAServices = (config, analysis) => {
|
|
30
|
+
return {
|
|
31
|
+
applicationId: config.applicationId,
|
|
32
|
+
dependencyTree: analysis,
|
|
33
|
+
organizationId: config.organizationId,
|
|
34
|
+
language: config.language,
|
|
35
|
+
tool: {
|
|
36
|
+
name: 'Contrast Codesec',
|
|
37
|
+
version: APP_VERSION
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
26
42
|
module.exports = {
|
|
27
43
|
commonSendSnapShot
|
|
28
44
|
}
|
|
@@ -40,9 +40,26 @@ const readAndParseLockFile = lockFilePath => {
|
|
|
40
40
|
return lockFile
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
const checkForCorrectFiles = languageFiles => {
|
|
44
|
+
if (!languageFiles.includes('packages.lock.json')) {
|
|
45
|
+
throw new Error(i18n.__('languageAnalysisHasNoLockFile', '.NET'))
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (!languageFiles.some(i => i.includes('.csproj'))) {
|
|
49
|
+
throw new Error(i18n.__('languageAnalysisProjectFileError', '.NET'))
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
43
53
|
const getDotNetDeps = (filePath, languageFiles) => {
|
|
44
|
-
|
|
45
|
-
const
|
|
54
|
+
checkForCorrectFiles(languageFiles)
|
|
55
|
+
const projectFileName = languageFiles.find(fileName =>
|
|
56
|
+
fileName.includes('.csproj')
|
|
57
|
+
)
|
|
58
|
+
const lockFileName = languageFiles.find(fileName =>
|
|
59
|
+
fileName.includes('.json')
|
|
60
|
+
)
|
|
61
|
+
const projectFile = readAndParseProjectFile(filePath + `/${projectFileName}`)
|
|
62
|
+
const lockFile = readAndParseLockFile(filePath + `/${lockFileName}`)
|
|
46
63
|
|
|
47
64
|
return { projectFile, lockFile }
|
|
48
65
|
}
|
|
@@ -50,5 +67,6 @@ const getDotNetDeps = (filePath, languageFiles) => {
|
|
|
50
67
|
module.exports = {
|
|
51
68
|
getDotNetDeps,
|
|
52
69
|
readAndParseProjectFile,
|
|
53
|
-
readAndParseLockFile
|
|
70
|
+
readAndParseLockFile,
|
|
71
|
+
checkForCorrectFiles
|
|
54
72
|
}
|
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
const { createGoTSMessage } = require('../common/formatMessage')
|
|
2
|
+
const {
|
|
3
|
+
parseDependenciesForSCAServices
|
|
4
|
+
} = require('../common/scaParserForGoAndJava')
|
|
2
5
|
const goReadDepFile = require('./goReadDepFile')
|
|
3
6
|
const goParseDeps = require('./goParseDeps')
|
|
4
7
|
|
|
5
|
-
const goAnalysis =
|
|
8
|
+
const goAnalysis = config => {
|
|
6
9
|
try {
|
|
7
10
|
const rawGoDependencies = goReadDepFile.getGoDependencies(config)
|
|
8
11
|
const parsedGoDependencies =
|
|
9
12
|
goParseDeps.parseGoDependencies(rawGoDependencies)
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
if (config.experimental) {
|
|
15
|
+
return parseDependenciesForSCAServices(parsedGoDependencies)
|
|
16
|
+
} else {
|
|
17
|
+
return createGoTSMessage(parsedGoDependencies)
|
|
18
|
+
}
|
|
12
19
|
} catch (e) {
|
|
13
20
|
console.log(e.message.toString())
|
|
14
21
|
}
|
|
@@ -6,9 +6,13 @@ const fs = require('fs')
|
|
|
6
6
|
const MAVEN = 'maven'
|
|
7
7
|
const GRADLE = 'gradle'
|
|
8
8
|
|
|
9
|
-
const determineProjectTypeAndCwd = (files,
|
|
9
|
+
const determineProjectTypeAndCwd = (files, config) => {
|
|
10
10
|
const projectData = {}
|
|
11
11
|
|
|
12
|
+
if (files.length > 1) {
|
|
13
|
+
files = files.filter(i => config.fileName.includes(i))
|
|
14
|
+
}
|
|
15
|
+
|
|
12
16
|
if (files[0].includes('pom.xml')) {
|
|
13
17
|
projectData.projectType = MAVEN
|
|
14
18
|
} else if (files[0].includes('build.gradle')) {
|
|
@@ -16,9 +20,9 @@ const determineProjectTypeAndCwd = (files, file) => {
|
|
|
16
20
|
}
|
|
17
21
|
|
|
18
22
|
//clean up the path to be a folder not a file
|
|
19
|
-
projectData.cwd = file
|
|
20
|
-
? file.replace('pom.xml', '').replace('build.gradle', '')
|
|
21
|
-
: file
|
|
23
|
+
projectData.cwd = config.file
|
|
24
|
+
? config.file.replace('pom.xml', '').replace('build.gradle', '')
|
|
25
|
+
: config.file
|
|
22
26
|
|
|
23
27
|
return projectData
|
|
24
28
|
}
|
|
@@ -124,7 +128,7 @@ const getJavaBuildDeps = (config, files) => {
|
|
|
124
128
|
}
|
|
125
129
|
|
|
126
130
|
try {
|
|
127
|
-
const projectData = determineProjectTypeAndCwd(files, config
|
|
131
|
+
const projectData = determineProjectTypeAndCwd(files, config)
|
|
128
132
|
if (projectData.projectType === MAVEN) {
|
|
129
133
|
output.mvnDependancyTreeOutput = buildMaven(config, projectData, timeout)
|
|
130
134
|
} else if (projectData.projectType === GRADLE) {
|
|
@@ -138,5 +142,6 @@ const getJavaBuildDeps = (config, files) => {
|
|
|
138
142
|
}
|
|
139
143
|
|
|
140
144
|
module.exports = {
|
|
141
|
-
getJavaBuildDeps
|
|
145
|
+
getJavaBuildDeps,
|
|
146
|
+
determineProjectTypeAndCwd
|
|
142
147
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
const analysis = require('./analysis')
|
|
2
2
|
const { parseBuildDeps } = require('./javaBuildDepsParser')
|
|
3
3
|
const { createJavaTSMessage } = require('../common/formatMessage')
|
|
4
|
+
const {
|
|
5
|
+
parseDependenciesForSCAServices
|
|
6
|
+
} = require('../common/scaParserForGoAndJava')
|
|
4
7
|
|
|
5
8
|
const javaAnalysis = (config, languageFiles) => {
|
|
6
9
|
languageFiles.JAVA.forEach(file => {
|
|
@@ -8,7 +11,12 @@ const javaAnalysis = (config, languageFiles) => {
|
|
|
8
11
|
})
|
|
9
12
|
|
|
10
13
|
const javaDeps = buildJavaTree(config, languageFiles.JAVA)
|
|
11
|
-
|
|
14
|
+
|
|
15
|
+
if (config.experimental) {
|
|
16
|
+
return parseDependenciesForSCAServices(javaDeps)
|
|
17
|
+
} else {
|
|
18
|
+
return createJavaTSMessage(javaDeps)
|
|
19
|
+
}
|
|
12
20
|
}
|
|
13
21
|
|
|
14
22
|
const buildJavaTree = (config, files) => {
|