@contrast/contrast 2.0.1 → 2.0.2-beta.1

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 (49) hide show
  1. package/dist/audit/report/reportingFeature.js +7 -0
  2. package/dist/cliConstants.js +9 -8
  3. package/dist/commands/audit/processAudit.js +0 -2
  4. package/dist/commands/github/fingerprintConfig.js +2 -1
  5. package/dist/commands/github/processFingerprint.js +17 -7
  6. package/dist/commands/github/projectGroup.js +110 -30
  7. package/dist/commands/github/repoServices.js +42 -4
  8. package/dist/common/HTTPClient.js +37 -16
  9. package/dist/common/baseRequest.js +74 -0
  10. package/dist/constants/constants.js +1 -1
  11. package/dist/scaAnalysis/common/auditReport.js +8 -1
  12. package/dist/scaAnalysis/common/scaServicesUpload.js +3 -1
  13. package/dist/scaAnalysis/go/goReadDepFile.js +5 -1
  14. package/dist/scaAnalysis/java/analysis.js +1 -1
  15. package/dist/scaAnalysis/java/javaBuildDepsParser.js +11 -1
  16. package/dist/scaAnalysis/legacy/legacyFlow.js +0 -6
  17. package/dist/scaAnalysis/processServicesFlow.js +38 -17
  18. package/dist/scaAnalysis/repoMode/mavenParser.js +95 -53
  19. package/dist/scaAnalysis/scaAnalysis.js +4 -8
  20. package/dist/scan/autoDetection.js +12 -5
  21. package/dist/scan/fileUtils.js +33 -19
  22. package/dist/utils/paramsUtil/paramHandler.js +11 -2
  23. package/dist/utils/validationCheck.js +5 -1
  24. package/package.json +7 -3
  25. package/src/audit/report/reportingFeature.ts +7 -0
  26. package/src/cliConstants.js +9 -8
  27. package/src/commands/audit/processAudit.js +0 -2
  28. package/src/commands/github/fingerprintConfig.js +2 -2
  29. package/src/commands/github/processFingerprint.js +21 -11
  30. package/src/commands/github/projectGroup.js +131 -35
  31. package/src/commands/github/repoServices.js +46 -4
  32. package/src/common/HTTPClient.js +46 -17
  33. package/src/common/baseRequest.ts +83 -0
  34. package/src/constants/constants.js +1 -1
  35. package/src/scaAnalysis/common/auditReport.js +8 -1
  36. package/src/scaAnalysis/common/scaServicesUpload.js +5 -1
  37. package/src/scaAnalysis/go/goReadDepFile.js +5 -1
  38. package/src/scaAnalysis/java/analysis.js +1 -1
  39. package/src/scaAnalysis/java/javaBuildDepsParser.js +17 -1
  40. package/src/scaAnalysis/legacy/legacyFlow.js +0 -5
  41. package/src/scaAnalysis/processServicesFlow.js +82 -24
  42. package/src/scaAnalysis/repoMode/mavenParser.js +112 -62
  43. package/src/scaAnalysis/scaAnalysis.js +9 -8
  44. package/src/scan/autoDetection.js +12 -5
  45. package/src/scan/fileUtils.js +33 -19
  46. package/src/utils/paramsUtil/paramHandler.js +16 -2
  47. package/src/utils/validationCheck.js +6 -1
  48. package/dist/utils/settingsHelper.js +0 -14
  49. package/src/utils/settingsHelper.js +0 -16
