@contrast/contrast 1.0.5 → 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 (138) hide show
  1. package/.prettierignore +0 -5
  2. package/dist/audit/autodetection/autoDetectLanguage.js +3 -3
  3. package/dist/audit/catalogueApplication/catalogueApplication.js +23 -5
  4. package/dist/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +4 -2
  5. package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +2 -1
  6. package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +2 -1
  7. package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +2 -1
  8. package/dist/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +5 -5
  9. package/dist/audit/languageAnalysisEngine/getProjectRootFilenames.js +9 -9
  10. package/dist/audit/languageAnalysisEngine/index.js +2 -2
  11. package/dist/audit/languageAnalysisEngine/languageAnalysisFactory.js +6 -27
  12. package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +25 -5
  13. package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +99 -20
  14. package/dist/audit/languageAnalysisEngine/report/models/reportListModel.js +2 -1
  15. package/dist/audit/languageAnalysisEngine/report/models/reportOutputModel.js +24 -0
  16. package/dist/audit/languageAnalysisEngine/report/models/reportSeverityModel.js +3 -1
  17. package/dist/audit/languageAnalysisEngine/report/models/severityCountModel.js +16 -0
  18. package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +35 -14
  19. package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +58 -47
  20. package/dist/audit/languageAnalysisEngine/sendSnapshot.js +65 -3
  21. package/dist/audit/save.js +29 -0
  22. package/dist/commands/audit/auditController.js +22 -6
  23. package/dist/commands/audit/help.js +24 -1
  24. package/dist/commands/audit/processAudit.js +8 -2
  25. package/dist/commands/audit/saveFile.js +7 -3
  26. package/dist/commands/scan/processScan.js +1 -1
  27. package/dist/commands/scan/sca/scaAnalysis.js +48 -11
  28. package/dist/common/HTTPClient.js +56 -15
  29. package/dist/common/errorHandling.js +6 -1
  30. package/dist/common/versionChecker.js +20 -5
  31. package/dist/constants/constants.js +13 -3
  32. package/dist/constants/locales.js +15 -12
  33. package/dist/constants.js +9 -4
  34. package/dist/index.js +4 -3
  35. package/dist/lambda/analytics.js +11 -0
  36. package/dist/lambda/lambda.js +35 -4
  37. package/dist/lambda/types.js +13 -0
  38. package/dist/sbom/generateSbom.js +4 -3
  39. package/dist/scaAnalysis/common/formatMessage.js +46 -1
  40. package/dist/scaAnalysis/common/treeUpload.js +1 -3
  41. package/dist/scaAnalysis/go/goAnalysis.js +17 -0
  42. package/dist/scaAnalysis/go/goParseDeps.js +158 -0
  43. package/dist/scaAnalysis/go/goReadDepFile.js +21 -0
  44. package/dist/scaAnalysis/java/analysis.js +11 -22
  45. package/dist/scaAnalysis/java/index.js +6 -6
  46. package/dist/scaAnalysis/java/javaBuildDepsParser.js +14 -1
  47. package/dist/scaAnalysis/javascript/analysis.js +110 -0
  48. package/dist/scaAnalysis/javascript/index.js +41 -0
  49. package/dist/scaAnalysis/php/analysis.js +89 -0
  50. package/dist/scaAnalysis/php/index.js +10 -0
  51. package/dist/scaAnalysis/python/analysis.js +42 -0
  52. package/dist/scaAnalysis/python/index.js +10 -0
  53. package/dist/scaAnalysis/ruby/analysis.js +226 -0
  54. package/dist/scaAnalysis/ruby/index.js +10 -0
  55. package/dist/scan/autoDetection.js +8 -4
  56. package/dist/scan/fileUtils.js +26 -8
  57. package/dist/scan/formatScanOutput.js +18 -17
  58. package/dist/scan/models/groupedResultsModel.js +1 -1
  59. package/dist/scan/models/scanResultsModel.js +3 -1
  60. package/dist/scan/populateProjectIdAndProjectName.js +2 -1
  61. package/dist/scan/scan.js +5 -3
  62. package/dist/scan/scanConfig.js +6 -1
  63. package/dist/scan/scanController.js +26 -6
  64. package/dist/scan/scanResults.js +20 -6
  65. package/dist/utils/commonApi.js +4 -1
  66. package/dist/utils/filterProjectPath.js +7 -2
  67. package/dist/utils/oraWrapper.js +5 -1
  68. package/package.json +13 -9
  69. package/src/audit/autodetection/autoDetectLanguage.ts +3 -3
  70. package/src/audit/catalogueApplication/catalogueApplication.js +28 -7
  71. package/src/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +11 -8
  72. package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +2 -1
  73. package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +2 -1
  74. package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +2 -1
  75. package/src/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +5 -5
  76. package/src/audit/languageAnalysisEngine/getProjectRootFilenames.js +11 -11
  77. package/src/audit/languageAnalysisEngine/index.js +2 -2
  78. package/src/audit/languageAnalysisEngine/languageAnalysisFactory.js +11 -31
  79. package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +35 -32
  80. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +179 -25
  81. package/src/audit/languageAnalysisEngine/report/models/reportLibraryModel.ts +3 -3
  82. package/src/audit/languageAnalysisEngine/report/models/reportListModel.ts +18 -11
  83. package/src/audit/languageAnalysisEngine/report/models/reportOutputModel.ts +29 -0
  84. package/src/audit/languageAnalysisEngine/report/models/reportSeverityModel.ts +12 -3
  85. package/src/audit/languageAnalysisEngine/report/models/severityCountModel.ts +20 -0
  86. package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +50 -18
  87. package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +88 -66
  88. package/src/audit/languageAnalysisEngine/sendSnapshot.js +78 -3
  89. package/src/audit/save.js +32 -0
  90. package/src/commands/audit/auditController.ts +23 -15
  91. package/src/commands/audit/help.ts +24 -1
  92. package/src/commands/audit/processAudit.ts +7 -4
  93. package/src/commands/audit/saveFile.ts +5 -1
  94. package/src/commands/scan/processScan.js +2 -1
  95. package/src/commands/scan/sca/scaAnalysis.js +70 -29
  96. package/src/common/HTTPClient.js +72 -25
  97. package/src/common/errorHandling.ts +10 -1
  98. package/src/common/versionChecker.ts +24 -5
  99. package/src/constants/constants.js +13 -3
  100. package/src/constants/locales.js +15 -12
  101. package/src/constants.js +9 -4
  102. package/src/index.ts +5 -3
  103. package/src/lambda/analytics.ts +9 -0
  104. package/src/lambda/arn.ts +2 -1
  105. package/src/lambda/lambda.ts +37 -17
  106. package/src/lambda/types.ts +35 -0
  107. package/src/lambda/utils.ts +2 -7
  108. package/src/sbom/generateSbom.ts +1 -1
  109. package/src/scaAnalysis/common/formatMessage.js +51 -1
  110. package/src/scaAnalysis/common/treeUpload.js +1 -6
  111. package/src/scaAnalysis/go/goAnalysis.js +19 -0
  112. package/src/scaAnalysis/go/goParseDeps.js +203 -0
  113. package/src/scaAnalysis/go/goReadDepFile.js +30 -0
  114. package/src/scaAnalysis/java/analysis.js +15 -32
  115. package/src/scaAnalysis/java/index.js +6 -6
  116. package/src/scaAnalysis/java/javaBuildDepsParser.js +15 -2
  117. package/src/scaAnalysis/javascript/analysis.js +127 -0
  118. package/src/scaAnalysis/javascript/index.js +56 -0
  119. package/src/scaAnalysis/php/analysis.js +98 -0
  120. package/src/scaAnalysis/php/index.js +11 -0
  121. package/src/scaAnalysis/python/analysis.js +49 -0
  122. package/src/scaAnalysis/python/index.js +11 -0
  123. package/src/scaAnalysis/ruby/analysis.js +282 -0
  124. package/src/scaAnalysis/ruby/index.js +11 -0
  125. package/src/scan/autoDetection.js +11 -7
  126. package/src/scan/fileUtils.js +27 -8
  127. package/src/scan/formatScanOutput.ts +26 -18
  128. package/src/scan/models/groupedResultsModel.ts +3 -3
  129. package/src/scan/models/resultContentModel.ts +1 -1
  130. package/src/scan/models/scanResultsModel.ts +5 -2
  131. package/src/scan/populateProjectIdAndProjectName.js +3 -1
  132. package/src/scan/scan.ts +8 -6
  133. package/src/scan/scanConfig.js +5 -1
  134. package/src/scan/scanController.js +30 -9
  135. package/src/scan/scanResults.js +31 -10
  136. package/src/utils/commonApi.js +4 -1
  137. package/src/utils/filterProjectPath.js +6 -2
  138. package/src/utils/oraWrapper.js +6 -1
