@contrast/contrast 1.0.7 → 1.0.8

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 (79) hide show
  1. package/dist/audit/autodetection/autoDetectLanguage.js +3 -3
  2. package/dist/audit/catalogueApplication/catalogueApplication.js +23 -5
  3. package/dist/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +5 -5
  4. package/dist/audit/languageAnalysisEngine/getProjectRootFilenames.js +9 -9
  5. package/dist/audit/languageAnalysisEngine/index.js +2 -2
  6. package/dist/audit/languageAnalysisEngine/languageAnalysisFactory.js +5 -28
  7. package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +11 -4
  8. package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +39 -13
  9. package/dist/audit/languageAnalysisEngine/report/models/reportListModel.js +2 -1
  10. package/dist/audit/languageAnalysisEngine/report/models/severityCountModel.js +3 -0
  11. package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +35 -14
  12. package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +3 -3
  13. package/dist/audit/save.js +29 -0
  14. package/dist/commands/audit/auditController.js +21 -5
  15. package/dist/commands/audit/help.js +24 -1
  16. package/dist/commands/audit/processAudit.js +7 -1
  17. package/dist/commands/audit/saveFile.js +7 -3
  18. package/dist/commands/scan/sca/scaAnalysis.js +31 -10
  19. package/dist/common/HTTPClient.js +6 -0
  20. package/dist/common/versionChecker.js +19 -4
  21. package/dist/constants/constants.js +1 -1
  22. package/dist/constants/locales.js +12 -11
  23. package/dist/constants.js +9 -4
  24. package/dist/index.js +4 -3
  25. package/dist/sbom/generateSbom.js +4 -3
  26. package/dist/scaAnalysis/common/formatMessage.js +26 -5
  27. package/dist/scaAnalysis/common/treeUpload.js +0 -1
  28. package/dist/scaAnalysis/go/goReadDepFile.js +1 -3
  29. package/dist/scaAnalysis/java/analysis.js +5 -5
  30. package/dist/scaAnalysis/javascript/analysis.js +110 -0
  31. package/dist/scaAnalysis/javascript/index.js +41 -0
  32. package/dist/scaAnalysis/php/analysis.js +89 -0
  33. package/dist/scaAnalysis/php/index.js +10 -0
  34. package/dist/scaAnalysis/python/analysis.js +8 -7
  35. package/dist/scaAnalysis/ruby/analysis.js +8 -8
  36. package/dist/scaAnalysis/ruby/index.js +2 -2
  37. package/dist/scan/autoDetection.js +4 -4
  38. package/dist/scan/fileUtils.js +13 -2
  39. package/dist/utils/filterProjectPath.js +7 -2
  40. package/package.json +3 -3
  41. package/src/audit/autodetection/autoDetectLanguage.ts +3 -3
  42. package/src/audit/catalogueApplication/catalogueApplication.js +28 -6
  43. package/src/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +5 -5
  44. package/src/audit/languageAnalysisEngine/getProjectRootFilenames.js +11 -11
  45. package/src/audit/languageAnalysisEngine/index.js +2 -2
  46. package/src/audit/languageAnalysisEngine/languageAnalysisFactory.js +4 -32
  47. package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +20 -19
  48. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +67 -17
  49. package/src/audit/languageAnalysisEngine/report/models/reportListModel.ts +4 -1
  50. package/src/audit/languageAnalysisEngine/report/models/severityCountModel.ts +4 -0
  51. package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +49 -17
  52. package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +1 -1
  53. package/src/audit/save.js +32 -0
  54. package/src/commands/audit/auditController.ts +22 -13
  55. package/src/commands/audit/help.ts +24 -1
  56. package/src/commands/audit/processAudit.ts +6 -3
  57. package/src/commands/audit/saveFile.ts +5 -1
  58. package/src/commands/scan/sca/scaAnalysis.js +53 -22
  59. package/src/common/HTTPClient.js +7 -0
  60. package/src/common/versionChecker.ts +23 -4
  61. package/src/constants/constants.js +1 -1
  62. package/src/constants/locales.js +12 -11
  63. package/src/constants.js +9 -4
  64. package/src/index.ts +5 -3
  65. package/src/sbom/generateSbom.ts +1 -1
  66. package/src/scaAnalysis/common/formatMessage.js +27 -5
  67. package/src/scaAnalysis/common/treeUpload.js +0 -1
  68. package/src/scaAnalysis/go/goReadDepFile.js +1 -3
  69. package/src/scaAnalysis/java/analysis.js +5 -5
  70. package/src/scaAnalysis/javascript/analysis.js +127 -0
  71. package/src/scaAnalysis/javascript/index.js +56 -0
  72. package/src/scaAnalysis/php/analysis.js +98 -0
  73. package/src/scaAnalysis/php/index.js +11 -0
  74. package/src/scaAnalysis/python/analysis.js +8 -7
  75. package/src/scaAnalysis/ruby/analysis.js +8 -8
  76. package/src/scaAnalysis/ruby/index.js +2 -2
  77. package/src/scan/autoDetection.js +4 -4
  78. package/src/scan/fileUtils.js +13 -2
  79. package/src/utils/filterProjectPath.js +6 -2