@@ -0,0 +1,83 @@
1
+ import { HttpsProxyAgent } from 'hpagent'
2
+ import fs from 'fs'
3
+ import got, { Options } from 'got'
4
+ import { Agents, HTTPSOptions } from 'got/dist/source/core'
5
+
6
+ export function gotInstance(config: any) {
7
+ return got.extend({ retry: { limit: 0 }, ...buildBaseRequestOptions(config) })
8
+ }
9
+
10
+ export function buildBaseRequestOptions(config: any) {
11
+ const { apiKey, authorization } = config
12
+ const rejectUnauthorized = !config.certSelfSigned
13
+
14
+ const superApiKey = config.superApiKey
15
+ const superAuthToken = config.superAuthorization
16
+
17
+ const requestOptions = {
18
+ responseType: 'json',
19
+ forever: true,
20
+ uri: config.host,
21
+ followRedirect: false,
22
+ headers: {
23
+ 'Content-Type': 'application/json; charset=utf-8',
24
+ Authorization: authorization,
25
+ 'API-Key': apiKey,
26
+ SuperAuthorization: superAuthToken,
27
+ 'Super-API-Key': superApiKey,
28
+ 'User-Agent': 'contrast-cli-v2'
29
+ },
30
+ agent: getAgent(config)
31
+ } as Options
32
+
33
+ requestOptions.https = {
34
+ rejectUnauthorized: rejectUnauthorized
35
+ }
36
+
37
+ maybeAddCertsToRequest(config, requestOptions.https)
38
+ return requestOptions
39
+ }
40
+
41
+ function getAgent(config: any) {
42
+ return config.proxy
43
+ ? (new HttpsProxyAgent({ proxy: config.proxy }) as Agents)
44
+ : false
45
+ }
46
+
47
+ function maybeAddCertsToRequest(config: any, https: HTTPSOptions) {
48
+ // cacert
49
+ const caCertFilePath = config.cacert
50
+ if (caCertFilePath) {
51
+ try {
52
+ https.certificateAuthority = fs.readFileSync(caCertFilePath)
53
+ } catch (error: any) {
54
+ throw new Error(
55
+ `Unable to read CA from ${caCertFilePath}, msg: ${error.message}`
56
+ )
57
+ }
58
+ }
59
+
60
+ // cert
61
+ const certPath = config.cert
62
+ if (certPath) {
63
+ try {
64
+ https.certificate = fs.readFileSync(certPath)
65
+ } catch (error: any) {
66
+ throw new Error(
67
+ `Unable to read Certificate PEM file from config option contrast.api.certificate.cert_file='${certPath}', msg: ${error.message}`
68
+ )
69
+ }
70
+ }
71
+
72
+ // key
73
+ const keyPath = config.key
74
+ if (keyPath) {
75
+ try {
76
+ https.key = fs.readFileSync(keyPath)
77
+ } catch (error: any) {
78
+ throw new Error(
79
+ `Unable to read Key PEM file from config option contrast.api.certificate.key_file='${keyPath}', msg: ${error.message}`
80
+ )
81
+ }
82
+ }
83
+ }
@@ -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 = '2.0.1'
17
+ const APP_VERSION = '2.0.2-beta.1'
18
18
  const TIMEOUT = 120000
19
19
  const HIGH_COLOUR = '#ff9900'
20
20
  const CRITICAL_COLOUR = '#e35858'
@@ -4,13 +4,20 @@ const {
4
4
  } = require('../../audit/report/commonReportingFunctions')
5
5
  const common = require('../../common/fail')
6
6
  const { printFormattedOutputSca } = require('./commonReportingFunctionsSca')
7
+ const { auditSave } = require('../../audit/save')
7
8
 
