@contrast/contrast 1.0.8 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/dist/audit/languageAnalysisEngine/getProjectRootFilenames.js +3 -12
  2. package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +88 -53
  3. package/dist/audit/languageAnalysisEngine/report/models/reportOutputModel.js +4 -3
  4. package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +58 -11
  5. package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +38 -5
  6. package/dist/audit/languageAnalysisEngine/sendSnapshot.js +6 -30
  7. package/dist/audit/save.js +21 -13
  8. package/dist/commands/audit/auditConfig.js +0 -16
  9. package/dist/commands/audit/auditController.js +1 -10
  10. package/dist/commands/audit/help.js +7 -24
  11. package/dist/commands/audit/processAudit.js +1 -7
  12. package/dist/commands/audit/saveFile.js +2 -2
  13. package/dist/commands/scan/sca/scaAnalysis.js +22 -9
  14. package/dist/common/HTTPClient.js +8 -8
  15. package/dist/constants/constants.js +7 -2
  16. package/dist/constants/locales.js +24 -30
  17. package/dist/constants.js +11 -9
  18. package/dist/index.js +54 -45
  19. package/dist/lambda/lambda.js +5 -2
  20. package/dist/sbom/generateSbom.js +2 -2
  21. package/dist/scaAnalysis/common/formatMessage.js +7 -1
  22. package/dist/scaAnalysis/common/treeUpload.js +4 -5
  23. package/dist/scaAnalysis/dotnet/analysis.js +43 -0
  24. package/dist/scaAnalysis/dotnet/index.js +10 -0
  25. package/dist/scaAnalysis/javascript/analysis.js +4 -7
  26. package/dist/scaAnalysis/javascript/index.js +14 -5
  27. package/dist/scaAnalysis/php/analysis.js +14 -33
  28. package/dist/scaAnalysis/php/index.js +11 -4
  29. package/dist/scaAnalysis/ruby/analysis.js +2 -10
  30. package/dist/scan/autoDetection.js +18 -21
  31. package/dist/scan/fileUtils.js +31 -12
  32. package/dist/scan/formatScanOutput.js +3 -3
  33. package/dist/scan/scanConfig.js +2 -2
  34. package/dist/utils/getConfig.js +1 -6
  35. package/package.json +2 -3
  36. package/src/audit/languageAnalysisEngine/getProjectRootFilenames.js +3 -32
  37. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +128 -68
  38. package/src/audit/languageAnalysisEngine/report/models/reportOutputModel.ts +11 -5
  39. package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +41 -19
  40. package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +43 -4
  41. package/src/audit/languageAnalysisEngine/sendSnapshot.js +6 -32
  42. package/src/audit/save.js +32 -16
  43. package/src/commands/audit/auditConfig.ts +0 -25
  44. package/src/commands/audit/auditController.ts +0 -11
  45. package/src/commands/audit/help.ts +7 -24
  46. package/src/commands/audit/processAudit.ts +1 -7
  47. package/src/commands/audit/saveFile.ts +2 -2
  48. package/src/commands/scan/processScan.js +0 -1
  49. package/src/commands/scan/sca/scaAnalysis.js +28 -13
  50. package/src/common/HTTPClient.js +9 -9
  51. package/src/constants/constants.js +9 -3
  52. package/src/constants/locales.js +47 -35
  53. package/src/constants.js +12 -10
  54. package/src/index.ts +76 -66
  55. package/src/lambda/lambda.ts +5 -2
  56. package/src/lambda/types.ts +1 -0
  57. package/src/sbom/generateSbom.ts +2 -2
  58. package/src/scaAnalysis/common/formatMessage.js +8 -1
  59. package/src/scaAnalysis/common/treeUpload.js +4 -5
  60. package/src/scaAnalysis/dotnet/analysis.js +54 -0
  61. package/src/scaAnalysis/dotnet/index.js +11 -0
  62. package/src/scaAnalysis/javascript/analysis.js +6 -7
  63. package/src/scaAnalysis/javascript/index.js +23 -7
  64. package/src/scaAnalysis/php/analysis.js +15 -35
  65. package/src/scaAnalysis/php/index.js +15 -4
  66. package/src/scaAnalysis/ruby/analysis.js +2 -11
  67. package/src/scan/autoDetection.js +18 -24
  68. package/src/scan/fileUtils.js +33 -12
  69. package/src/scan/formatScanOutput.ts +3 -3
  70. package/src/scan/scanConfig.js +2 -4
  71. package/src/utils/getConfig.ts +1 -12
  72. package/dist/audit/AnalysisEngine.js +0 -37
  73. package/dist/audit/autodetection/autoDetectLanguage.js +0 -32
  74. package/dist/audit/dotnetAnalysisEngine/index.js +0 -25
  75. package/dist/audit/dotnetAnalysisEngine/parseLockFileContents.js +0 -35
  76. package/dist/audit/dotnetAnalysisEngine/parseProjectFileContents.js +0 -15
  77. package/dist/audit/dotnetAnalysisEngine/readLockFileContents.js +0 -18
  78. package/dist/audit/dotnetAnalysisEngine/readProjectFileContents.js +0 -14
  79. package/dist/audit/dotnetAnalysisEngine/sanitizer.js +0 -9
  80. package/dist/audit/goAnalysisEngine/index.js +0 -17
  81. package/dist/audit/goAnalysisEngine/parseProjectFileContents.js +0 -164
  82. package/dist/audit/goAnalysisEngine/readProjectFileContents.js +0 -21
  83. package/dist/audit/goAnalysisEngine/sanitizer.js +0 -5
  84. package/dist/audit/javaAnalysisEngine/index.js +0 -34
  85. package/dist/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +0 -155
  86. package/dist/audit/javaAnalysisEngine/parseProjectFileContents.js +0 -353
  87. package/dist/audit/javaAnalysisEngine/readProjectFileContents.js +0 -98
  88. package/dist/audit/javaAnalysisEngine/sanitizer.js +0 -5
  89. package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +0 -25
  90. package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +0 -25
  91. package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasLockFile.js +0 -35
  92. package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +0 -24
  93. package/dist/audit/languageAnalysisEngine/constants.js +0 -20
  94. package/dist/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +0 -25
  95. package/dist/audit/languageAnalysisEngine/index.js +0 -39
  96. package/dist/audit/languageAnalysisEngine/languageAnalysisFactory.js +0 -66
  97. package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +0 -166
  98. package/dist/audit/nodeAnalysisEngine/handleNPMLockFileV2.js +0 -40
  99. package/dist/audit/nodeAnalysisEngine/index.js +0 -31
  100. package/dist/audit/nodeAnalysisEngine/parseNPMLockFileContents.js +0 -18
  101. package/dist/audit/nodeAnalysisEngine/parseYarnLockFileContents.js +0 -18
  102. package/dist/audit/nodeAnalysisEngine/readNPMLockFileContents.js +0 -17
  103. package/dist/audit/nodeAnalysisEngine/readProjectFileContents.js +0 -14
  104. package/dist/audit/nodeAnalysisEngine/readYarnLockFileContents.js +0 -24
  105. package/dist/audit/nodeAnalysisEngine/sanitizer.js +0 -9
  106. package/dist/audit/phpAnalysisEngine/index.js +0 -23
  107. package/dist/audit/phpAnalysisEngine/parseLockFileContents.js +0 -52
  108. package/dist/audit/phpAnalysisEngine/readLockFileContents.js +0 -13
  109. package/dist/audit/phpAnalysisEngine/readProjectFileContents.js +0 -16
  110. package/dist/audit/phpAnalysisEngine/sanitizer.js +0 -5
  111. package/dist/audit/pythonAnalysisEngine/index.js +0 -25
  112. package/dist/audit/pythonAnalysisEngine/parsePipfileLockContents.js +0 -17
  113. package/dist/audit/pythonAnalysisEngine/parseProjectFileContents.js +0 -21
  114. package/dist/audit/pythonAnalysisEngine/readPipfileLockFileContents.js +0 -13
  115. package/dist/audit/pythonAnalysisEngine/readPythonProjectFileContents.js +0 -14
  116. package/dist/audit/pythonAnalysisEngine/sanitizer.js +0 -7
  117. package/dist/audit/rubyAnalysisEngine/index.js +0 -25
  118. package/dist/audit/rubyAnalysisEngine/parseGemfileLockContents.js +0 -176
  119. package/dist/audit/rubyAnalysisEngine/parsedGemfile.js +0 -22
  120. package/dist/audit/rubyAnalysisEngine/readGemfileContents.js +0 -14
  121. package/dist/audit/rubyAnalysisEngine/readGemfileLockContents.js +0 -14
  122. package/dist/audit/rubyAnalysisEngine/sanitizer.js +0 -6
  123. package/src/audit/AnalysisEngine.js +0 -103
  124. package/src/audit/autodetection/autoDetectLanguage.ts +0 -40
  125. package/src/audit/dotnetAnalysisEngine/index.js +0 -26
  126. package/src/audit/dotnetAnalysisEngine/parseLockFileContents.js +0 -47
  127. package/src/audit/dotnetAnalysisEngine/parseProjectFileContents.js +0 -29
  128. package/src/audit/dotnetAnalysisEngine/readLockFileContents.js +0 -30
  129. package/src/audit/dotnetAnalysisEngine/readProjectFileContents.js +0 -26
  130. package/src/audit/dotnetAnalysisEngine/sanitizer.js +0 -11
  131. package/src/audit/goAnalysisEngine/index.js +0 -18
  132. package/src/audit/goAnalysisEngine/parseProjectFileContents.js +0 -209
  133. package/src/audit/goAnalysisEngine/readProjectFileContents.js +0 -31
  134. package/src/audit/goAnalysisEngine/sanitizer.js +0 -7
  135. package/src/audit/javaAnalysisEngine/index.js +0 -41
  136. package/src/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +0 -225
  137. package/src/audit/javaAnalysisEngine/parseProjectFileContents.js +0 -420
  138. package/src/audit/javaAnalysisEngine/readProjectFileContents.js +0 -141
  139. package/src/audit/javaAnalysisEngine/sanitizer.js +0 -6
  140. package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +0 -36
  141. package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +0 -42
  142. package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasLockFile.js +0 -54
  143. package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +0 -33
  144. package/src/audit/languageAnalysisEngine/constants.js +0 -23
  145. package/src/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +0 -41
  146. package/src/audit/languageAnalysisEngine/index.js +0 -45
  147. package/src/audit/languageAnalysisEngine/languageAnalysisFactory.js +0 -96
  148. package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +0 -251
  149. package/src/audit/nodeAnalysisEngine/handleNPMLockFileV2.js +0 -49
  150. package/src/audit/nodeAnalysisEngine/index.js +0 -35
  151. package/src/audit/nodeAnalysisEngine/parseNPMLockFileContents.js +0 -20
  152. package/src/audit/nodeAnalysisEngine/parseYarnLockFileContents.js +0 -26
  153. package/src/audit/nodeAnalysisEngine/readNPMLockFileContents.js +0 -23
  154. package/src/audit/nodeAnalysisEngine/readProjectFileContents.js +0 -27
  155. package/src/audit/nodeAnalysisEngine/readYarnLockFileContents.js +0 -36
  156. package/src/audit/nodeAnalysisEngine/sanitizer.js +0 -11
  157. package/src/audit/phpAnalysisEngine/index.js +0 -27
  158. package/src/audit/phpAnalysisEngine/parseLockFileContents.js +0 -60
  159. package/src/audit/phpAnalysisEngine/readLockFileContents.js +0 -14
  160. package/src/audit/phpAnalysisEngine/readProjectFileContents.js +0 -25
  161. package/src/audit/phpAnalysisEngine/sanitizer.js +0 -4
  162. package/src/audit/pythonAnalysisEngine/index.js +0 -55
  163. package/src/audit/pythonAnalysisEngine/parsePipfileLockContents.js +0 -23
  164. package/src/audit/pythonAnalysisEngine/parseProjectFileContents.js +0 -33
  165. package/src/audit/pythonAnalysisEngine/readPipfileLockFileContents.js +0 -16
  166. package/src/audit/pythonAnalysisEngine/readPythonProjectFileContents.js +0 -22
  167. package/src/audit/pythonAnalysisEngine/sanitizer.js +0 -9
  168. package/src/audit/rubyAnalysisEngine/index.js +0 -30
  169. package/src/audit/rubyAnalysisEngine/parseGemfileLockContents.js +0 -215
  170. package/src/audit/rubyAnalysisEngine/parsedGemfile.js +0 -39
  171. package/src/audit/rubyAnalysisEngine/readGemfileContents.js +0 -18
  172. package/src/audit/rubyAnalysisEngine/readGemfileLockContents.js +0 -17
  173. package/src/audit/rubyAnalysisEngine/sanitizer.js +0 -8