@@ -12,7 +12,8 @@ import {
12
12
  findCVESeveritiesAndOrderByHighestPriority,
13
13
  findHighestSeverityCVE,
14
14
  findNameAndVersion,
15
- severityCountAllCVEs
15
+ severityCountAllCVEs,
16
+ severityCountAllLibraries
16
17
  } from './utils/reportUtils'
17
18
  import { SeverityCountModel } from './models/severityCountModel'
18
19
  import {
@@ -20,6 +21,13 @@ import {
20
21
  ReportOutputHeaderModel,
21
22
  ReportOutputModel
22
23
  } from './models/reportOutputModel'
24
+ import {
25
+ CRITICAL_COLOUR,
26
+ HIGH_COLOUR,
27
+ LOW_COLOUR,
28
+ MEDIUM_COLOUR,
29
+ NOTE_COLOUR
30
+ } from '../../../constants/constants'
23
31
 
24
32
  export const createLibraryHeader = (
25
33
  id: string,
@@ -27,11 +35,9 @@ export const createLibraryHeader = (
27
35
  numberOfCves: number
28
36
  ) => {
29
37
  numberOfVulnerableLibraries === 1
30
- ? console.log(
31
- ` Found 1 vulnerable library containing ${numberOfCves} CVE's`
32
- )
38
+ ? console.log(`Found 1 vulnerable library containing ${numberOfCves} CVEs`)
33
39
  : console.log(
34
- ` Found ${numberOfVulnerableLibraries} vulnerable libraries containing ${numberOfCves} CVE's `
40
+ `Found ${numberOfVulnerableLibraries} vulnerable libraries containing ${numberOfCves} CVEs `
35
41
  )
36
42
  }
37
43
 
@@ -43,10 +49,6 @@ export const getReport = async (config: any, reportId: string) => {
43
49
  if (res.statusCode === 200) {
44
50
  return res.body
45
51
  } else {
46
- console.log('config-------------------')
47
- console.log(config)
48
- console.log('reportId----------------')
49
- console.log(reportId)
50
52
  console.log(JSON.stringify(res))
51
53
  handleResponseErrors(res, 'report')
52
54
  }
@@ -81,7 +83,11 @@ export const printFormattedOutput = (
81
83
  new ReportCompositeKey(
82
84
  name,
83
85
  version,
84
- findHighestSeverityCVE(library.cveArray) as ReportSeverityModel
86
+ findHighestSeverityCVE(library.cveArray) as ReportSeverityModel,
87
+ severityCountAllCVEs(
88
+ library.cveArray,
89
+ new SeverityCountModel()
90
+ ).getTotal
85
91
  ),
86
92
  library.cveArray
87
93
  )
@@ -89,15 +95,23 @@ export const printFormattedOutput = (
89
95
  report.reportOutputList.push(newOutputModel)
90
96
  }
91
97
 
92
- const orderedOutputListLowestFirst = orderBy(
98
+ const outputOrderedByLowestSeverityAndLowestNumOfCvesFirst = orderBy(
93
99
  report.reportOutputList,
94
- reportListItem => reportListItem.compositeKey.highestSeverity.priority,
100
+ [
101
+ (reportListItem: ReportModelStructure) => {
102
+ return reportListItem.compositeKey.highestSeverity.priority
103
+ },
104
+ (reportListItem: ReportModelStructure) => {
105
+ return reportListItem.compositeKey.numberOfSeverities
106
+ }
107
+ ],
95
108
  ['desc']
96
109
  )
97
110
 
98
- let contrastHeaderNumCounter = 0
99
- for (const reportModel of orderedOutputListLowestFirst) {
100
- contrastHeaderNumCounter++
111
+ let contrastHeaderNumCounter =
112
+ outputOrderedByLowestSeverityAndLowestNumOfCvesFirst.length + 1
113
+ for (const reportModel of outputOrderedByLowestSeverityAndLowestNumOfCvesFirst) {
114
+ contrastHeaderNumCounter--
101
115
  const { libraryName, libraryVersion, highestSeverity } =
102
116
  reportModel.compositeKey
103
117
  const numOfCVEs = reportModel.cveArray.length
@@ -118,7 +132,22 @@ export const printFormattedOutput = (
118
132
  reportOutputModel.header.introducesMessage
119
133
  )
120
134
  console.log(reportOutputModel.body.issueMessage)
121
- console.log(reportOutputModel.body.adviceMessage)
135
+ console.log(reportOutputModel.body.adviceMessage + '\n')
136
+ }
137
+
138
+ const {
139
+ criticalMessage,
140
+ highMessage,
141
+ mediumMessage,
142
+ lowMessage,
143
+ noteMessage,
144
+ total
145
+ } = buildFooter(libraries)
146
+
147
+ if (total > 1) {
148
+ console.log(
149
+ `${criticalMessage} | ${highMessage} | ${mediumMessage} | ${lowMessage} | ${noteMessage}`
150
+ )
122
151
  }
123
152
  }
124
153
 
@@ -130,7 +159,7 @@ export function buildHeader(
130
159
  numOfCVEs: number
131
160
  ) {
132
161
  const vulnerabilityPluralised =
133
- numOfCVEs > 1 ? 'Vulnerabilities' : 'Vulnerability'
162
+ numOfCVEs > 1 ? 'vulnerabilities' : 'vulnerability'
134
163
  const formattedHeaderNum = buildFormattedHeaderNum(contrastHeaderNum)
135
164
 
136
165
  const vulnMessage = chalk
@@ -176,6 +205,27 @@ export function buildBody(cveArray: ReportCVEModel[]) {
176
205
  return new ReportOutputBodyModel(issueMessage, adviceMessage)
177
206
  }
178
207
 
208
+ const buildFooter = (libraries: ReportLibraryModel[]) => {
209
+ const { critical, high, medium, low, note, getTotal } =
210
+ severityCountAllLibraries(libraries)
211
+ const criticalMessage = chalk
212
+ .hex(CRITICAL_COLOUR)
213
+ .bold(`${critical} Critical`)
214
+ const highMessage = chalk.hex(HIGH_COLOUR).bold(`${high} High`)
215
+ const mediumMessage = chalk.hex(MEDIUM_COLOUR).bold(`${medium} Medium`)
216
+ const lowMessage = chalk.hex(LOW_COLOUR).bold(`${low} Low`)
217
+ const noteMessage = chalk.hex(NOTE_COLOUR).bold(`${note} Note`)
218
+
219
+ return {
220
+ criticalMessage,
221
+ highMessage,
222
+ mediumMessage,
223
+ lowMessage,
224
+ noteMessage,
225
+ total: getTotal
226
+ }
227
+ }
228
+
179
229
  export function buildFormattedHeaderNum(contrastHeaderNum: number) {
180
230
  let formattedHeaderNum
181
231
 
@@ -23,14 +23,17 @@ export class ReportCompositeKey {
23
23
  libraryName!: string
24
24
  libraryVersion!: string
25
25
  highestSeverity!: ReportSeverityModel
26
+ numberOfSeverities!: number
26
27
 
27
28
  constructor(
28
29
  libraryName: string,
29
30
  libraryVersion: string,
30
- highestSeverity: ReportSeverityModel
31
+ highestSeverity: ReportSeverityModel,
32
+ numberOfSeverities: number
31
33
  ) {
32
34
  this.libraryName = libraryName
33
35
  this.libraryVersion = libraryVersion
34
36
  this.highestSeverity = highestSeverity
37
+ this.numberOfSeverities = numberOfSeverities
35
38
  }
36
39
  }
@@ -13,4 +13,8 @@ export class SeverityCountModel {
13
13
  this.low = 0
14
14
  this.note = 0
15
15
  }
16
+
17
+ get getTotal(): number {
18
+ return this.critical + this.high + this.medium + this.low + this.note
19
+ }
16
20
  }
@@ -4,9 +4,11 @@ import {
4
4
  printVulnerabilityResponse
5
5
  } from './commonReportingFunctions'
6
6
  import {
7
- convertGenericToTypedLibraries,
7
+ convertGenericToTypedLibraryVulns,
8
8
  severityCountAllLibraries
9
9
  } from './utils/reportUtils'
10
+ import i18n from 'i18n'
11
+ import chalk from 'chalk'
10
12
 
11
13
  export async function vulnerabilityReport(
12
14
  analysis: any,
@@ -17,11 +19,9 @@ export async function vulnerabilityReport(
17
19
 
18
20
  if (reportResponse !== undefined) {
19
21
  const id = applicationId
20
- const name = analysis.config.applicationName
21
22
  formatVulnerabilityOutput(
22
23
  reportResponse.vulnerabilities,
23
24
  id,
24
- name,
25
25
  analysis.config
26
26
  )
27
27
  }
@@ -30,27 +30,59 @@ export async function vulnerabilityReport(
30
30
  export function formatVulnerabilityOutput(
31
31
  libraryVulnerabilityResponse: any,
32
32
  id: string,
33
- name: string,
34
33
  config: any
35
34
  ) {
36
- const vulnerableLibraries = convertGenericToTypedLibraries(
35
+ const vulnerableLibraries = convertGenericToTypedLibraryVulns(
37
36
  libraryVulnerabilityResponse
38
37
  )
39
38
 
40
39
  const numberOfVulnerableLibraries = vulnerableLibraries.length
41
- let numberOfCves = 0
42
- vulnerableLibraries.forEach(lib => (numberOfCves += lib.cveArray.length))
43
40
 
44
- createLibraryHeader(id, numberOfVulnerableLibraries, numberOfCves)
41
+ if (numberOfVulnerableLibraries === 0) {
42
+ console.log(i18n.__('scanNoVulnerabilitiesFound'))
43
+ console.log(i18n.__('scanNoVulnerabilitiesFoundSecureCode'))
44
+ console.log(i18n.__('scanNoVulnerabilitiesFoundGoodWork'))
45
+ console.log(
46
+ chalk.bold(`Found ${numberOfVulnerableLibraries} vulnerabilities`)
47
+ )
48
+ console.log(
49
+ i18n.__(
50
+ 'foundDetailedVulnerabilities',
51
+ String(0),
52
+ String(0),
53
+ String(0),
54
+ String(0),
55
+ String(0)
56
+ )
57
+ )
58
+ } else {
59
+ let numberOfCves = 0
60
+ vulnerableLibraries.forEach(lib => (numberOfCves += lib.cveArray.length))
45
61
 
46
- const hasSomeVulnerabilitiesReported = printVulnerabilityResponse(
47
- vulnerableLibraries,
48
- config
49
- )
62
+ createLibraryHeader(id, numberOfVulnerableLibraries, numberOfCves)
63
+
64
+ const hasSomeVulnerabilitiesReported = printVulnerabilityResponse(
65
+ vulnerableLibraries,
66
+ config
67
+ )
68
+
69
+ return [
70
+ hasSomeVulnerabilitiesReported,
71
+ numberOfCves,
72
+ severityCountAllLibraries(vulnerableLibraries)
73
+ ]
74
+ }
75
+ }
76
+
77
+ export async function vulnerabilityReportV2(config: any, reportId: string) {
78
+ const reportResponse = await getReport(config, reportId)
50
79
 
51
- return [
52
- hasSomeVulnerabilitiesReported,
53
- numberOfCves,
54
- severityCountAllLibraries(vulnerableLibraries)
55
- ]
80
+ if (reportResponse !== undefined) {
81
+ const name = config.applicationName
82
+ formatVulnerabilityOutput(
83
+ reportResponse.vulnerabilities,
84
+ config.applicationId,
85
+ config
86
+ )
87
+ }
56
88
  }
@@ -67,7 +67,7 @@ export function findCVESeverity(cve: ReportCVEModel) {
67
67
  }
68
68
  }
69
69
 
70
- export function convertGenericToTypedLibraries(libraries: any) {
70
+ export function convertGenericToTypedLibraryVulns(libraries: any) {
71
71
  return Object.entries(libraries).map(([name, cveArray]) => {
72
72
  return new ReportLibraryModel(name, cveArray as ReportCVEModel[])
73
73
  })
@@ -0,0 +1,32 @@
1
+ const fs = require('fs')
2
+ const i18n = require('i18n')
3
+ const chalk = require('chalk')
4
+ const save = require('../commands/audit/saveFile')
5
+ const sbom = require('../sbom/generateSbom')
6
+
7
+ async function auditSave(config) {
8
+ if (config.save) {
9
+ if (config.save.toLowerCase() === 'sbom') {
10
+ save.saveFile(config, await sbom.generateSbom(config))
11
+
12
+ const filename = `${config.applicationId}-sbom-cyclonedx.json`
13
+ if (fs.existsSync(filename)) {
14
+ console.log(i18n.__('auditSBOMSaveSuccess') + ` - ${filename}`)
15
+ } else {
16
+ console.log(
17
+ chalk.yellow.bold(
18
+ `\n Unable to save ${filename} Software Bill of Materials (SBOM)`
19
+ )
20
+ )
21
+ }
22
+ } else {
23
+ console.log(i18n.__('auditBadFiletypeSpecifiedForSave'))
24
+ }
25
+ } else if (config.save === null) {
26
+ console.log(i18n.__('auditNoFiletypeSpecifiedForSave'))
27
+ }
28
+ }
29
+
30
+ module.exports = {
31
+ auditSave
32
+ }
@@ -3,7 +3,6 @@ import commonApi from '../../audit/languageAnalysisEngine/commonApi'
3
3
 
4
4
  const identifyLanguageAE = require('./../../audit/languageAnalysisEngine')
5
5
  const languageFactory = require('../../audit/languageAnalysisEngine/languageAnalysisFactory')
6
- const { v4: uuidv4 } = require('uuid')
7
6
 
8
7
  export const dealWithNoAppId = async (config: { [x: string]: string }) => {
9
8
  let appID: string
@@ -14,14 +13,15 @@ export const dealWithNoAppId = async (config: { [x: string]: string }) => {
14
13
  return await catalogueApplication(config)
15
14
  }
16
15
  if (!appID && !config.applicationName) {
17
- config.applicationName = uuidv4()
18
- return await catalogueApplication(config)
16
+ config.applicationName = getAppName(config.file) as string
17
+ // @ts-ignore
18
+ appID = await commonApi.returnAppId(config)
19
+ if (!appID) {
20
+ return await catalogueApplication(config)
21
+ }
19
22
  }
20
- // @ts-ignore
21
- } catch (e) {
22
- // @ts-ignore
23
+ } catch (e: any) {
23
24
  if (e.toString().includes('tunneling socket could not be established')) {
24
- // @ts-ignore
25
25
  console.log(e.message.toString())
26
26
  console.log(
27
27
  'There seems to be an issue with your proxy, please check and try again'
@@ -37,10 +37,19 @@ export const startAudit = async (config: { [key: string]: string }) => {
37
37
  // @ts-ignore
38
38
  config.applicationId = await dealWithNoAppId(config)
39
39
  }
40
- identifyLanguageAE(
41
- config.projectPath,
42
- languageFactory,
43
- config.applicationId,
44
- config
45
- )
40
+ identifyLanguageAE(config.file, languageFactory, config.applicationId, config)
41
+ }
42
+
43
+ export const getAppName = (file: string) => {
44
+ const last = file.charAt(file.length - 1)
45
+ if (last !== '/') {
46
+ return file.split('/').pop()
47
+ } else {
48
+ const str = removeLastChar(file)
49
+ return str.split('/').pop()
50
+ }
51
+ }
52
+
53
+ const removeLastChar = (str: string) => {
54
+ return str.substring(0, str.length - 1)
46
55
  }
@@ -41,7 +41,30 @@ const auditUsageGuide = commandLineUsage([
41
41
  },
42
42
  {
43
43
  header: i18n.__('constantsAuditOptions'),
44
- optionList: constants.commandLineDefinitions.auditOptionDefinitions
44
+ optionList: constants.commandLineDefinitions.auditOptionDefinitions,
45
+ hide: [
46
+ 'application-id',
47
+ 'application-name',
48
+ 'organization-id',
49
+ 'api-key',
50
+ 'authorization',
51
+ 'host',
52
+ 'proxy',
53
+ 'help',
54
+ 'ff',
55
+ 'ignore-cert-errors',
56
+ 'verbose',
57
+ 'debug',
58
+ 'experimental',
59
+ 'tags',
60
+ 'sub-project',
61
+ 'code',
62
+ 'maven-settings-path',
63
+ 'language',
64
+ 'experimental',
65
+ 'app-groups',
66
+ 'metadata'
67
+ ]
45
68
  }
46
69
  ])
47
70
 
@@ -1,6 +1,7 @@
1
1
  import { startAudit } from './auditController'
2
2
  import { getAuditConfig } from './auditConfig'
3
3
  import { auditUsageGuide } from './help'
4
+ import { processSca } from '../scan/sca/scaAnalysis'
4
5
 
5
6
  export type parameterInput = string[]
6
7
 
@@ -11,9 +12,11 @@ export const processAudit = async (argv: parameterInput) => {
11
12
  }
12
13
  const config = getAuditConfig(argv)
13
14
 
14
- // console.log(config)
15
-
16
- const auditResults = await startAudit(config)
15
+ if (config.experimental) {
16
+ await processSca(config)
17
+ } else {
18
+ await startAudit(config)
19
+ }
17
20
  }
18
21
 
19
22
  const printHelpMessage = () => {
@@ -1,6 +1,10 @@
1
1
  import fs from 'fs'
2
2
 
3
- export default function saveFile(config: any, rawResults: any) {
3
+ export const saveFile = (config: any, rawResults: any) => {
4
4
  const fileName = `${config.applicationId}-sbom-cyclonedx.json`
5
5
  fs.writeFileSync(fileName, JSON.stringify(rawResults))
6
6
  }
7
+
8
+ module.exports = {
9
+ saveFile
10
+ }
@@ -6,19 +6,35 @@ const {
6
6
  } = require('../../../scan/autoDetection')
7
7
  const auditController = require('../../audit/auditController')
8
8
  const {
9
- supportedLanguages: { JAVA, GO, RUBY, PYTHON }
9
+ supportedLanguages: { JAVA, GO, PYTHON, RUBY, JAVASCRIPT, NODE, PHP }
10
10
  } = require('../../../audit/languageAnalysisEngine/constants')
11
11
  const goAnalysis = require('../../../scaAnalysis/go/goAnalysis')
12
+ const phpAnalysis = require('../../../scaAnalysis/php/index')
12
13
  const { rubyAnalysis } = require('../../../scaAnalysis/ruby')
13
14
  const { pythonAnalysis } = require('../../../scaAnalysis/python')
15
+ const javascriptAnalysis = require('../../../scaAnalysis/javascript')
16
+ const {
17
+ pollForSnapshotCompletition
18
+ } = require('../../../audit/languageAnalysisEngine/sendSnapshot')
19
+ const {
20
+ returnOra,
21
+ startSpinner,
22
+ succeedSpinner
23
+ } = require('../../../utils/oraWrapper')
24
+ const i18n = require('i18n')
25
+ const {
26
+ vulnerabilityReportV2
27
+ } = require('../../../audit/languageAnalysisEngine/report/reportingFeature')
28
+ const auditSave = require('../../../audit/save')
14
29
 
15
30
  const processSca = async config => {
16
31
  let filesFound
17
- if (config.projectPath) {
18
- filesFound = manualDetectAuditFilesAndLanguages(config.projectPath)
32
+ if (config.file) {
33
+ config.file = config.file.concat('/')
34
+ filesFound = await manualDetectAuditFilesAndLanguages(config.file)
19
35
  } else {
20
36
  filesFound = await autoDetection.autoDetectAuditFilesAndLanguages(config)
21
- config.projectPath = process.cwd()
37
+ config.file = process.cwd().concat('/')
22
38
  }
23
39
 
24
40
  // files found looks like [ { javascript: [ Array ] } ]
@@ -31,26 +47,25 @@ const processSca = async config => {
31
47
  messageToSend = javaAnalysis.javaAnalysis(config, filesFound[0])
32
48
  config.language = JAVA
33
49
  break
34
- // case 'javascript':
35
- // // code block
36
- // break;
37
- // case 'dotnet':
38
- // // code block
39
- // break;
40
- case RUBY:
41
- messageToSend = rubyAnalysis(config, filesFound[0])
42
- config.language = RUBY
50
+ case JAVASCRIPT:
51
+ messageToSend = await javascriptAnalysis.jsAnalysis(
52
+ config,
53
+ filesFound[0]
54
+ )
55
+ config.language = NODE
43
56
  break
44
57
  case PYTHON:
45
58
  messageToSend = pythonAnalysis(config, filesFound[0])
46
59
  config.language = PYTHON
47
60
  break
48
- // case 'ruby':
49
- // // code block
50
- // break;
51
- // case 'php':
52
- // // code block
53
- // break;
61
+ case RUBY:
62
+ messageToSend = rubyAnalysis(config, filesFound[0])
63
+ config.language = RUBY
64
+ break
65
+ case 'PHP':
66
+ messageToSend = phpAnalysis.phpAnalysis(config, filesFound[0])
67
+ config.language = PHP
68
+ break
54
69
  case GO:
55
70
  messageToSend = goAnalysis.goAnalysis(config, filesFound[0])
56
71
  config.language = GO
@@ -65,14 +80,30 @@ const processSca = async config => {
65
80
  config.applicationId = await auditController.dealWithNoAppId(config)
66
81
  }
67
82
  //send message to TS
68
- console.log('processing dependencies')
69
- const response = await treeUpload.commonSendSnapShot(messageToSend, config)
83
+ const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'))
84
+ startSpinner(reportSpinner)
85
+ const snapshotResponse = await treeUpload.commonSendSnapShot(
86
+ messageToSend,
87
+ config
88
+ )
89
+
90
+ //poll for completion
91
+ await pollForSnapshotCompletition(
92
+ config,
93
+ snapshotResponse.id,
94
+ reportSpinner
95
+ )
96
+ succeedSpinner(reportSpinner, 'Contrast SCA audit complete')
97
+
98
+ await vulnerabilityReportV2(config, snapshotResponse.id)
99
+
100
+ await auditSave.auditSave(config)
70
101
  } else {
71
102
  if (filesFound.length === 0) {
72
103
  console.log('no compatible dependency files detected. Continuing...')
73
104
  } else {
74
105
  console.log(
75
- 'multiple language files detected, please use --project-path to specify a directory or the file where dependencies are declared'
106
+ 'multiple language files detected, please use --file to specify a directory or the file where dependencies are declared'
76
107
  )
77
108
  }
78
109
  }
@@ -339,6 +339,13 @@ HTTPClient.prototype.getSbom = function getSbom(config) {
339
339
  return requestUtils.sendRequest({ method: 'get', options })
340
340
  }
341
341
 
342
+ HTTPClient.prototype.getLatestVersion = function getLatestVersion() {
343
+ const options = _.cloneDeep(this.requestOptions)
344
+ options.url =
345
+ 'https://pkg.contrastsecurity.com/artifactory/cli/latest-version.txt'
346
+ return requestUtils.sendRequest({ method: 'get', options })
347
+ }
348
+
342
349
  // analytics
343
350
 
344
351
  HTTPClient.prototype.postAnalyticsFunction = function (config, provider, body) {
@@ -1,12 +1,31 @@
1
- import latestVersion from 'latest-version'
2
1
  import { APP_VERSION } from '../constants/constants'
3
2
  import boxen from 'boxen'
4
3
  import chalk from 'chalk'
5
4
  import semver from 'semver'
5
+ import commonApi from '../utils/commonApi'
6
+ import { constants } from 'http2'
7
+ import { ContrastConf } from '../utils/getConfig'
6
8
 
7
- export async function findLatestCLIVersion(updateMessageHidden: boolean) {
8
- if (!updateMessageHidden) {
9
- const latestCLIVersion = await latestVersion('@contrast/contrast')
9
+ const getLatestVersion = async (config: any) => {
10
+ const client = commonApi.getHttpClient(config)
11
+ try {
12
+ const res = await client.getLatestVersion()
13
+ if (res.statusCode === constants.HTTP_STATUS_OK) {
14
+ return res.body
15
+ }
16
+ } catch (e) {
17
+ return
18
+ }
19
+ }
20
+
21
+ // @ts-ignore
22
+ export async function findLatestCLIVersion(config: ContrastConf) {
23
+ const messageHidden = config.get('updateMessageHidden') as boolean
24
+
25
+ if (!messageHidden) {
26
+ let latestCLIVersion: string = await getLatestVersion(config)
27
+ //strip key
28
+ latestCLIVersion = latestCLIVersion.substring(8)
10
29
 
11
30
  if (semver.lt(APP_VERSION, latestCLIVersion)) {
12
31
  const updateAvailableMessage = `Update available ${chalk.yellow(
@@ -13,7 +13,7 @@ const MEDIUM = 'MEDIUM'
13
13
  const HIGH = 'HIGH'
14
14
  const CRITICAL = 'CRITICAL'
15
15
  const APP_NAME = 'contrast'
16
- const APP_VERSION = '1.0.7'
16
+ const APP_VERSION = '1.0.8'
17
17
  const TIMEOUT = 120000
18
18
  const HIGH_COLOUR = '#ff9900'
19
19
  const CRITICAL_COLOUR = '#e35858'