8
- const processAuditReport = (config, reportModelList) => {
9
+ const processAuditReport = async (config, reportModelList, reportId) => {
9
10
  let severityCounts = {}
10
11
  if (reportModelList !== undefined) {
11
12
  severityCounts = formatScaServicesReport(config, reportModelList)
12
13
  }
13
14
 
15
+ if (config.save !== undefined) {
16
+ await auditSave(config, reportId)
17
+ } else {
18
+ console.log('Use contrast audit --save to generate an SBOM')
19
+ }
20
+
14
21
  if (config.fail) {
15
22
  common.processFail(config, severityCounts)
16
23
  }
@@ -14,8 +14,12 @@ const scaTreeUpload = async (analysis, config, reportSpinner) => {
14
14
  config.language = config.language === 'JAVASCRIPT' ? 'NODE' : config.language
15
15
  const startTime = performance.now()
16
16
  const timeout = commonApi.getTimeout(config)
17
+
18
+ const doINeedParent = config.repositoryId && config.language === 'JAVA'
19
+
17
20
  const requestBody = {
18
- dependencyTree: analysis,
21
+ parentPom: doINeedParent ? analysis.parentPom : null,
22
+ dependencyTree: doINeedParent ? analysis.dependencyTree : analysis,
19
23
  organizationId: config.organizationId,
20
24
  language: config.language,
21
25
  tool: {
@@ -8,7 +8,10 @@ const getGoDependencies = config => {
8
8
  try {
9
9
  // A sample of this output can be found
10
10
  // in the go test folder data/goModGraphResults.text
11
- cmdStdout = child_process.execSync('go mod graph', { cwd })
11
+ cmdStdout = child_process.execSync('go mod graph', {
12
+ cwd: cwd,
13
+ maxBuffer: 50 * 1024 * 1024
14
+ })
12
15
 
13
16
  return cmdStdout.toString()
14
17
  } catch (err) {
@@ -22,6 +25,7 @@ const getGoDependencies = config => {
22
25
  // throw new Error(
23
26
  // i18n.__('goReadProjectFile', cwd, `${err.message ? err.message : ''}`)
24
27
  // )
28
+ process.exit(1)
25
29
  }
26
30
  }
27
31
 
@@ -30,7 +30,7 @@ const determineProjectTypeAndCwd = (files, config) => {
30
30
 
31
31
  const buildMaven = (config, projectData, timeout) => {
32
32
  let command = 'mvn'
33
- let args = ['dependency:tree', '-B']
33
+ let args = ['dependency:tree', '-B', '-Dscope=runtime']
34
34
  if (config.mavenSettingsPath) {
35
35
  args.push('-s')
36
36
  args.push(config.mavenSettingsPath)
@@ -140,7 +140,7 @@ const computeRelationToLastElement = element => {
140
140
  }
141
141
 
142
142
  const stripElement = element => {
143
- return element
143
+ const initialStrippedElement = element
144
144
  .replace(/[|]/g, '')
145
145
  .replace('+---', '')
146
146
  .replace('\\---', '')
@@ -148,6 +148,22 @@ const stripElement = element => {
148
148
  .replace('(c)', '')
149
149
  .replace('->', '@')
150
150
  .replace('(*)', '')
151
+
152
+ //work out Gradle resolved versioning e.g. org.slf4j:slf4j-api:1.7.25 -> 1.7.22
153
+ //take 1.7.22
154
+ const splitElements = initialStrippedElement.split(':')
155
+ if (
156
+ splitElements[2] !== undefined &&
157
+ splitElements[2] !== null &&
158
+ splitElements[2].includes('@')
159
+ ) {
160
+ const splitVersions = splitElements[2].split('@')
161
+ return initialStrippedElement
162
+ .replace(':' + splitVersions[0], '')
163
+ .replace('@', ':')
164
+ }
165
+
166
+ return initialStrippedElement
151
167
  }
152
168
 
153
169
  const checkVersion = element => {
@@ -32,11 +32,6 @@ const legacyFlow = async (config, messageToSend) => {
32
32
  succeedSpinner(reportSpinner, i18n.__('auditSCAAnalysisComplete'))
33
33
 
34
34
  await vulnerabilityReportV2(config, snapshotResponse.id)
35
- if (config.save !== undefined) {
36
- await auditSave(config)
37
- } else {
38
- console.log('\nUse contrast audit --save to generate an SBOM')
39
- }
40
35
  const endTime = performance.now() - startTime
41
36
  const scanDurationMs = endTime - startTime
42
37
 
@@ -1,7 +1,8 @@
1
1
  const projectConfig = require('../commands/github/projectGroup')
2
+ const repoService = require('../commands/github/repoServices')
2
3
  const scaServicesUpload = require('../scaAnalysis/common/scaServicesUpload')
3
4
 
4
- const trackProcess = async (analysis, config, reportSpinner) => {
5
+ const dealWithNoProjectId = async (analysis, config, reportSpinner) => {
5
6
  await projectConfig.registerNewProjectGroup(config)
6
7
  let projectId = await projectConfig.getProjectIdByOrg(config)
7
8
  await projectConfig.registerProjectIdOnCliServices(config, projectId)
@@ -10,29 +11,83 @@ const trackProcess = async (analysis, config, reportSpinner) => {
10
11
  }
11
12
 
12
13
  const repoProcess = async (analysis, config, reportSpinner) => {
13
- let repoInfo = repoService.retrieveRepoId(config)
14
- if (repoInfo.repoId === '') {
15
- repoInfo = repoService.registerRepo(config)
14
+ if (config.debug || config.verbose) {
15
+ console.log('in repository process')
16
+ console.log('repository id: ', config.repositoryId)
17
+ }
18
+ if (config.repositoryId === '') {
19
+ console.log('Failed to retrieve Repository Id')
20
+ process.exit(1)
16
21
  }
17
- await projectConfig.registerProjectIdOnCliServices(config, repoInfo.projectId)
18
- return repoInfo
19
- }
20
22
 
21
- const dealWithNoProjectId = async (analysis, config, reportSpinner) => {
22
- // if (config.repo === '') {
23
- // return repoProcess(analysis, config, reportSpinner)
23
+ let repoInfo = await repoService.retrieveProjectInfoViaRepoId(config)
24
+
25
+ repoInfo = repoInfo.find(
26
+ element =>
27
+ config.fileName === element.path &&
28
+ config.fileName === element.name &&
29
+ config.projectGroupId === element.projectGroupId
30
+ )
31
+
32
+ // console.log('repoInfo', repoInfo)
33
+
34
+ // if(repoInfo !== undefined) {
35
+ // console.log('re-register / register first time')
36
+ // const language = repoInfo.language === 'JAVASCRIPT' ? 'NODE' : repoInfo.language
37
+ // const additionalData = {
38
+ // projectGroupId: repoInfo.projectGroupId,
39
+ // projectGroupName: repoInfo.name,
40
+ // projectLanguage: language,
41
+ // projectType: 'REPOSITORY'
42
+ // }
43
+ //
44
+ // // check project exists in sca / register (just in case, it failed in the past)
45
+ // await projectConfig.registerProjectIdOnCliServices(
46
+ // config,
47
+ // repoInfo.projectId,
48
+ // additionalData
49
+ // )
24
50
  // }
25
- if (config.track) {
26
- return trackProcess(analysis, config, reportSpinner)
27
- }
28
51
 
29
- if (!config.track) {
30
- return await scaServicesUpload.noProjectUpload(
31
- analysis,
52
+ if (
53
+ config.projectGroupId &&
54
+ !repoInfo?.projectId &&
55
+ (repoInfo === undefined || repoInfo.length === 0)
56
+ ) {
57
+ console.log(
58
+ '*** has projectGroupId, no projectId and repo has no project found that matches'
59
+ )
60
+ repoInfo = await projectConfig.registerProjectWithGroupProjectId(config)
61
+ console.log('new registered group', repoInfo)
62
+ const language =
63
+ repoInfo.language === 'JAVASCRIPT' ? 'NODE' : repoInfo.language
64
+
65
+ // const additionalData = {
66
+ // projectGroupId: repoInfo.projectGroupId,
67
+ // projectGroupName: repoInfo.name,
68
+ // projectLanguage: language,
69
+ // projectType: 'REPOSITORY'
70
+ // }
71
+
72
+ await projectConfig.registerProjectIdOnCliServices(
32
73
  config,
33
- reportSpinner
74
+ repoInfo.projectId
34
75
  )
35
76
  }
77
+ config.projectId = repoInfo.projectId
78
+ return await scaServicesUpload.scaTreeUpload(analysis, config, reportSpinner)
79
+ }
80
+
81
+ const trackProcess = async (analysis, config, reportSpinner) => {
82
+ let projectId = await projectConfig.getProjectIdByOrg(config)
83
+
84
+ if (projectId === '') {
85
+ return dealWithNoProjectId(analysis, config, reportSpinner)
86
+ }
87
+ config.projectId = projectId
88
+ // we can always register just in case but normally we exit when
89
+ await projectConfig.registerProjectIdOnCliServices(config, projectId)
90
+ return await scaServicesUpload.scaTreeUpload(analysis, config, reportSpinner)
36
91
  }
37
92
 
38
93
  const processUpload = async (analysis, config, reportSpinner) => {
@@ -40,15 +95,17 @@ const processUpload = async (analysis, config, reportSpinner) => {
40
95
  // if cli tracked but no projectId -> registerNewProjectGroup THEN scaTreeUpload
41
96
  // if cli not tracked and no projectID -> noProjectUpload
42
97
  // if cli not tracked and projectID -> scaTreeUpload}
43
- let projectId = await projectConfig.getProjectIdByOrg(config)
44
98
 
45
- if (projectId === '') {
46
- return dealWithNoProjectId(analysis, config, reportSpinner)
99
+ if (config.repositoryId) {
100
+ return repoProcess(analysis, config, reportSpinner)
47
101
  }
48
102
 
49
- if (projectId) {
50
- config.projectId = projectId
51
- return await scaServicesUpload.scaTreeUpload(
103
+ if (config.track) {
104
+ return trackProcess(analysis, config, reportSpinner)
105
+ }
106
+
107
+ if (!config.track) {
108
+ return await scaServicesUpload.noProjectUpload(
52
109
  analysis,
53
110
  config,
54
111
  reportSpinner
@@ -57,5 +114,6 @@ const processUpload = async (analysis, config, reportSpinner) => {
57
114
  }
58
115
 
59
116
  module.exports = {
60
- processUpload
117
+ processUpload,
118
+ repoProcess
61
119
  }
@@ -1,89 +1,139 @@
1
1
  const fs = require('fs')
2
- const xml2js = require('xml2js')
2
+ const { XMLParser } = require('fast-xml-parser')
3
3
 
4
4
  const readPomFile = project => {
5
5
  const mavenFilePath = project.cwd + '/pom.xml'
6
6
  const projectFile = fs.readFileSync(mavenFilePath)
7
- let jsonPomFile
8
- xml2js.parseString(projectFile, (err, result) => {
9
- if (err) {
10
- throw err
11
- }
12
- const json = JSON.stringify(result, null)
13
- jsonPomFile = JSON.parse(json)
7
+ const parser = new XMLParser()
8
+ return parser.parse(projectFile)
9
+ }
10
+
11
+ const parsePomFile = jsonPomFile => {
12
+ console.log(JSON.stringify(jsonPomFile))
13
+ let dependencyTree = {}
14
+ let dependencies = []
15
+ let dependencyManagement = []
16
+
17
+ if (jsonPomFile.project && jsonPomFile.project.dependencies) {
18
+ dependencies = jsonPomFile.project.dependencies.dependency
19
+ }
20
+
21
+ if (jsonPomFile.project && jsonPomFile.project.dependencyManagement) {
22
+ dependencyManagement =
23
+ jsonPomFile.project.dependencyManagement.dependencies.dependency
24
+ }
25
+
26
+ //merge dependencies with dependencyManagement deps
27
+ //filter out any that don't appear in both by groupId and artifactId
28
+ const mergedAndFilteredDeps = dependencies.map(obj1 => {
29
+ const obj2 = dependencyManagement.find(
30
+ obj2 =>
31
+ obj2.groupId === obj1.groupId && obj2.artifactId === obj1.artifactId
32
+ )
33
+ return obj2 ? { ...obj1, ...obj2 } : obj1
14
34
  })
15
- return jsonPomFile
35
+
36
+ buildDependencies(mergedAndFilteredDeps, dependencyTree, jsonPomFile)
37
+ return {
38
+ parentPom: getParentDependency(jsonPomFile),
39
+ dependencyTree
40
+ }
41
+ }
42
+
43
+ const getParentDependency = jsonPomFile => {
44
+ if (jsonPomFile.project && jsonPomFile.project.parent) {
45
+ return buildParent(jsonPomFile.project.parent)
46
+ } else {
47
+ return undefined
48
+ }
16
49
  }
17
50
 
18
- const getFromVersionsTag = (dependencyName, versionIdentifier, jsonPomFile) => {
19
- // reading:
20
- // <!-- DEPENDENCY VERSIONS -->
21
- // <versions.animal-sniffer>1.16</versions.animal-sniffer>
22
- let formattedVersion = versionIdentifier.replace(/[{}]/g, '').replace('$', '')
51
+ const buildParent = parent => {
52
+ return {
53
+ group: parent.groupId,
54
+ name: parent.artifactId,
55
+ version: parent.version
56
+ }
57
+ }
23
58
 
24
- if (jsonPomFile.project.properties[0].hasOwnProperty([formattedVersion])) {
25
- return jsonPomFile.project.properties[0][formattedVersion][0]
59
+ const getVersionFromParent = (parentObj, dependencyWithoutVersion) => {
60
+ const { groupId, version } = parentObj
61
+ if (groupId === dependencyWithoutVersion.groupId) {
62
+ return version
26
63
  } else {
27
64
  return null
28
65
  }
29
66
  }
30
67
 
31
- const parsePomFile = jsonPomFile => {
32
- let dependencyTree = {}
33
- let parsedVersion
34
- let dependencies
35
- jsonPomFile.project.hasOwnProperty('dependencies')
36
- ? (dependencies = jsonPomFile.project.dependencies[0].dependency)
37
- : (dependencies =
38
- jsonPomFile.project.dependencyManagement[0].dependencies[0].dependency)
39
-
40
- for (let x in dependencies) {
41
- let dependencyObject = dependencies[x]
42
- if (!dependencyObject.hasOwnProperty('version')) {
43
- parsedVersion = getVersion(jsonPomFile, dependencyObject)
44
- } else {
45
- dependencyObject.version[0].includes('${versions.')
46
- ? (parsedVersion = getFromVersionsTag(
47
- dependencyObject.artifactId[0],
48
- dependencyObject.version[0],
49
- jsonPomFile
50
- ))
51
- : (parsedVersion = dependencyObject.version[0])
68
+ const getVersionFromProperties = (properties, dep) => {
69
+ if (properties && dep.version.includes('${')) {
70
+ const currentDepVersionPlaceholder = dep.version
71
+ .replace('${', '')
72
+ .replace('}', '')
73
+
74
+ for (const prop in properties) {
75
+ if (prop === currentDepVersionPlaceholder) {
76
+ return properties[prop]
77
+ }
52
78
  }
79
+ }
80
+ }
53
81
 
54
- let depName =
55
- dependencyObject.groupId +
56
- '/' +
57
- dependencyObject.artifactId +
58
- '@' +
59
- parsedVersion
60
-
61
- let parsedDependency = {
62
- name: dependencyObject.artifactId[0],
63
- group: dependencyObject.groupId[0],
64
- version: parsedVersion,
65
- directDependency: true,
66
- productionDependency: true,
67
- dependencies: []
82
+ const buildDependencies = (dependencies, dependencyTree, jsonPomFile) => {
83
+ const parent = getParentDependency(jsonPomFile)
84
+ for (const dep of dependencies) {
85
+ //sometimes versions are parsed as numbers, convert to string
86
+ const versionAsString = dep.version ? dep.version.toString() : dep.version
87
+ if (versionAsString && !versionAsString.includes('${')) {
88
+ const depName = dep.groupId + '/' + dep.artifactId + '@' + versionAsString
89
+ dependencyTree[depName] = buildDep(dep, dep.version)
90
+ } else if (
91
+ jsonPomFile.project.properties &&
92
+ dep.version &&
93
+ dep.version.includes('${')
94
+ ) {
95
+ searchAndBuildFromProperties(jsonPomFile, dep, dependencyTree)
96
+ } else if (!dep.version) {
97
+ if (parent && parent.version) {
98
+ //get version where group matches from parent tag
99
+ const { parent } = jsonPomFile.project
100
+ const parsedVersion = getVersionFromParent(parent, dep)
101
+ const depName = dep.groupId + '/' + dep.artifactId + '@' + parsedVersion
102
+ dependencyTree[depName] = buildDep(dep, parsedVersion)
103
+ }
68
104
  }
69
- dependencyTree[depName] = parsedDependency
70
105
  }
71
- return dependencyTree
72
106
  }
73
107
 
74
- const getVersion = (pomFile, dependencyWithoutVersion) => {
75
- let parentVersion = pomFile.project.parent[0].version[0]
76
- let parentGroupName = pomFile.project.parent[0].groupId[0]
77
- if (parentGroupName === dependencyWithoutVersion.groupId[0]) {
78
- return parentVersion
108
+ const searchAndBuildFromProperties = (jsonPomFile, dep, dependencyTree) => {
109
+ //get version from properties tag
110
+ const { properties } = jsonPomFile.project
111
+ let versionFromProperties = getVersionFromProperties(properties, dep)
112
+
113
+ if (versionFromProperties) {
114
+ versionFromProperties = versionFromProperties.toString()
115
+ const depName =
116
+ dep.groupId + '/' + dep.artifactId + '@' + versionFromProperties
117
+ dependencyTree[depName] = buildDep(dep, versionFromProperties)
79
118
  } else {
80
- return null
119
+ const depName = dep.groupId + '/' + dep.artifactId + '@' + null
120
+ dependencyTree[depName] = buildDep(dep, null)
121
+ }
122
+ }
123
+
124
+ const buildDep = (dep, version) => {
125
+ return {
126
+ name: dep.artifactId,
127
+ group: dep.groupId,
128
+ version: version,
129
+ directDependency: true,
130
+ productionDependency: true,
131
+ dependencies: []
81
132
  }
82
133
  }
83
134
 
84
135
  module.exports = {
85
136
  readPomFile,
86
- getVersion,
87
- parsePomFile,
88
- getFromVersionsTag
137
+ getVersionFromParent,
138
+ parsePomFile
89
139
  }
@@ -10,7 +10,6 @@ const autoDetection = require('../scan/autoDetection')
10
10
  const rootFile = require('../audit/languageAnalysisEngine/getProjectRootFilenames')
11
11
  const path = require('path')
12
12
  const i18n = require('i18n')
13
- const auditSave = require('../audit/save')
14
13
  const { auditUsageGuide } = require('../commands/audit/help')
15
14
  const repoMode = require('./repoMode')
16
15
  const { dotNetAnalysis } = require('./dotnet')
@@ -37,6 +36,8 @@ const processSca = async config => {
37
36
  process.exit(0)
38
37
  }
39
38
 
39
+ config.repo = config.repositoryId !== undefined
40
+
40
41
  const projectStats = await rootFile.getProjectStats(config.file)
41
42
  let pathWithFile = projectStats.isFile()
42
43
 
@@ -46,7 +47,7 @@ const processSca = async config => {
46
47
  : config.file
47
48
 
48
49
  filesFound = await autoDetection.autoDetectAuditFilesAndLanguages(config.file)
49
-
50
+ filesFound = await autoDetection.detectPackageManager(filesFound)
50
51
  autoDetection.dealWithMultiJava(filesFound)
51
52
 
52
53
  if (filesFound.length > 1 && pathWithFile) {
@@ -59,6 +60,7 @@ const processSca = async config => {
59
60
  //check we have the language and call the right analyser
60
61
  let messageToSend = undefined
61
62
  if (filesFound.length === 1) {
63
+ config.packageManager = filesFound[0]?.packageManager
62
64
  switch (Object.keys(filesFound[0])[0]) {
63
65
  case JAVA:
64
66
  config.language = JAVA
@@ -131,12 +133,11 @@ const processSca = async config => {
131
133
  const reportModelLibraryList = convertGenericToTypedReportModelSca(
132
134
  reportResponse.reportArray
133
135
  )
134
- auditReport.processAuditReport(config, reportModelLibraryList)
135
- if (config.save !== undefined) {
136
- await auditSave.auditSave(config, reportResponse.reportId)
137
- } else {
138
- console.log('Use contrast audit --save to generate an SBOM')
139
- }
136
+ await auditReport.processAuditReport(
137
+ config,
138
+ reportModelLibraryList,
139
+ reportResponse.reportId
140
+ )
140
141
 
141
142
  succeedSpinner(reportSpinner, i18n.__('auditSCAAnalysisComplete'))
142
143
 
@@ -9,11 +9,14 @@ const autoDetectFingerprintInfo = async (filePath, depth, config) => {
9
9
  let count = 0
10
10
  complexObj.forEach(i => {
11
11
  count++
12
- result.push({
13
- filePath: i,
14
- id: count.toString(),
15
- repositoryId: config.repositoryId
16
- })
12
+ if (!i.includes('package.json')) {
13
+ result.push({
14
+ filePath: i,
15
+ id: count.toString(),
16
+ repositoryId: config.repositoryId,
17
+ projectGroupId: config.projectGroupId
18
+ })
19
+ }
17
20
  })
18
21
 
19
22
  return result
@@ -43,15 +46,19 @@ const detectPackageManager = async array => {
43
46
  }
44
47
  if (i.filePath.includes('Pipfile')) {
45
48
  i['language'] = PYTHON
49
+ i['packageManager'] = 'PYPI'
46
50
  }
47
51
  if (i.filePath.includes('csproj')) {
48
52
  i['language'] = DOTNET
53
+ i['packageManager'] = 'NUGET'
49
54
  }
50
55
  if (i.filePath.includes('Gemfile')) {
51
56
  i['language'] = RUBY
57
+ i['packageManager'] = 'RUBYGEMS'
52
58
  }
53
59
  if (i.filePath.includes('go.mod')) {
54
60
  i['language'] = GO
61
+ i['packageManager'] = 'PKG'
55
62
  }
56
63
  })
57
64
  return array