@@ -1,9 +1,6 @@
1
1
  import { catalogueApplication } from '../../audit/catalogueApplication/catalogueApplication'
2
2
  import commonApi from '../../audit/languageAnalysisEngine/commonApi'
3
3
 
4
- const identifyLanguageAE = require('./../../audit/languageAnalysisEngine')
5
- const languageFactory = require('../../audit/languageAnalysisEngine/languageAnalysisFactory')
6
-
7
4
  export const dealWithNoAppId = async (config: { [x: string]: string }) => {
8
5
  let appID: string
9
6
  try {
@@ -32,14 +29,6 @@ export const dealWithNoAppId = async (config: { [x: string]: string }) => {
32
29
  return appID
33
30
  }
34
31
 
35
- export const startAudit = async (config: { [key: string]: string }) => {
36
- if (!config.applicationId) {
37
- // @ts-ignore
38
- config.applicationId = await dealWithNoAppId(config)
39
- }
40
- identifyLanguageAE(config.file, languageFactory, config.applicationId, config)
41
- }
42
-
43
32
  export const getAppName = (file: string) => {
44
33
  const last = file.charAt(file.length - 1)
45
34
  if (last !== '/') {
@@ -13,30 +13,13 @@ const auditUsageGuide = commandLineUsage([
13
13
  '{bold ' +
14
14
  i18n.__('constantsAuditPrerequisitesContentSupportedLanguages') +
15
15
  '}',
16
- '{bold ' +
17
- i18n.__('constantsAuditPrerequisitesContentJava') +
18
- '}' +
19
- i18n.__('constantsAuditPrerequisitesContentMessage'),
20
- '',
21
- '{italic ' + i18n.__('constantsJavaNote') + '}',
22
- '{italic ' + i18n.__('constantsJavaNoteGradle') + '}',
23
- '',
24
- '{bold ' +
25
- i18n.__('constantsAuditPrerequisitesContentDotNet') +
26
- '}' +
27
- i18n.__('constantsAuditPrerequisitesContentDotNetMessage'),
28
- '{bold ' +
29
- i18n.__('constantsAuditPrerequisitesContentLanguageNode') +
30
- '}' +
31
- i18n.__('constantsAuditPrerequisitesContentLanguageNodeMessage'),
32
- '{bold ' +
33
- i18n.__('constantsAuditPrerequisitesContentLanguageRuby') +
34
- '}' +
35
- i18n.__('constantsAuditPrerequisitesContentLanguageRubyMessage'),
36
- '{bold ' +
37
- i18n.__('constantsAuditPrerequisitesContentLanguagePython') +
38
- '}' +
39
- i18n.__('constantsAuditPrerequisitesContentLanguagePythonMessage')
16
+ i18n.__('constantsAuditPrerequisitesJavaContentMessage'),
17
+ i18n.__('constantsAuditPrerequisitesContentDotNetMessage'),
18
+ i18n.__('constantsAuditPrerequisitesContentNodeMessage'),
19
+ i18n.__('constantsAuditPrerequisitesContentRubyMessage'),
20
+ i18n.__('constantsAuditPrerequisitesContentPythonMessage'),
21
+ i18n.__('constantsAuditPrerequisitesContentGoMessage'),
22
+ i18n.__('constantsAuditPrerequisitesContentPHPMessage')
40
23
  ]
41
24
  },
42
25
  {
@@ -1,4 +1,3 @@
1
- import { startAudit } from './auditController'
2
1
  import { getAuditConfig } from './auditConfig'
3
2
  import { auditUsageGuide } from './help'
4
3
  import { processSca } from '../scan/sca/scaAnalysis'
@@ -11,12 +10,7 @@ export const processAudit = async (argv: parameterInput) => {
11
10
  process.exit(0)
12
11
  }
13
12
  const config = getAuditConfig(argv)
14
-
15
- if (config.experimental) {
16
- await processSca(config)
17
- } else {
18
- await startAudit(config)
19
- }
13
+ await processSca(config)
20
14
  }
21
15
 
22
16
  const printHelpMessage = () => {
@@ -1,7 +1,7 @@
1
1
  import fs from 'fs'
2
2
 
3
- export const saveFile = (config: any, rawResults: any) => {
4
- const fileName = `${config.applicationId}-sbom-cyclonedx.json`
3
+ export const saveFile = (config: any, type: string, rawResults: any) => {
4
+ const fileName = `${config.applicationId}-sbom-${type}.json`
5
5
  fs.writeFileSync(fileName, JSON.stringify(rawResults))
6
6
  }
7
7
 
@@ -7,7 +7,6 @@ const { processSca } = require('./sca/scaAnalysis')
7
7
 
8
8
  const processScan = async argvMain => {
9
9
  let config = scanConfig.getScanConfig(argvMain)
10
- // console.log(config)
11
10
  //try SCA analysis first
12
11
  if (config.experimental) {
13
12
  await processSca(config)
@@ -1,13 +1,10 @@
1
1
  const autoDetection = require('../../../scan/autoDetection')
2
2
  const javaAnalysis = require('../../../scaAnalysis/java')
3
3
  const treeUpload = require('../../../scaAnalysis/common/treeUpload')
4
- const {
5
- manualDetectAuditFilesAndLanguages
6
- } = require('../../../scan/autoDetection')
7
4
  const auditController = require('../../audit/auditController')
8
5
  const {
9
- supportedLanguages: { JAVA, GO, PYTHON, RUBY, JAVASCRIPT, NODE, PHP }
10
- } = require('../../../audit/languageAnalysisEngine/constants')
6
+ supportedLanguages: { JAVA, GO, PYTHON, RUBY, JAVASCRIPT, NODE, PHP, DOTNET }
7
+ } = require('../../../constants/constants')
11
8
  const goAnalysis = require('../../../scaAnalysis/go/goAnalysis')
12
9
  const phpAnalysis = require('../../../scaAnalysis/php/index')
13
10
  const { rubyAnalysis } = require('../../../scaAnalysis/ruby')
@@ -26,14 +23,17 @@ const {
26
23
  vulnerabilityReportV2
27
24
  } = require('../../../audit/languageAnalysisEngine/report/reportingFeature')
28
25
  const auditSave = require('../../../audit/save')
29
-
26
+ const { dotNetAnalysis } = require('../../../scaAnalysis/dotnet')
30
27
  const processSca = async config => {
28
+ const startTime = performance.now()
31
29
  let filesFound
32
30
  if (config.file) {
33
31
  config.file = config.file.concat('/')
34
- filesFound = await manualDetectAuditFilesAndLanguages(config.file)
32
+ filesFound = await autoDetection.autoDetectAuditFilesAndLanguages(
33
+ config.file
34
+ )
35
35
  } else {
36
- filesFound = await autoDetection.autoDetectAuditFilesAndLanguages(config)
36
+ filesFound = await autoDetection.autoDetectAuditFilesAndLanguages(undefined)
37
37
  config.file = process.cwd().concat('/')
38
38
  }
39
39
 
@@ -70,15 +70,21 @@ const processSca = async config => {
70
70
  messageToSend = goAnalysis.goAnalysis(config, filesFound[0])
71
71
  config.language = GO
72
72
  break
73
+ case DOTNET:
74
+ messageToSend = dotNetAnalysis(config, filesFound[0])
75
+ config.language = DOTNET
76
+ break
73
77
  default:
74
78
  //something is wrong
75
- console.log('language detected not supported')
79
+ console.log('No supported language detected in project path')
76
80
  return
77
81
  }
78
82
 
79
83
  if (!config.applicationId) {
80
84
  config.applicationId = await auditController.dealWithNoAppId(config)
81
85
  }
86
+
87
+ console.log('') //empty log for space before spinner
82
88
  //send message to TS
83
89
  const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'))
84
90
  startSpinner(reportSpinner)
@@ -93,16 +99,25 @@ const processSca = async config => {
93
99
  snapshotResponse.id,
94
100
  reportSpinner
95
101
  )
96
- succeedSpinner(reportSpinner, 'Contrast SCA audit complete')
102
+ succeedSpinner(reportSpinner, i18n.__('auditSCAAnalysisComplete'))
97
103
 
98
104
  await vulnerabilityReportV2(config, snapshotResponse.id)
105
+ if (config.save !== undefined) {
106
+ await auditSave.auditSave(config)
107
+ }
108
+ const endTime = performance.now() - startTime
109
+ const scanDurationMs = endTime - startTime
99
110
 
100
- await auditSave.auditSave(config)
111
+ console.log(
112
+ `----- completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`
113
+ )
101
114
  } else {
102
115
  if (filesFound.length === 0) {
103
- console.log('no compatible dependency files detected. Continuing...')
116
+ console.log(i18n.__('languageAnalysisNoLanguage'))
117
+ console.log(i18n.__('languageAnalysisNoLanguageHelpLine'))
118
+ throw new Error()
104
119
  } else {
105
- console.log(
120
+ throw new Error(
106
121
  'multiple language files detected, please use --file to specify a directory or the file where dependencies are declared'
107
122
  )
108
123
  }
@@ -333,9 +333,9 @@ HTTPClient.prototype.checkLibrary = function checkLibrary(data) {
333
333
  return requestUtils.sendRequest({ method: 'post', options })
334
334
  }
335
335
 
336
- HTTPClient.prototype.getSbom = function getSbom(config) {
336
+ HTTPClient.prototype.getSbom = function getSbom(config, type) {
337
337
  const options = _.cloneDeep(this.requestOptions)
338
- options.url = createSbomCycloneDXUrl(config)
338
+ options.url = createSbomUrl(config, type)
339
339
  return requestUtils.sendRequest({ method: 'get', options })
340
340
  }
341
341
 
@@ -417,13 +417,13 @@ function createLibraryVulnerabilitiesUrl(config) {
417
417
  return `${config.host}/Contrast/api/ng/${config.organizationId}/libraries/artifactsByGroupNameVersion`
418
418
  }
419
419
 
420
- function createSpecificReportUrl(config, reportId) {
421
- return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/${config.applicationId}/reports/${reportId}`
420
+ function createSpecificReportUrl(config, reportId, includeTree = false) {
421
+ return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/${config.applicationId}/reports/${reportId}?&includeTree=${includeTree}`
422
422
  }
423
423
 
424
- function createSpecificReportWithProdUrl(config, reportId) {
425
- return createSpecificReportUrl(config, reportId).concat(
426
- `?nodesToInclude=PROD`
424
+ function createSpecificReportWithProdUrl(config, reportId, includeTree) {
425
+ return createSpecificReportUrl(config, reportId, includeTree).concat(
426
+ `&nodesToInclude=PROD`
427
427
  )
428
428
  }
429
429
 
@@ -435,8 +435,8 @@ function createDataUrl() {
435
435
  return `https://ardy.contrastsecurity.com/production`
436
436
  }
437
437
 
438
- function createSbomCycloneDXUrl(config) {
439
- return `${config.host}/Contrast/api/ng/${config.organizationId}/applications/${config.applicationId}/libraries/sbom/cyclonedx`
438
+ function createSbomUrl(config, type) {
439
+ return `${config.host}/Contrast/api/ng/${config.organizationId}/applications/${config.applicationId}/libraries/sbom/${type}`
440
440
  }
441
441
 
442
442
  module.exports = HTTPClient
@@ -5,15 +5,16 @@ const JAVA = 'JAVA'
5
5
  const RUBY = 'RUBY'
6
6
  const PYTHON = 'PYTHON'
7
7
  const GO = 'GO'
8
- // we set the langauge as Node instead of PHP since we're using the Node engine in TS
9
8
  const PHP = 'PHP'
10
9
  const JAVASCRIPT = 'JAVASCRIPT'
10
+ // Severity
11
11
  const LOW = 'LOW'
12
12
  const MEDIUM = 'MEDIUM'
13
13
  const HIGH = 'HIGH'
14
14
  const CRITICAL = 'CRITICAL'
15
+ // App
15
16
  const APP_NAME = 'contrast'
16
- const APP_VERSION = '1.0.8'
17
+ const APP_VERSION = '1.0.9'
17
18
  const TIMEOUT = 120000
18
19
  const HIGH_COLOUR = '#ff9900'
19
20
  const CRITICAL_COLOUR = '#e35858'
@@ -29,10 +30,13 @@ const NOTE_PRIORITY = 5
29
30
  const AUTH_UI_URL = 'https://cli-auth.contrastsecurity.com'
30
31
  const AUTH_CALLBACK_URL = 'https://cli-auth-api.contrastsecurity.com'
31
32
  const SARIF_FILE = 'SARIF'
33
+ const SBOM_CYCLONE_DX_FILE = 'cyclonedx'
34
+ const SBOM_SPDX_FILE = 'spdx'
32
35
  const CE_URL = 'https://ce.contrastsecurity.com/'
33
36
 
34
37
  module.exports = {
35
38
  supportedLanguages: { NODE, DOTNET, JAVA, RUBY, PYTHON, GO, PHP, JAVASCRIPT },
39
+ supportedLanguagesScan: { JAVASCRIPT, DOTNET, JAVA },
36
40
  LOW,
37
41
  MEDIUM,
38
42
  HIGH,
@@ -53,5 +57,7 @@ module.exports = {
53
57
  HIGH_PRIORITY,
54
58
  MEDIUM_PRIORITY,
55
59
  LOW_PRIORITY,
56
- NOTE_PRIORITY
60
+ NOTE_PRIORITY,
61
+ SBOM_CYCLONE_DX_FILE,
62
+ SBOM_SPDX_FILE
57
63
  }
@@ -53,8 +53,10 @@ const en_locales = () => {
53
53
  "Identified project language as '%s' but found multiple project files: %s. Please specify which project file you would like analyzed with the %s CLI option.",
54
54
  languageAnalysisHasNoLockFile:
55
55
  "Identified project language as '%s' but no project lock file was found.",
56
+ languageAnalysisHasNoPackageJsonFile:
57
+ 'Identified project language as javascript but no package.json file was found.',
56
58
  languageAnalysisHasMultipleLockFiles:
57
- "Identified project language as '%s' but multiple project lock files were found: %s \n",
59
+ "Identified project language as '%s' but multiple project lock files were found.",
58
60
  languageAnalysisProjectFileError:
59
61
  "Identified project language as '%s' but no project file was found.",
60
62
  languageAnalysisProjectRootFileNameReadError:
@@ -64,17 +66,20 @@ const en_locales = () => {
64
66
  languageAnalysisProjectRootFileNameFailure:
65
67
  'Failed to get information about the file or directory @ %s because: ',
66
68
  languageAnalysisFailure: ' analysis failed because: ',
67
- languageAnalysisNoLanguage: 'No language detected in project path @ %s',
69
+ languageAnalysisNoLanguage:
70
+ 'We cannot detect a project, use --f <path> to specify a file or folder to analyze.',
71
+ languageAnalysisNoLanguageHelpLine: `${chalk.bold(
72
+ 'contrast audit --help'
73
+ )} for more information.`,
68
74
  NodeAnalysisFailure: 'NODE analysis failed because: ',
69
75
  phpAnalysisFailure: 'PHP analysis failed because: ',
70
- NodeParseNPM:
71
- "Failed to parse NODE package-lock.json file @ '%s' because: ",
76
+ NodeParseNPM: 'Failed to parse NODE package-lock.json file because: ',
72
77
  phpParseComposerLock:
73
78
  "Failed to parse PHP composer.lock file @ '%s' because: ",
74
79
  NodeReadNpmError:
75
80
  'Failed to read the package-lock.json file @ "%s" because: ',
76
81
  phpReadError: 'Failed to read the composer.lock file @ "%s" because: ',
77
- NodeParseYarn: "Failed to parse Node yarn.lock version 1 @ '%s' because: ",
82
+ NodeParseYarn: 'Failed to parse yarn.lock version %s because: ',
78
83
  NodeParseYarn2: "Failed to parse Node yarn.lock version 2 @ '%s' because: ",
79
84
  nodeReadProjectFileError:
80
85
  'Failed to read the NODE project file @ "%s" because: ',
@@ -118,8 +123,7 @@ const en_locales = () => {
118
123
  'Provide this if you want to catalogue an application',
119
124
  constantsLanguage:
120
125
  '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',
121
- constantsFilePath:
122
- 'The directory root of a project/application that you would like analyzed. Defaults to current directory.',
126
+ constantsFilePath: `Path of the file you want to perform an SCA audit on. If no folder is specified, Contrast searches for dependency files in the working directory.`,
123
127
  constantsSilent: 'Silences JSON output.',
124
128
  constantsAppGroups:
125
129
  'Assign your application to one or more pre-existing groups when using the catalogue command. Group lists should be comma separated.',
@@ -144,7 +148,8 @@ const en_locales = () => {
144
148
  '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.',
145
149
  constantsCount: 'The number of CVEs that must be exceeded to fail a build',
146
150
  constantsHeader: 'CodeSec by Contrast Security',
147
- constantsPrerequisitesContentScanLanguages: 'Java & JavaScript supported',
151
+ constantsPrerequisitesContentScanLanguages:
152
+ 'Java, Javascript and .NET supported',
148
153
  constantsContrastContent:
149
154
  "Use the 'contrast' command for fast and accurate security analysis of your applications and APIs (Java, JavaScript and .NET ) as well as serverless functions (AWS lambda, Java and Python).",
150
155
  constantsUsageGuideContentRecommendation:
@@ -249,7 +254,7 @@ const en_locales = () => {
249
254
  scanLabel:
250
255
  "adds a label to the scan - defaults to 'Started by CLI tool at current date'",
251
256
  constantsIgnoreDev:
252
- 'Excludes developer dependencies from the output. By default all dependencies are included.',
257
+ 'Excludes developer dependencies from the results. All dependencies are included by default.',
253
258
  constantsCommands: 'Commands',
254
259
  constantsScanOptions: 'Scan Options',
255
260
  sbomError: 'All required parameters are not present.',
@@ -364,36 +369,43 @@ const en_locales = () => {
364
369
  'An error has occurred when trying to get the Project Id please check your internet connection or provide the Project Id manually',
365
370
  internalServerErrorHeader: '500 error - Internal server error',
366
371
  resourceLockedErrorHeader: '423 error - Resource is locked',
367
- auditHeader: 'Contrast Audit',
368
- auditHeaderMessage: `
369
- Performs software composition analysis (SCA) on your application/code time to show you the dependencies between open source libraries, including where vulnerabilities were introduced.\n
370
- 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.`,
372
+ auditHeader: 'Contrast audit help',
373
+ auditHeaderMessage:
374
+ "Use 'contrast audit' to analyze a project’s dependencies for vulnerabilities.",
371
375
  constantsAuditPrerequisitesContentSupportedLanguages:
372
376
  'Supported languages and their requirements are:',
373
- constantsAuditPrerequisitesContentJava: 'Java: ',
374
- constantsAuditPrerequisitesContentMessage: `
375
- pom.xml AND Maven build platform, including the dependency plugin.
376
- For a Gradle project (v4.8+) use build.gradle. A gradle-wrapper.properties file is also required.
377
- Kotlin is also supported requiring a build.gradle.kts file.`,
378
- constantsAuditPrerequisitesContentDotNet: '.NET framework and .NET core: ',
377
+ constantsAuditPrerequisitesJavaContentMessage: `
378
+ ${chalk.bold('Java:')} pom.xml ${chalk.bold(
379
+ 'and'
380
+ )} Maven build platform including the dependency plugin.
381
+ ${chalk.bold('Or')} build.gradle ${chalk.bold(
382
+ 'and'
383
+ )} gradle dependencies or ./gradlew dependencies must be supported`,
379
384
  constantsAuditPrerequisitesContentDotNetMessage: `
380
- MSBuild 15.0 or greater and have a packages.lock.json file are supported.\n
381
- Note: If the packages.lock.json file is unavailable it can be generated by setting RestorePackagesWithLockFile to true within each *.csproj file and running dotnet build.\n`,
382
- constantsAuditPrerequisitesContentLanguageNode: 'Node: ',
383
- constantsAuditPrerequisitesContentLanguageRuby: 'Ruby: ',
384
- constantsAuditPrerequisitesContentLanguagePython: 'Python: ',
385
- constantsAuditPrerequisitesContentLanguageNodeMessage:
386
- '*.package.json AND a lock file either *.package-lock.json or *.yarn.lock',
387
- constantsAuditPrerequisitesContentLanguageRubyMessage:
388
- 'gemfile AND gemfile.lock',
389
- constantsAuditPrerequisitesContentLanguagePythonMessage:
390
- 'pipfile AND pipfile.lock',
385
+ ${chalk.bold(
386
+ '.NET framework and .NET core:'
387
+ )} MSBuild 15.0 or greater and a packages.lock.json file.
388
+ Note: If the packages.lock.json file is unavailable it can be generated by setting RestorePackagesWithLockFile to true within each *.csproj file and running dotnet build.\n`,
389
+ constantsAuditPrerequisitesContentNodeMessage: `${chalk.bold(
390
+ 'Node:'
391
+ )} package.json and a lock file (either .package-lock.json or .yarn.lock.)\n`,
392
+ constantsAuditPrerequisitesContentRubyMessage: `${chalk.bold(
393
+ 'Ruby:'
394
+ )} gemfile and gemfile.lock\n`,
395
+ constantsAuditPrerequisitesContentPythonMessage: `${chalk.bold(
396
+ 'Python:'
397
+ )} pipfile and pipfile.lock\n`,
398
+ constantsAuditPrerequisitesContentGoMessage: `${chalk.bold(
399
+ 'Go:'
400
+ )} go.mod\n`,
401
+ constantsAuditPrerequisitesContentPHPMessage: `${chalk.bold(
402
+ 'PHP:'
403
+ )} composer.json and composer.lock\n`,
391
404
  constantsAuditOptions: 'Audit Options',
392
- auditOptionsIgnoreDevDependencies: '-igd, --ignore-dev',
393
- auditOptionsIgnoreDevDependenciesDescription: 'ignores DevDependencies',
394
- auditOptionsSave: '-s, --save',
395
405
  auditOptionsSaveDescription:
396
- 'saves the output in specified format, options: sbom',
406
+ 'Generate and save an SBOM (Software Bill of Materials)\n',
407
+ auditOptionsSaveOptionsDescription:
408
+ 'Valid options are: spdx, cyclonedx (cycloneDX is the default format)',
397
409
  scanNotCompleted:
398
410
  'Scan not completed. Check for framework and language support here: %s',
399
411
  auditNotCompleted: 'audit not completed. Please try again',
@@ -415,7 +427,7 @@ const en_locales = () => {
415
427
  auditReportSuccessMessage: 'Report successfully retrieved',
416
428
  auditReportFailureMessage: 'Unable to generate library report',
417
429
  auditSCAAnalysisBegins: 'Contrast SCA audit started',
418
- auditSCAAnalysisComplete: 'Contrast SCA audit complete',
430
+ auditSCAAnalysisComplete: 'Contrast audit complete',
419
431
  ...lambda
420
432
  }
421
433
  }
package/src/constants.js CHANGED
@@ -266,15 +266,6 @@ const auditOptionDefinitions = [
266
266
  {
267
267
  name: 'maven-settings-path'
268
268
  },
269
- {
270
- name: 'language',
271
- alias: 'l',
272
- description:
273
- '{bold ' +
274
- i18n.__('constantsRequiredCatalogue') +
275
- '}: ' +
276
- i18n.__('constantsLanguage')
277
- },
278
269
  {
279
270
  name: 'organization-id',
280
271
  alias: 'o',
@@ -333,12 +324,23 @@ const auditOptionDefinitions = [
333
324
  '{bold ' +
334
325
  i18n.__('constantsOptional') +
335
326
  '}: ' +
336
- i18n.__('auditOptionsSaveDescription')
327
+ i18n.__('auditOptionsSaveDescription') +
328
+ i18n.__('auditOptionsSaveOptionsDescription')
337
329
  },
338
330
  {
339
331
  name: 'experimental',
340
332
  alias: 'e',
341
333
  type: Boolean
334
+ },
335
+ {
336
+ name: 'timeout',
337
+ alias: 't',
338
+ type: Number,
339
+ description:
340
+ '{bold ' +
341
+ i18n.__('constantsOptional') +
342
+ '}: ' +
343
+ i18n.__('scanOptionsTimeoutSummary')
342
344
  }
343
345
  ]
344
346
 
package/src/index.ts CHANGED
@@ -36,74 +36,84 @@ const getMainOption = () => {
36
36
  }
37
37
 
38
38
  const start = async () => {
39
- if (await isCorrectNodeVersion(process.version)) {
40
- const { mainOptions, argv: argvMain } = getMainOption()
41
- const command =
42
- mainOptions.command != undefined ? mainOptions.command.toLowerCase() : ''
43
- if (
44
- command === 'version' ||
45
- argvMain.includes('--v') ||
46
- argvMain.includes('--version')
47
- ) {
48
- console.log(APP_VERSION)
49
- await findLatestCLIVersion(config)
50
- return
51
- }
52
-
53
- // @ts-ignore
54
- config.set('numOfRuns', config.get('numOfRuns') + 1)
55
-
56
- // @ts-ignore
57
- if (config.get('numOfRuns') >= 1) {
58
- await findLatestCLIVersion(config)
59
- config.set('numOfRuns', 0)
60
- }
61
-
62
- if (command === 'config') {
63
- return processConfig(argvMain, config)
64
- }
65
-
66
- if (command === 'auth') {
67
- return await processAuth(argvMain, config)
68
- }
69
-
70
- if (command === 'lambda') {
71
- return await processLambda(argvMain)
72
- }
73
-
74
- if (command === 'scan') {
75
- return await processScan(argvMain)
76
- }
77
-
78
- if (command === 'audit') {
79
- return await processAudit(argvMain)
80
- }
81
-
82
- if (
83
- command === 'help' ||
84
- argvMain.includes('--help') ||
85
- Object.keys(mainOptions).length === 0
86
- ) {
87
- console.log(mainUsageGuide)
88
- } else if (mainOptions._unknown !== undefined) {
89
- const foundCommand = findCommandOnError(mainOptions._unknown)
90
-
91
- foundCommand
92
- ? console.log(
93
- `Unknown Command: Did you mean "${foundCommand}"? \nUse "${foundCommand} --help" for the full list of options`
94
- )
95
- : console.log(
96
- `Unknown Command: ${command} \nUse --help for the full list`
97
- )
39
+ try {
40
+ if (await isCorrectNodeVersion(process.version)) {
41
+ const { mainOptions, argv: argvMain } = getMainOption()
42
+ const command =
43
+ mainOptions.command != undefined
44
+ ? mainOptions.command.toLowerCase()
45
+ : ''
46
+ if (
47
+ command === 'version' ||
48
+ argvMain.includes('--v') ||
49
+ argvMain.includes('--version')
50
+ ) {
51
+ console.log(APP_VERSION)
52
+ await findLatestCLIVersion(config)
53
+ return
54
+ }
55
+
56
+ // @ts-ignore
57
+ config.set('numOfRuns', config.get('numOfRuns') + 1)
58
+
59
+ // @ts-ignore
60
+ if (config.get('numOfRuns') >= 1) {
61
+ await findLatestCLIVersion(config)
62
+ config.set('numOfRuns', 0)
63
+ }
64
+
65
+ if (command === 'config') {
66
+ return processConfig(argvMain, config)
67
+ }
68
+
69
+ if (command === 'auth') {
70
+ return await processAuth(argvMain, config)
71
+ }
72
+
73
+ if (command === 'lambda') {
74
+ return await processLambda(argvMain)
75
+ }
76
+
77
+ if (command === 'scan') {
78
+ return await processScan(argvMain)
79
+ }
80
+
81
+ if (command === 'audit') {
82
+ return await processAudit(argvMain)
83
+ }
84
+
85
+ if (
86
+ command === 'help' ||
87
+ argvMain.includes('--help') ||
88
+ Object.keys(mainOptions).length === 0
89
+ ) {
90
+ console.log(mainUsageGuide)
91
+ } else if (mainOptions._unknown !== undefined) {
92
+ const foundCommand = findCommandOnError(mainOptions._unknown)
93
+
94
+ foundCommand
95
+ ? console.log(
96
+ `Unknown Command: Did you mean "${foundCommand}"? \nUse "${foundCommand} --help" for the full list of options`
97
+ )
98
+ : console.log(
99
+ `Unknown Command: ${command} \nUse --help for the full list`
100
+ )
101
+ } else {
102
+ console.log(
103
+ `Unknown Command: ${command} \nUse --help for the full list`
104
+ )
105
+ }
106
+ process.exit(9)
98
107
  } else {
99
- console.log(`Unknown Command: ${command} \nUse --help for the full list`)
108
+ console.log(
109
+ 'Contrast supports Node versions >=16.13.2 <17. Please use one of those versions.'
110
+ )
111
+ process.exit(9)
100
112
  }
101
- process.exit(9)
102
- } else {
103
- console.log(
104
- 'Contrast supports Node versions >=16.13.2 <17. Please use one of those versions.'
105
- )
106
- process.exit(9)
113
+ } catch (err: any) {
114
+ console.log()
115
+ console.log(err.message.toString())
116
+ process.exit(1)
107
117
  }
108
118
  }
109
119
 
@@ -16,6 +16,7 @@ import { sleep } from '../utils/requestUtils'
16
16
  import ora from '../utils/oraWrapper'
17
17
  import { postAnalytics } from './analytics'
18
18
  import { LambdaOptions, AnalyticsOption, StatusType, EventType } from './types'
19
+ import { APP_VERSION } from '../constants/constants'
19
20
 
20
21
  type ApiParams = {
21
22
  organizationId: string
@@ -73,7 +74,8 @@ const processLambda = async (argv: string[]) => {
73
74
  const startCommandAnalytics: AnalyticsOption = {
74
75
  arguments: lambdaOptions,
75
76
  sessionId: commandSessionId,
76
- eventType: EventType.START
77
+ eventType: EventType.START,
78
+ packageVersion: APP_VERSION
77
79
  }
78
80
  postAnalytics(startCommandAnalytics).catch((error: Error) => {
79
81
  /* ignore */
@@ -99,7 +101,8 @@ const processLambda = async (argv: string[]) => {
99
101
  const endCommandAnalytics: AnalyticsOption = {
100
102
  sessionId: commandSessionId,
101
103
  eventType: EventType.END,
102
- status: errorMsg ? StatusType.FAILED : StatusType.SUCCESS
104
+ status: errorMsg ? StatusType.FAILED : StatusType.SUCCESS,
105
+ packageVersion: APP_VERSION
103
106
  }
104
107
  if (errorMsg) {
105
108
  endCommandAnalytics.errorMsg = errorMsg
@@ -28,6 +28,7 @@ type ScanFunctionData = {
28
28
  export type AnalyticsOption = {
29
29
  sessionId: string
30
30
  eventType: EventType
31
+ packageVersion: string
31
32
  arguments?: LambdaOptions
32
33
  scanFunctionData?: ScanFunctionData
33
34
  status?: StatusType