@@ -0,0 +1,56 @@
1
+ const analysis = require('./analysis')
2
+ const i18n = require('i18n')
3
+ const formatMessage = require('../common/formatMessage')
4
+
5
+ const jsAnalysis = async (config, languageFiles) => {
6
+ if (
7
+ languageFiles.JAVASCRIPT.includes('package-lock.json') &&
8
+ languageFiles.JAVASCRIPT.includes('yarn.lock')
9
+ ) {
10
+ console.log(i18n.__('languageAnalysisMultipleLanguages1'))
11
+ return
12
+ }
13
+ return buildNodeTree(config, languageFiles.JAVASCRIPT)
14
+ }
15
+ const buildNodeTree = async (config, files) => {
16
+ let analysis = await readFiles(config, files)
17
+ const rawNode = await parseFiles(config, files, analysis)
18
+ return formatMessage.createJavaScriptTSMessage(rawNode)
19
+ }
20
+
21
+ const readFiles = async (config, files) => {
22
+ let js = {}
23
+
24
+ js.packageJSON = JSON.parse(
25
+ await analysis.readFile(config, files, 'package.json')
26
+ )
27
+
28
+ if (files.includes('package-lock.json')) {
29
+ js.rawLockFileContents = await analysis.readFile(
30
+ config,
31
+ files,
32
+ 'package-lock.json'
33
+ )
34
+ }
35
+ if (files.includes('yarn.lock')) {
36
+ js.yarn = {}
37
+ js.yarn = await analysis.readYarn(config, files, 'yarn.lock')
38
+ }
39
+
40
+ return js
41
+ }
42
+
43
+ const parseFiles = async (config, files, js) => {
44
+ if (files.includes('package-lock.json')) {
45
+ js.npmLockFile = await analysis.parseNpmLockFile(js)
46
+ }
47
+ if (files.includes('yarn.lock')) {
48
+ js = await analysis.parseYarnLockFile(js)
49
+ }
50
+
51
+ return js
52
+ }
53
+
54
+ module.exports = {
55
+ jsAnalysis
56
+ }
@@ -0,0 +1,98 @@
1
+ const fs = require('fs')
2
+ const i18n = require('i18n')
3
+ const _ = require('lodash')
4
+
5
+ let php = {}
6
+
7
+ const readProjectFile = (projectPath, customFile) => {
8
+ const filePath = filePathForWindows(projectPath + customFile)
9
+ try {
10
+ php.composerJSON = JSON.parse(fs.readFileSync(filePath, 'utf8')) //wrong here
11
+ php.composerJSON.dependencies = php.composerJSON.require
12
+ php.composerJSON.devDependencies = php.composerJSON['require-dev']
13
+ return php
14
+ } catch (err) {
15
+ console.log(err.message.toString())
16
+ }
17
+ }
18
+
19
+ const readAndParseLockFile = (projectPath, customFile) => {
20
+ const filePath = filePathForWindows(projectPath + customFile)
21
+ try {
22
+ php.rawLockFileContents = JSON.parse(fs.readFileSync(filePath, 'utf8'))
23
+ php.lockFile = php.rawLockFileContents
24
+ let packages = _.keyBy(php.lockFile.packages, 'name')
25
+ let packagesDev = _.keyBy(php.lockFile['packages-dev'], 'name')
26
+ php.lockFile.dependencies = _.merge(packages, packagesDev)
27
+
28
+ const listOfTopDep = Object.keys(php.lockFile.dependencies)
29
+
30
+ Object.entries(php.lockFile.dependencies).forEach(([key, value]) => {
31
+ if (value.require) {
32
+ const listOfRequiresDep = Object.keys(value.require)
33
+ listOfRequiresDep.forEach(dep => {
34
+ if (!listOfTopDep.includes(dep)) {
35
+ addChildDepToLockFileAsOwnObj(php, value['require'], dep)
36
+ }
37
+ })
38
+ }
39
+
40
+ if (value['require-dev']) {
41
+ const listOfRequiresDep = Object.keys(value['require-dev'])
42
+ listOfRequiresDep.forEach(dep => {
43
+ if (!listOfTopDep.includes(dep)) {
44
+ addChildDepToLockFileAsOwnObj(php, value['require-dev'], dep)
45
+ }
46
+ })
47
+ }
48
+ })
49
+ formatParentDepToLockFile(php)
50
+ delete php.rawLockFileContents
51
+ return php
52
+ } catch (err) {
53
+ return console.log(i18n.__('phpParseComposerLock', php) + `${err.message}`) // not sure on this
54
+ }
55
+ }
56
+
57
+ const getPhpDeps = (config, files) => {
58
+ try {
59
+ return (
60
+ readProjectFile(config.file, files[0].projectFilename),
61
+ readAndParseLockFile(config.file, files[1].lockFilename)
62
+ )
63
+ } catch (err) {
64
+ console.log(err.message.toString())
65
+ process.exit(1)
66
+ }
67
+ }
68
+
69
+ const filePathForWindows = path => {
70
+ if (process.platform === 'win32') {
71
+ path = path.replace(/\//g, '\\')
72
+ }
73
+ return path
74
+ }
75
+
76
+ function addChildDepToLockFileAsOwnObj(php, depObj, key) {
77
+ php.lockFile.dependencies[key] = { version: depObj[key] }
78
+ }
79
+
80
+ function formatParentDepToLockFile(php) {
81
+ for (const [key, value] of Object.entries(php.lockFile.dependencies)) {
82
+ let requires = {}
83
+ for (const [childKey, childValue] of Object.entries(value)) {
84
+ if (childKey === 'require' || childKey === 'require-dev') {
85
+ requires = _.merge(requires, childValue)
86
+ php.lockFile.dependencies[key].requires = requires
87
+ delete php.lockFile.dependencies[key].require
88
+ delete php.lockFile.dependencies[key]['require-dev']
89
+ }
90
+ }
91
+ }
92
+ }
93
+
94
+ module.exports = {
95
+ getPhpDeps,
96
+ readAndParseLockFile,
97
+ readProjectFile
98
+ }
@@ -0,0 +1,11 @@
1
+ const { getPhpDeps } = require('./analysis')
2
+ const { createPhpTSMessage } = require('../common/formatMessage')
3
+
4
+ const phpAnalysis = (config, languageFiles) => {
5
+ const phpDeps = getPhpDeps(config, languageFiles.PHP)
6
+ return createPhpTSMessage(phpDeps)
7
+ }
8
+
9
+ module.exports = {
10
+ phpAnalysis
11
+ }
@@ -0,0 +1,49 @@
1
+ const multiReplace = require('string-multiple-replace')
2
+ const fs = require('fs')
3
+
4
+ const readAndParseProjectFile = file => {
5
+ const filePath = filePathForWindows(file + '/Pipfile')
6
+ const pipFile = fs.readFileSync(filePath, 'utf8')
7
+
8
+ const matcherObj = { '"': '' }
9
+ const sequencer = ['"']
10
+ const parsedPipfile = multiReplace(pipFile, matcherObj, sequencer)
11
+
12
+ const pythonArray = parsedPipfile.split('\n')
13
+
14
+ return pythonArray.filter(element => element !== '' && !element.includes('#'))
15
+ }
16
+
17
+ const readAndParseLockFile = file => {
18
+ const filePath = filePathForWindows(file + '/Pipfile.lock')
19
+ const lockFile = fs.readFileSync(filePath, 'utf8')
20
+ let parsedPipLock = JSON.parse(lockFile)
21
+ parsedPipLock['defaults'] = parsedPipLock['default']
22
+ delete parsedPipLock['default']
23
+ return parsedPipLock
24
+ }
25
+
26
+ const getPythonDeps = config => {
27
+ try {
28
+ const parseProject = readAndParseProjectFile(config.file)
29
+ const parsePip = readAndParseLockFile(config.file)
30
+
31
+ return { pipfileLock: parsePip, pipfilDependanceies: parseProject }
32
+ } catch (err) {
33
+ console.log(err.message.toString())
34
+ process.exit(1)
35
+ }
36
+ }
37
+
38
+ const filePathForWindows = path => {
39
+ if (process.platform === 'win32') {
40
+ path = path.replace(/\//g, '\\')
41
+ }
42
+ return path
43
+ }
44
+
45
+ module.exports = {
46
+ getPythonDeps,
47
+ readAndParseProjectFile,
48
+ readAndParseLockFile
49
+ }
@@ -0,0 +1,11 @@
1
+ const { createPythonTSMessage } = require('../common/formatMessage')
2
+ const { getPythonDeps } = require('./analysis')
3
+
4
+ const pythonAnalysis = (config, languageFiles) => {
5
+ const pythonDeps = getPythonDeps(config, languageFiles.PYTHON)
6
+ return createPythonTSMessage(pythonDeps)
7
+ }
8
+
9
+ module.exports = {
10
+ pythonAnalysis
11
+ }
@@ -0,0 +1,282 @@
1
+ const fs = require('fs')
2
+
3
+ const readAndParseGemfile = file => {
4
+ const fileName = filePathForWindows(file + '/Gemfile')
5
+ const gemFile = fs.readFileSync(fileName, 'utf8')
6
+ const rubyArray = gemFile.split('\n')
7
+
8
+ let filteredRubyDep = rubyArray.filter(element => {
9
+ return (
10
+ !element.includes('#') &&
11
+ element.includes('gem') &&
12
+ !element.includes('source')
13
+ )
14
+ })
15
+
16
+ for (let i = 0; i < filteredRubyDep.length; i++) {
17
+ filteredRubyDep[i] = filteredRubyDep[i].trim()
18
+ }
19
+
20
+ return filteredRubyDep
21
+ }
22
+
23
+ const readAndParseGemLockFile = file => {
24
+ const fileName = filePathForWindows(file + '/Gemfile.lock')
25
+ const lockFile = fs.readFileSync(fileName, 'utf8')
26
+ const dependencyRegEx = /^\s*([A-Za-z0-9.!@#$%\-^&*_+]*)\s*(\((.*?)\))/
27
+
28
+ const lines = lockFile.split('\n')
29
+
30
+ return {
31
+ dependencies: getDirectDependencies(lines, dependencyRegEx),
32
+ runtimeDetails: getLockFileRuntimeInfo(lines),
33
+ sources: getSourceArray(lines, dependencyRegEx)
34
+ }
35
+ }
36
+
37
+ const nonDependencyKeys = (line, sourceObject) => {
38
+ const GEMFILE_KEY_VALUE = /^\s*([^:(]*)\s*\:*\s*(.*)/
39
+ let parts = GEMFILE_KEY_VALUE.exec(line)
40
+ let key = parts[1].trim()
41
+ let value = parts[2] || ''
42
+
43
+ sourceObject[key] = value
44
+ return sourceObject
45
+ }
46
+
47
+ const populateResolveAndPlatform = (version, sourceObject) => {
48
+ const depArr = version.split('-')
49
+ sourceObject.resolved = depArr[0]
50
+ sourceObject.platform = depArr.length > 1 ? depArr[1] : 'UNSPECIFIED'
51
+ return sourceObject
52
+ }
53
+
54
+ const isUpperCase = str => {
55
+ return str === str.toUpperCase()
56
+ }
57
+
58
+ const getDirectDependencies = (lines, dependencyRegEx) => {
59
+ const dependencies = {}
60
+
61
+ let depIndex = 0
62
+ for (let i = 0; i < lines.length; i++) {
63
+ if (lines[i] === 'DEPENDENCIES') {
64
+ depIndex = i
65
+ }
66
+ }
67
+ const getDepArray = lines.slice(depIndex)
68
+
69
+ for (let j = 1; j < getDepArray.length; j++) {
70
+ const element = getDepArray[j]
71
+ if (!isUpperCase(element)) {
72
+ const isDependencyWithVersion = dependencyRegEx.test(element)
73
+ if (isDependencyWithVersion) {
74
+ const dependency = dependencyRegEx.exec(element)
75
+ let name = dependency[1]
76
+ name = name.replace('!', '')
77
+ dependencies[name.trim()] = dependency[3]
78
+ } else {
79
+ let name = element
80
+ name = name.replace('!', ' ')
81
+ dependencies[name.trim()] = 'UNSPECIFIED'
82
+ }
83
+ }
84
+ }
85
+
86
+ return dependencies
87
+ }
88
+
89
+ const getLockFileRuntimeInfo = lines => {
90
+ let rubVersionIndex = 0
91
+ for (let i = 0; i < lines.length; i++) {
92
+ if (lines[i] === 'RUBY VERSION') {
93
+ rubVersionIndex = i
94
+ break
95
+ }
96
+ }
97
+
98
+ const runtimeDetails = {}
99
+ if (rubVersionIndex !== 0) {
100
+ const getRubyVersionArray = lines.slice(rubVersionIndex)
101
+
102
+ for (let element of getRubyVersionArray) {
103
+ if (!isUpperCase(element)) {
104
+ runtimeDetails['version'] = getVersion(element)
105
+ runtimeDetails['patchLevel'] = getPatchLevel(element)
106
+
107
+ if (element.includes('engine')) {
108
+ let splitElement = element.split(' ')
109
+ runtimeDetails[splitElement[0]] = splitElement[1]
110
+ }
111
+ }
112
+ }
113
+ }
114
+ return runtimeDetails
115
+ }
116
+
117
+ const getVersion = element => {
118
+ const versionRegex = /^([ruby\s0-9.*]+)/
119
+ if (versionRegex.test(element)) {
120
+ let version = versionRegex.exec(element)[0]
121
+
122
+ if (version.includes('ruby')) {
123
+ return trimWhiteSpace(version.replace('ruby', ''))
124
+ }
125
+ }
126
+ }
127
+
128
+ const getPatchLevel = element => {
129
+ const patchLevelRegex = /(p\d+)/
130
+ if (patchLevelRegex.test(element)) {
131
+ return patchLevelRegex.exec(element)[0]
132
+ }
133
+ }
134
+
135
+ const formatSourceArr = sourceArr => {
136
+ return sourceArr.map(element => {
137
+ if (element.sourceType === 'GIT') {
138
+ delete element.specs
139
+ }
140
+
141
+ if (element.sourceType === 'GEM') {
142
+ delete element.branch
143
+ delete element.revision
144
+ delete element.depthLevel
145
+ delete element.specs
146
+ }
147
+
148
+ if (element.sourceType === 'PATH') {
149
+ delete element.branch
150
+ delete element.revision
151
+ delete element.depthLevel
152
+ delete element.specs
153
+ delete element.platform
154
+ }
155
+ return element
156
+ })
157
+ }
158
+
159
+ const getSourceArray = (lines, dependencyRegEx) => {
160
+ const sourceObject = {
161
+ dependencies: {}
162
+ }
163
+
164
+ const whitespaceRegx = /^(\s*)/
165
+ let index = 0
166
+
167
+ let line = 0
168
+ const sources = []
169
+ while ((line = lines[index++]) !== undefined) {
170
+ let currentWS = whitespaceRegx.exec(line)[1].length
171
+ if (!line.includes(' bundler (')) {
172
+ if (currentWS === 0 && !line.includes(':') && line !== '') {
173
+ sourceObject.sourceType = line
174
+ }
175
+
176
+ if (currentWS !== 0 && line.includes(':')) {
177
+ nonDependencyKeys(line, sourceObject)
178
+ }
179
+
180
+ if (currentWS > 2) {
181
+ let nexlineWS = whitespaceRegx.exec(lines[index])[1].length
182
+ sourceObject.dependencies = buildSourceDependencyWithVersion(
183
+ whitespaceRegx,
184
+ dependencyRegEx,
185
+ line,
186
+ currentWS,
187
+ sourceObject.name,
188
+ sourceObject.dependencies
189
+ )
190
+
191
+ if (currentWS === 4 && sourceObject.depthLevel === undefined) {
192
+ const dependency = dependencyRegEx.exec(line)
193
+ sourceObject.name = dependency[1]
194
+ sourceObject.depthLevel = currentWS
195
+ populateResolveAndPlatform(dependency[3], sourceObject)
196
+ }
197
+
198
+ if (currentWS === 4 && sourceObject.depthLevel) {
199
+ // create new Parent
200
+ const dependency = dependencyRegEx.exec(line)
201
+ sourceObject.name = dependency[1]
202
+ sourceObject.depthLevel = currentWS
203
+ populateResolveAndPlatform(dependency[3], sourceObject)
204
+ }
205
+
206
+ if (
207
+ (currentWS === 4 && nexlineWS === 4) ||
208
+ (currentWS === 6 && nexlineWS === 4) ||
209
+ nexlineWS == ''
210
+ ) {
211
+ let newObj = {}
212
+ newObj = JSON.parse(JSON.stringify(sourceObject))
213
+ sources.push(newObj)
214
+ sourceObject.dependencies = {}
215
+ }
216
+ }
217
+ }
218
+ }
219
+ return formatSourceArr(sources)
220
+ }
221
+
222
+ const buildSourceDependencyWithVersion = (
223
+ whitespaceRegx,
224
+ dependencyRegEx,
225
+ line,
226
+ currentWhiteSpace,
227
+ name,
228
+ dependencies
229
+ ) => {
230
+ const isDependencyWithVersion = dependencyRegEx.test(line)
231
+
232
+ if (currentWhiteSpace === 6) {
233
+ const dependency = dependencyRegEx.exec(line)
234
+ if (isDependencyWithVersion) {
235
+ if (name !== dependency[1]) {
236
+ dependencies[dependency[1]] = dependency[3]
237
+ }
238
+ } else {
239
+ dependencies[line.trim()] = 'UNSPECIFIED'
240
+ }
241
+ }
242
+
243
+ return dependencies
244
+ }
245
+
246
+ const getRubyDeps = config => {
247
+ try {
248
+ const parsedGem = readAndParseGemfile(config.file)
249
+ const parsedLock = readAndParseGemLockFile(config.file)
250
+
251
+ return { gemfilesDependanceies: parsedGem, gemfileLock: parsedLock }
252
+ } catch (err) {
253
+ console.log(err.message)
254
+ process.exit(1)
255
+ }
256
+ }
257
+
258
+ const trimWhiteSpace = string => {
259
+ return string.replace(/\s+/g, '')
260
+ }
261
+
262
+ const filePathForWindows = path => {
263
+ if (process.platform === 'win32') {
264
+ path = path.replace(/\//g, '\\')
265
+ }
266
+ return path
267
+ }
268
+
269
+ module.exports = {
270
+ getRubyDeps,
271
+ readAndParseGemfile,
272
+ readAndParseGemLockFile,
273
+ nonDependencyKeys,
274
+ populateResolveAndPlatform,
275
+ isUpperCase,
276
+ getDirectDependencies,
277
+ getLockFileRuntimeInfo,
278
+ getVersion,
279
+ getPatchLevel,
280
+ formatSourceArr,
281
+ getSourceArray
282
+ }
@@ -0,0 +1,11 @@
1
+ const analysis = require('./analysis')
2
+ const { createRubyTSMessage } = require('../common/formatMessage')
3
+
4
+ const rubyAnalysis = (config, languageFiles) => {
5
+ const rubyDeps = analysis.getRubyDeps(config, languageFiles.RUBY)
6
+ return createRubyTSMessage(rubyDeps)
7
+ }
8
+
9
+ module.exports = {
10
+ rubyAnalysis
11
+ }
@@ -14,6 +14,11 @@ const autoDetectFileAndLanguage = async configToUse => {
14
14
  process.exit(1)
15
15
  }
16
16
 
17
+ if (fileFinder.fileIsEmpty(entries[0])) {
18
+ console.log(i18n.__('scanFileIsEmpty'))
19
+ process.exit(1)
20
+ }
21
+
17
22
  configToUse.file = entries[0]
18
23
  if (configToUse.name === undefined) {
19
24
  configToUse.name = entries[0]
@@ -38,19 +43,18 @@ const autoDetectAuditFilesAndLanguages = async () => {
38
43
  return languagesFound
39
44
  } else {
40
45
  console.log(
41
- 'found multiple languages, please specify one using --file to run SCA analysis'
46
+ 'found multiple languages, please specify one using --file to run SCA audit'
42
47
  )
43
48
  }
44
49
  }
45
50
 
46
- const manualDetectAuditFilesAndLanguages = async projectPath => {
47
- let projectRootFilenames = await rootFile.getProjectRootFilenames(projectPath)
48
- let identifiedLanguages = languageResolver.deduceLanguageScaAnalysis(
49
- projectRootFilenames
50
- )
51
+ const manualDetectAuditFilesAndLanguages = file => {
52
+ let projectRootFilenames = rootFile.getProjectRootFilenames(file)
53
+ let identifiedLanguages =
54
+ languageResolver.deduceLanguageScaAnalysis(projectRootFilenames)
51
55
 
52
56
  if (Object.keys(identifiedLanguages).length === 0) {
53
- console.log(i18n.__('languageAnalysisNoLanguage', projectPath))
57
+ console.log(i18n.__('languageAnalysisNoLanguage', file))
54
58
  return []
55
59
  }
56
60
  return [identifiedLanguages]
@@ -22,14 +22,14 @@ const findFilesJava = async languagesFound => {
22
22
  )
23
23
 
24
24
  if (result.length > 0) {
25
- return languagesFound.push({ java: result })
25
+ return languagesFound.push({ JAVA: result })
26
26
  }
27
27
  return languagesFound
28
28
  }
29
29
 
30
30
  const findFilesJavascript = async languagesFound => {
31
31
  const result = await fg(
32
- ['**/package.json', '**/yarn.lock', '**/package.lock.json'],
32
+ ['**/package.json', '**/yarn.lock', '**/package-lock.json'],
33
33
  {
34
34
  dot: false,
35
35
  deep: 1,
@@ -38,7 +38,7 @@ const findFilesJavascript = async languagesFound => {
38
38
  )
39
39
 
40
40
  if (result.length > 0) {
41
- return languagesFound.push({ javascript: result })
41
+ return languagesFound.push({ JAVASCRIPT: result })
42
42
  }
43
43
  return languagesFound
44
44
  }
@@ -51,7 +51,7 @@ const findFilesPython = async languagesFound => {
51
51
  })
52
52
 
53
53
  if (result.length > 0) {
54
- return languagesFound.push({ python: result })
54
+ return languagesFound.push({ PYTHON: result })
55
55
  }
56
56
  return languagesFound
57
57
  }
@@ -64,7 +64,7 @@ const findFilesGo = async languagesFound => {
64
64
  })
65
65
 
66
66
  if (result.length > 0) {
67
- return languagesFound.push({ go: result })
67
+ return languagesFound.push({ GO: result })
68
68
  }
69
69
  return languagesFound
70
70
  }
@@ -77,7 +77,7 @@ const findFilesRuby = async languagesFound => {
77
77
  })
78
78
 
79
79
  if (result.length > 0) {
80
- return languagesFound.push({ ruby: result })
80
+ return languagesFound.push({ RUBY: result })
81
81
  }
82
82
  return languagesFound
83
83
  }
@@ -90,7 +90,7 @@ const findFilesPhp = async languagesFound => {
90
90
  })
91
91
 
92
92
  if (result.length > 0) {
93
- return languagesFound.push({ php: result })
93
+ return languagesFound.push({ PHP: result })
94
94
  }
95
95
  return languagesFound
96
96
  }
@@ -110,6 +110,24 @@ const fileExists = path => {
110
110
  return fs.existsSync(path)
111
111
  }
112
112
 
113
+ const fileIsEmpty = path => {
114
+ if (fileExists(path) && checkFilePermissions(path)) {
115
+ try {
116
+ return fs.readFileSync(path).length === 0
117
+ } catch (e) {
118
+ if (
119
+ e.message.toString().includes('illegal operation on a directory, read')
120
+ ) {
121
+ console.log('file provided cannot be a directory')
122
+ } else {
123
+ console.log(e.message.toString())
124
+ }
125
+ process.exit(0)
126
+ }
127
+ }
128
+ return false
129
+ }
130
+
113
131
  module.exports = {
114
132
  findFile,
115
133
  fileExists,
@@ -119,5 +137,6 @@ module.exports = {
119
137
  findFilesPython,
120
138
  findFilesGo,
121
139
  findFilesPhp,
122
- findFilesRuby
140
+ findFilesRuby,
141
+ fileIsEmpty
123
142
  }